隐马尔可夫模型

隐马尔可夫模型(Hidden Markov Model,HMM)是描述两个时序序列联合分布p(x,y)的概率模型。

x序列外界可见(外界指的是观测者),称为观测序列( observation sequence ) ; y序列外界不可见,称为状态序列( state sequence )。

隐马尔可夫模型之所以称为“马尔可夫模型”,是因为它满足马尔可夫假设。

马尔可夫假设:每个事件的发生概率只取决于前一个事件。


② 任意时刻观测xt只依赖于该时刻的yt,于其他时刻的状态和观测无关![](https://voluntexi.github.io//postimages/1658380756706.png)为什么x可以决定y呢?因为在概率论中:联合概率分布p(x,y)\\ ②\ 任意时刻观测x_t只依赖于该时刻的y_t,于其他时刻的状态和观测无关 ![](https://voluntexi.github.io//post-images/1658380756706.png) 为什么x可以决定y呢?因为在概率论中:联合概率分布p(x,y)中\\

隐马尔可夫模型利用了三个要素来模拟时序序列的发生,分别为初始状态概率向量、状态转移概率矩阵和发射概率矩阵(观测概率矩阵)

初始状态概率向量

通过p(y1π)表示,其中:π称之为初始状态概率向量通过p(y_1|\pi)表示,其中:\\ \pi称之为初始状态概率向量

P(B) = 0.7\ P(M) = 0\ P(E) = 0\ P(S) = 0.3

p(y_1=B)=0.7\
p(y_1=M)=0\
p(y_1=E)=0\
p(y_1=S)=0.3\
此时的隐马尔可夫模型的初始状态概率向量为:[0.7,0,0,0.3]

### 状态转移概率矩阵 状态转移概率矩阵的确定过程: 在确定了y_t后根据马尔可夫假设,可以将y_t转移到y_{t+1}。因为y_t一共有N种假设状态,\\

p(yt+1=Syt=B)=0就可以模拟这种禁止转移的需求。减少p(yt+1=Myt=M)来模拟该语言现象。同样,词性标注中的“形容词名词”“副词动词”也可以通过状态转移概率来模拟。p(y_{t+1}=S|y_t=B)=0就可以模拟这种禁止转移的需求。\\ 减少p(y_{t+1}=M|y_t=M)来模拟该语言现象。\\同样,词性标注中的“形容词→名词”“副词→动词”也可以通过状态转移概率来模拟。\\

发射概率矩阵

有了状态y之后那么怎么确定对应的观测x的概率分布呢?

这时根据隐马尔可夫假设②任意时刻观测x只依赖于该时刻的y,于其他时刻的状态和观测无关。若观测x一共有M种可能,那么x的概率分布参数向量的维度为M。由于y一共有N种,那么这些参数构成了N*M矩阵(size(状态) * size(x)),成为发射概率矩阵B。

p(x1=y1=B)对应为矩阵中左上角的第一个元素。若字符集的大小为1000,那么size(B)=41000p(x_1=阿|y_1=B)对应为矩阵中左上角的第一个元素。\\若字符集的大小为1000,那么size(B)=4*1000\\

初始状态概率向量、状态转移概率矩阵与发射概率矩阵成为隐马尔可夫模型的三元组。三元组确定后,隐马尔可夫模型就确定了。

隐马尔可夫模型的三个基本用法

  • 样本生成问题:给定模型三元组,生成满足模型约束的样本。
  • 模型训练问题:给定训练集,估计模型三元组参数
  • 序列预测问题:已知模型三元组参数,给定观测序列x,求最可能的状态y

样本生成问题实例

设想如下案例:

某医院招标开发“智能”医疗诊断系统,用来辅助感冒诊断。

  • ①来诊者只有两种状态:要么健康,要么发烧。
  • ②来诊者不确定自己到底是哪种状态,只能回答感觉头晕、体寒或正常。
  • ③感冒这种病,只跟病人前一天的状态有关。
  • ④当天的病情决定当天的身体感觉。

有位来诊者的病历卡上完整地记录了最近T天的身体感受(头晕、体寒或正常),请预测这T天的身体状态(健康或发烧)。

由于医疗数据属于机密隐私,医院无法提供训练数据,但根据医生经验,感冒发病的规律如图所示。

也就是说,在初始状态下有0.4的概率第二天发烧,然后有0.1的概率正常。

我们可以写出隐马尔可夫模型:

初始概率向量π

【0.6,0.4】

状态转移概率矩阵A

0.7 0.3
0.4 0.6

发射概率矩阵B

0.5 0.4 0.1
0.1 0.3 0.6

样本生成:

生成过程就是沿着隐马尔可夫链走T步。

代码:

import random
pi=[0.6,0.4]
y=['健康','发烧']
x=['头晕','体寒','正常']
A=[[0.7,0.3],
   [0.4,0.6]]
B=[[0.5,0.4,0.1],
   [0.1,0.3,0.6]]
size=4
def generateHMM(status,size):
    symList=[0 for i in range(size)]
    symList[0]=x[status]
    initSym=0 if random.random()<=pi[0] else 1
    for i in range(1,size):
        symList[i],initSym=continueGen(initSym,i)
    print(symList)
def continueGen(now,i):
    if i==size-1:
        return y[now],0
    else:
        flag=random.random()
        genx= 1 if flag>=A[now][0] else 0#下一代的病情
        flag=random.random()
        if flag<=B[now][0]:
            return str(y[now]+" "+x[0]),genx
        elif flag<=(B[now][1]+B[now][0]):
            return str(y[now]+" "+x[1]),genx
        else:
            return str(y[now]+" "+x[2]),genx
generateHMM(0,4)
generateHMM(1,4)
generateHMM(2,4)

输出如下:

['头晕', '发烧 正常', '健康 体寒', '健康']
['体寒', '发烧 正常', '发烧 正常', '发烧']
['正常', '健康 头晕', '发烧 正常', '发烧']

由于随机数的原因,每次运行的结果都是随机的。

模型训练问题实例

通过上述样本来进行监督学习来估计模型参数。

在监督学习中,通过利用极大似然法来估计隐马尔科夫模型的参数。

初始状态概率向量的估计:

统计y1的所有取值的频次记作向量c,然后用类似的方法归一化:统计y_1的所有取值的频次记作向量c,然后用类似的方法归一化:\\

转移概率矩阵的估计:

根据极大似然估计进行归一化:根据极大似然估计进行归一化:\\

发射概率矩阵的估计:

b^ij=Bi,jJ=1MBi,J , i=1,2,...N,j=1,2...,M\hat{b}_{ij}=\frac{B_{i,j}}{\sum_{J=1}^{M}B_{i,J}}\ ,\ i=1,2,...N,j=1,2...,M

p(y_1=S_i)=\pi_i\ …①

p(y_t=S_j|y_{t-1}=s_i)=A_{i,j}\ …②

p(y)=p(y_1,…,y_T)=p(y_1)\prod_{t=2}^{T}p(y_t|y_{t-1})

p(x_t=O_j|y_t=s_i)=B_{i,j}\ …③

p(x|y)=\prod_{t=1}^{T}p(x_t|y_{t})\ …④

p(x,y)=p(y_1)\prod_{t=2}^{T}p(y_t|y_{t-1})\prod_{t=1}^{T}p(x_t|y_{t})

首先求:\
P(晴天,干燥)=\pi(晴天)B(晴天,干燥)=0.32
\p(阴天,干燥)=\pi(阴天)B(阴天,干燥)=0.18\
p(雨天,干燥)=\pi(雨天)B(雨天,干燥)=0.09\
接下来求:\P(潮湿,晴天|T_1=干燥)=(0.32
0.4+0.18
0.3
0.090.1)0.2=0.382\
P(潮湿,阴天|T_1=干燥)=(0.32
0.5+0.18
0.4+0.090.5)0.4=0.1108\
P(潮湿,雨天|T_1=干燥)=(0.32
0.1+0.18
0.3+0.09*0.4)*0.7=0.0854
\依此类推:\
P(干燥,晴天|T_1=干燥,T_2=潮湿)=0.0456\

P=0.0456+0.0637+0.0214=0.1307

#### 维特比算法 在构成了图后,接下来使用维特比算法寻找最优的状态序列: ![img](https://pic3.zhimg.com/80/v2-456e477e800815414ecf5092b563f7ae_720w.jpg) 在上面的表格例子中: ![在这里插入图片描述](https://img-blog.csdnimg.cn/20201224204246152.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3FxXzQzMzkxNDE0,size_16,color_FFFFFF,t_70) ## HMM应用于中文分词 大体步骤为: * 用{B,M,E,S}进行标注 * 使用HMM训练 在hanlp中已经实现了HMM分词器,因此可以直接使用API进行调用: ```python FirstOrderHiddenMarkovModel = JClass('com.hankcs.hanlp.model.hmm.FirstOrderHiddenMarkovModel') def train(model): segmenter.train('./msr_training.utf8') return segmenter.toSegment() segment = train(msr_train, FirstOrderHiddenMarkovModel()) [商品, 和, 服务]#output 2. 计算转移概率矩阵 4. 使用 Viterbi 算法解码 如果没有标注语料,则问题的解决过程: 1. 获取词的个数 3. 参数学习(利用 EM 迭代算法获取初始状态概率、状态转移概率和输出概率)