在马尔可夫模型中,每一个状态都是可观察的序列,是状态关于时间的随机过程,也成为可视马尔可夫模型。隐马尔科夫模型中的状态是不可见的,我们可以看到的是状态表现出来的观察值和状态的概率函数。在隐马模型中,观察值是关于状态的随机过程,而状态是关于时间的随机过程,因此隐马模型是一个双重随机过程。
什么叫状态序列与观察序列呢?举个例子:
假如,有一对男生女生异地恋,根据电影里面情节女生一般会在国外异地,男生在国内。女生每天晚上会根据天气情况(可能会影响心情吧)去干不同的事情,然后会向男生汇报,随着时间的推移会产生一个一天为间隔的时间序列。
女生活动情况受天气影响,天气暂且定为可能为:晴天、多云、阴天,女生活动暂且定为:跑步与读书。
那么,女生只会跟她男友汇报自己跑步还是读书,却不说今天天气如何,对于男友来说,这就相当于知道了观察序列(跑步与读书已经告诉),天气情况(晴天、多云、阴天)确实伴随存在,但是自己不知道。
现在,假设女友告诉男友最近四天自己分别是:跑步、读书、跑步、读书,那么男友应该这样考虑。(这里手动推算很麻烦,只手动推到两天计算)
符号约定:
- p1(...)代表第一天,p2(...)代表第二天;
- 比如:p(晴天,阴天),代表前一天晴天==》后一天阴天的概率;
这是个条件概率问题:
第一天,跑步,天气可以分为三种情况:晴天、多云、阴天;
p1(晴天跑步) = p1(晴天)*p1(跑步|晴天)
p1(多云跑步) = p1(多云)*p1(跑步|多云)
p1(阴天跑步) = p1(阴天)*p1(跑步|阴天)
那么,第一天跑步概率就是:
p1(跑步)=p1(晴天跑步)+p1(多云跑步)+p1(阴天跑步)
第二天,读书,天气可以分为三种情况:晴天、多云、阴天;
比如第一天晴天,到第二天可能转变成三种状态,即:
晴天====》》》
|---晴天
|---多云
|---阴天
女友会再根据第二天天气决定日常活动是跑步还是读书。
这样推下去,对于第二天每一种天气隐含状态(对于男友来说)都由第一天三种中可能的一种天气转换而来。
那么,第一天跑步、第二天读书概率就会由三部分加起来组成:
同时,第二天晴天也由第一天三种天气状态转变而来,故也由三部分组成:
p2(晴天读书)=p2(晴天)*p2(读书|晴天)
=【p1(晴天跑步)*(晴天,晴天)+p1(多云跑步)*(多云,晴天),p1(阴天跑步)*(阴天,晴天)】*p2(读书|晴天)
p2(多云读书)=p2(多云)*p2(读书|多云)
=【p1(晴天跑步)*(晴天,多云)+p1(多云跑步)*(多云,多云),p1(阴天跑步)*(阴天,多云)】*p2(读书|多云)
p2(阴天读书)=p2(阴天)*p2(读书|阴天)
=【p1(晴天跑步)*(晴天,阴天)+p1(多云跑步)*(多云,阴天),p1(阴天跑步)*(阴天,阴天)】*p2(读书|阴天)
最后,可得第一天跑步、第二天读书概率:
P(p1(跑步),p2(读书))=
p2(晴天读书)+p2(多云读书)+p2(阴天读书)
其实,这就是隐马尔科夫模型中的前向算法计算步骤。
那么,可以归结隐马尔科夫模型的5个组成:
(1)、模型中的状态个数N(例子中天气的三种状态);
(2)、每个状态的可以输出的不同观测值M(例子中跑步和读书);
(3)、状态转移矩阵A= {aij}(例子中aij表示从第i种天气转移到第j种天气的概率);
(4)、发射矩阵B={bj(k)},例子中表示当第j种天气时女友做第k种活动(跑步或者读书)的概率;
(5)、初始状态概率分布π = {πj}.(例子中第一天为第j种天气的概率)。
手动推演了两天,后面的就有谱了,下面通过Python实现这个问题:
女友告诉男友最近四天自己分别是:跑步、读书、跑步、读书
计算出理论上,四种观察状态的概率分别是多少:
条件是:
Python代码如下:
import numpy as np
A = np.array([[0.5,0.2,0.3],[0.3,0.5,0.2],[0.2,0.3,0.5]])
B = np.array([[0.5,0.5],[0.4,0.6],[0.7,0.3]])
π = np.array([0.2,0.4,0.4])
k = 3
a = B.T[0]*π
print('======================')
print('C语言的编码风格,比较麻烦')
print('第一天')
print(a)
b = [0,0,0]
for t in range(k):
print('第'+str(t+2)+'天')
for i in range(k):
s = 0
if(t%2 == 0):
for j in range(k):
s = s+a[j]*A[j,i]*B[i,1]
b[i] = s
else:
for j in range(k):
s = s+a[j]*A[j,i]*B[i,0]
b[i] = s
a = np.array(b)
print(a)
print('第四天读书概率为:')
print(sum(a))
print('======================')
print('Python语言线性代数运算,简单')
print('第一天')
a1 = B.T[0]*π
print(a1)
a11 = [0,0,0]
for t in range(k):
print('第'+str(t+2)+'天')
if(t%2 == 0):
for i in range(k):
a11[i] = sum(a1*A.T[i]*B.T[1][i])
else:
for i in range(k):
a11[i] = sum(a1*A.T[i]*B.T[0][i])
a1 = np.array(a11)
print(a1)
print('第四天读书概率为:')
print(sum(a1))
结果为:
=====================
C语言的编码风格,比较麻烦
第一天
[ 0.1 0.16 0.28]
第2天
[ 0.077 0.1104 0.0606]
第3天
[ 0.04187 0.035512 0.052836]
第4天
[ 0.0210779 0.02518848 0.01382442]
第四天读书概率为:
0.0600908
=====================
Python语言线性代数运算,简单
第一天
[ 0.1 0.16 0.28]
第2天
[ 0.077 0.1104 0.0606]
第3天
[ 0.04187 0.035512 0.052836]
第4天
[ 0.0210779 0.02518848 0.01382442]
第四天读书概率为:
0.0600908