概率图模型
一、马尔科夫链特性
在已知系统当前状态的条件下,他未来的演变不依赖于过去的演变。第T+1次的结果只受第T次结果的影响,即只与当前状态有关,而与系统的初始状态和此次转移前的所有状态无关。(无后效性)
马尔科夫的一步转移概率可以定义为:
Pij(n) = P{Xn+1=j|Xn=i}
一步转移矩阵定义:转移概率Pij所组成的矩阵。
马尔科夫链的发现反映了诸多系统的普遍规律,例如在编码领域,我们熟悉的LZMA(文件名为.7z)数据压缩算法就使用了马尔科夫链;在生物世界中,生物种群的数量变化也就是一个马尔科夫的过程;物理学的扩散现象就是轨道连续的马尔科夫过程等。而马尔科夫过程与我们生活最接近的一类应用是在天气预报方面。
二、概率图模型
概率图模型就是为了解决复杂性和非确定性问题推理而产生的学科,是概率论和图论的结合。
概率图模型是由节点和弧构成的图,其中节点表示随机变量,而弧表示条件独立性的假设。根据弧是否有方向,可分为有向和无向两种。其中无向图被统称为马尔科夫网,有向图模型被统称为贝叶斯网。
贝叶斯网的推理简介:
1、 后验概率问题
2、 最大后验假设问题(MAP)
在已知证据E=e,有时会对一些变量的后验概率最大的状态组合感兴趣,这些变量称为假设变量,记之为H。H的一个状态组合称为一个假设,记为h。在所有可能的假设中,找出后验概率最大的那个假设h*,即:
h* = argmaxP(H=h|E=e)
3、 最大可能解释问题(MPE)
在贝叶斯网中,证据E=e的一个解释指的是网络中全部变量的一个与E=e相一致的状态组合。有时往往最关心概率最大的那个解释,即最大可能概率,简称MPE。求MPE问题可视为MAP问题的一个特例,即MAP中的假设变量H包含了网络中所有的非证据变量。
三、隐马尔科夫模型(Hidden Markov Model)
隐马尔科夫模型是马尔科夫链的一种延伸,其难点是底层马尔科夫链的状态空间(雨天,阴天,晴天——一个预测值)不能被直接观察到,但能观察到一个显式的观测序列(潮湿,湿润,干燥,干旱——一个观测值),该观测向量与底层马尔科夫链的状态空间可通过一定的概率分布表现出来。因此,隐马尔科夫模型是一个双重随机过程——具有一定状态数的隐马尔科夫链和可观察向量的随机函数集。
以天气预报为例。将天气定义为雨天,阴天,晴天三种,长期的经验提供天气状态的转移概率矩阵。目标仍然是预测天气,但限制条件是不能直接观察天气的状态,需要通过一个与天气状态相关的显示状态预估。这个显示状态(可观察的)是空气湿润程度:潮湿,湿润,干燥,干旱四种。为此,我们需要建立一个隐马尔科夫模型(HMM),该模型包含两组状态集合和三组改路集合:
1)隐状态:系统的(真实)状态序列,可以由马尔科夫过程进行描述,例如:雨天,阴天,晴天。
2)观察状态:在这个过程中显示状态序列(例如空气的湿度)。
3)状态转移矩阵:是隐状态空间,即马尔科夫状态空间的状态转移矩阵。
4)混淆矩阵:也称发射概率,包含了每个给定的观察状态转换到每个隐藏状态的概率矩阵。
5)初始化概率向量:从一个观察状态到每个隐状态的概率向量(初始概率),表示为初始时刻观察状态转换到隐状态的概率。例如:一年中晴天,阴天,雨天的概率。
四、HMM推理与前向算法
继续使用天气预报的例子,用来解释HMM并不恰当。假设预测天气的人住在山洞里,无法直接观察天气的变化,但他有一个湿度计,可以读出每天的湿度。由于多年的观察,他还有关于干湿度的观测数据,他知道一年中晴天,雨天,阴天的总比例,也就是初始化向量,还知道每种天气之间的转移概率,以及每类干湿度对应天气的发射概率。假设他观察到连续三天的显式状态为(干旱,干燥,潮湿),那么他想预测这三天的天气状况:隐状态序列。很显然,这是一个最大后验假设问题。
from numpy import *
import numpy as np
startP = mat([0.63,0.17,0.20]) #起始概率
#状态转移概率
stateP = mat([[0.5,0.25,0.25],[0.375,0.125,0.375],[0.125,0.675,0.375]])
emitP = mat([[0.6,0.20,0.05],[0.25,0.25,0.25],[0.05,0.10,0.05]]) #发射(混合)概率
state1Emit = multiply(startP,emitP[:,0].T) #计算概率,第一天的
print("argmax:",np.argmax(state1Emit))
print(shape(emitP[:,0].T))
#计算第二天干燥下的概率
state2Emit = stateP * state1Emit.T
state2Emit = multiply(state2Emit,emitP[:,1])
print(state2Emit)
print("argmax:",np.argmax(state2Emit))
#计算第三天潮湿下的概率
state3Emit = stateP*state2Emit
state3Emit = multiply(state3Emit,emitP[:,2])
print(state3Emit)
print("argmax:",np.argmax(state3Emit))
很显然,随着矩阵规模的逐步增大,算法的计算量是灾难性的。下面思考如何简化计算过程。
五、Vertibi算法原理
我们发现HMM的计算结果呈现以下规律性:
1) 最优路径是由网络中概率最大的节点构成的一条路径;
2) 初始状态矩阵和t0时刻的转移概率决定了第一天天气状态的所有概率。但是,对后续各天气状态产生决定影响的只有最大概率下的天气状态;
3) 之后每一天都是如此,t+1时刻的概率同时受到t时刻的转移概率和当天的显状态的影响。但是只有最大概率下的天气状态才会对后续状态产生决定性的影响。
Vertibi算法实现:
from numpy import *
def vertibi(obs,states,start_p,trans_p,emit_p):
"""
:param obs: 观察序列
:param states:隐状态
:param start_p:初始概率(隐状态)
:param trans_p:转移概率(隐状态)
:param emit_p:发射概率(显状态表现为隐状态的概率)
:return:
"""
V = [{}] #路径概率表 V[时间][隐状态]=概率
for y in states: #初始化初始状态(t== 0)
V[0][y] = start_p[y]*emit_p[y][obs[0]]
for t in range(1,len(obs)): #对t>0 跑一遍维特比算法
V.append({})
for y in states:
#概率 隐状态 = 前状态是y0的概率 * y0转移到y的概率 * y表现为当前状态的概率
V[t][y] = max([(V[t-1][y0] * trans_p[y0][y] * emit_p[y][obs[t]]) for y0 in states])
for i in range(0,len(obs)):
Vi = sorted(V[i].items(), key=lambda v: v[1], reverse=True) # 按照value的值从大到小排序
print(Vi)
states = ('sunny','cloudy','rainy')
obs = ('dry','dryish','soggy')
start_p = {'sunny':0.63,'cloudy':0.17,'rainy':0.20}
trans_p ={
'sunny':{'sunny':0.5,'cloudy':0.375,'rainy':0.125},
'cloudy':{'sunny':0.25,'cloudy':0.125,'rainy':0.625},
'rainy':{'sunny':0.25,'cloudy':0.375,'rainy':0.375}
}
emit_p = {
'sunny':{'dry':0.60,'dryish':0.20,'soggy':0.05},
'cloudy':{'dry':0.25,'dryish':0.25,'soggy':0.25},
'rainy':{'dry':0.05,'dryish':0.10,'soggy':0.375}
}
vertibi(obs,states,start_p,trans_p,emit_p)
输出结果为:
[('sunny', 0.378), ('cloudy', 0.0425), ('rainy', 0.010000000000000002)]
[('sunny', 0.0378), ('cloudy', 0.0354375), ('rainy', 0.004725)]
[('rainy', 0.008305664062499999), ('cloudy', 0.00354375), ('sunny', 0.0009450000000000001)]