大家好,我是Sonhhxg_柒,希望你看完之后,能对你有所帮助,不足请指正!共同学习交流
个人主页-Sonhhxg_柒的博客_CSDN博客
欢迎各位→点赞 + 收藏⭐️ + 留言
系列专栏 - 机器学习【ML】 自然语言处理【NLP】 深度学习【DL】
foreword
✔说明⇢本人讲解主要包括Python、机器学习(ML)、深度学习(DL)、自然语言处理(NLP)等内容。
如果你对这个系列感兴趣的话,可以关注订阅哟
文章目录
一、基础信息 介绍篇
1.1 什么是概率图模型?
1.2 什么是 随机场?
二、马尔可夫过程 介绍篇
2.1 什么是 马尔可夫过程?
2.2 马尔可夫过程 的核心思想 是什么?
三、隐马尔科夫算法 篇
3.1 隐马尔科夫算法 介绍篇
3.2 隐马尔科夫算法 模型计算过程篇
3.3 HMM模型三个基本问题的联系?
3.4 隐马尔科夫算法 问题篇
四、最大熵马尔科夫模型(MEMM)篇
4.1 最大熵马尔科夫模型(MEMM)动机篇
4.2 最大熵马尔科夫模型(MEMM)介绍篇
4.3 最大熵马尔科夫模型(MEMM)问题篇
五、条件随机场(CRF)篇
5.1 CRF 动机篇
5.2 CRF 介绍篇
5.3 CRF 优缺点篇
5.4 CRF 复现?
六、对比篇
6.1 CRF模型 和 HMM 和 MEMM 模型 区别?
6.2 为什么 CRF模型 会比 HMM 被普遍使用?
概率图模型(Probabilistic Graphical Model, PGM),简称图模型(Graphical Model,GM),是指一种用图结构来描述多元随机变量之间条件独立性的概率模型(注意条件独立性),从而给研究高维空间的概率模型带来了很大的便捷性。
每个位置按照某种分布随机赋予一个值 所构成 的 整体。
假设一个随机过程中,tn 时刻的状态xn 的条件发布,只与其前一状态x_n-1 相关,即:
P(xn|x1,x2,...,xn−1)=P(xn|xn−1)
则将其称为 马尔可夫过程。
对于 马尔可夫过程 的 思想,用一句话去概括:当前时刻状态 仅与上一时刻状态相关,与其他时刻不相关。
可以从 马尔可夫过程 图 去理解,由于 每个状态间 是以 有向直线连接,也就是 当前时刻状态 仅与上一时刻状态相关。
3.1.1 隐马尔科夫算法 是什么?
隐马尔科夫算法是对含有未知参数(隐状态)的马尔可夫链进行建模的生成模型,如下图所示:
在隐马尔科夫模型中,包含隐状态 和 观察状态,隐状态 ii 对于观察者而言是不可见的,而观察状态 oi 对于观察者而言是可见的。隐状态间存在转移概率,隐状态 ii到对应的观察状态 oi 间存在输出概率。
3.1.3 隐马尔科夫算法 中 三个矩阵 是什么?
3.1.4 隐马尔科夫算法 中 两个假设 是什么?
3.1.5 隐马尔科夫算法 中 工作流程 是什么?
3.2.1 隐马尔科夫算法 序列概率计算过程 是什么样的?
1.思想
如何对一条序列计算其整体的概率。即目标是计算出 P(O|λ) ;
给定模型 λ=(A,B,π) 和观测序列 O=(o1,o2,...,oT) ,计算在模型 λ 下观测序列 O 出现的概率 P(O|λ)
2.常用方法
由于有隐藏的状态序列 I 的存在,我们是无法计算 P(O|λ) 的。一种常见的做法是把 I 边缘掉,即 P(O|λ)=∑(P(O,I|λ)) ,当然,这种计算复杂度非常高,为 O(TN2)
减少计算量的原因在于每一次计算直接引用前一个时刻的计算结果,避免重复计算,计算复杂度将为$O(T^2 * N)$
3.2.2 隐马尔科夫算法 学习训练过程 是什么样的?
1.思想
找出数据的分布情况,也就是模型参数的确定;
已知观测序列 O=(o1,o2,...,oT) ,估计模型 λ=(A,B,π) 参数,使得在该模型下观测序列概率 P(O|λ) 最大,即用极大似然估计的方法估计参数
2.常用方法
3.2.3 隐马尔科夫算法 序列标注(解码)过程 是什么样的?
1.思想
也就是“预测过程”,通常称为解码过程。在给定的观测序列下找出一条隐状态序列,条件是这个隐状态序列的概率是最大的那个
2.常用方法:Viterbi算法
Viterbi计算有向无环图的一条最大路径:
三个基本问题 存在 渐进关系。首先,要学会用前向算法和后向算法算观测序列出现的概率,然后用Baum-Welch算法求参数的时候,某些步骤是需要用到前向算法和后向算法的,计算得到参数后,我们就可以用来做预测了。因此可以看到,三个基本问题,它们是渐进的,对于做NLP的同学来说,应用HMM模型做解码任务应该是最终的目的。
因为HMM模型其实它简化了很多问题,做了某些很强的假设,如齐次马尔可夫性假设和观测独立性假设,做了假设的好处是,简化求解的难度,坏处是对真实情况的建模能力变弱了。
在序列标注问题中,隐状态(标注)不仅和单个观测状态相关,还和观察序列的长度、上下文等信息相关。例如词性标注问题中,一个词被标注为动词还是名词,不仅与它本身以及它前一个词的标注有关,还依赖于上下文中的其他词。
4.1.1 HMM 存在 什么问题?
HMM中,观测节点 oi 依赖隐藏状态节点 ii ,也就意味着我的观测节点只依赖当前时刻的隐藏状态。但在更多的实际场景下,观测序列是需要很多的特征来刻画的,比如说,我在做NER时,我的标注 ii 不仅跟当前状态 oi 相关,而且还跟前后标注 oj(j≠i) 相关,比如字母大小写、词性等等。
4.2.1 最大熵马尔科夫模型(MEMM) 是什么样?
通过 “定义特征” 的方式,学习条件概率:
并且, P(i|i′,o) 这个概率通过最大熵分类器建模(取名MEMM的原因):
重点来了,这是ME的内容,也是理解MEMM的关键: Z(o,i′) 这部分是归一化; fa(o,i) 是特征函数,具体点,这个函数是需要去定义的; λ 是特征函数的权重,这是个未知参数,需要从训练阶段学习而得。
定义特征函数:
其中,特征函数 fa(o,i) 的 个数 可以任意制定,(a=1,...,n)
所以总体上,MEMM的建模公式这样:
请务必注意,理解判别模型和定义特征两部分含义,这已经涉及到CRF的雏形了。
4.2.2 最大熵马尔科夫模型(MEMM) 如何解决 HMM 问题?
在前面介绍 HMM 时,HMM 提出了 观测节点 oi 依赖隐藏状态节点 ii 假设,该假设不合理的,针对该问题, MEMM 提出 观测节点 ii 依赖隐藏状态节点 oi 以及上一时刻的隐藏节点$i_{i-1}$ 假设。(HMM 和 MEMM 箭头);
1.问题简述
MEMM 容易出现标注偏置问题,MEMM倾向于选择拥有更少转移的状态。
用Viterbi算法解码MEMM,状态1倾向于转换到状态2,同时状态2倾向于保留在状态2。 解码过程细节(需要会viterbi算法这个前提):
但是得到的最优的状态转换路径是1->1->1->1,为什么呢?因为状态2可以转换的状态比状态1要多,从而使转移概率降低,即MEMM倾向于选择拥有更少转移的状态。
3.问题原因分析
对于MEMM公式:
求和的作用在概率中是归一化,但是这里归一化放在了指数内部,管这叫local归一化。 来了,viterbi求解过程,是用dp的状态转移公式(MEMM的没展开,请参考CRF下面的公式),因为是局部归一化,所以MEMM的viterbi的转移公式的第二部分出现了问题,导致dp无法正确的递归到全局的最优。
5.1.1 HMM 和 MEMM 存在什么问题?
5.2.1 什么是 CRF?
设 X 与 Y 是随机变量,P(Y|X) 是给定条件 X 的条件下 Y 的条件概率分布,若随机变量 Y 构成一个由无向图G=(V,E)表示的马尔科夫随机场。则称 条件概率分布P(X|Y)为条件随机场。
5.2.2 CRF 的 主要思想是什么?
统计全局概率,在做归一化时,考虑了数据在全局的分布。
5.2.3 CRF 的定义是什么?
给定 X=(x1,x2,...,xn) ,Y=(y_1,y_2,...,y_n) 均为线性链表示的随机变量序列,若在给随机变量序列 X 的条件下,随机变量序列 Y 的条件概率分布 P(Y|X) 构成条件随机场,即满足马尔可夫性:
则称为 P(Y|X) 为线性链条件随机场。
通过去除了隐马尔科夫算法中的观测状态相互独立假设,使算法在计算当前隐状态$x_i$时,会考虑整个观测序列,从而获得更高的表达能力,并进行全局归一化解决标注偏置问题。
5.2.4 CRF 的 三个基本问题 是什么?
5.2.4.1 概率计算问题
Z(x) 为归一化因子,是在全局范围进行归一化,枚举了整个隐状态序列$x_{1…n}$的全部可能,从而解决了局部归一化带来的标注偏置问题。
tk 为定义在边上的特征函数,转移特征,依赖于前一个和当前位置
s1 为定义在节点上的特征函数,状态特征,依赖于当前位置。
5.2.4.2 学习计算问题
5.2.4.3 预测问题
5.2.5 CRF 的 流程是什么?
5.3.1 CRF 的 优点在哪里?
5.3.2 CRF 的 缺点在哪里?
import numpy as np
class CRF(object):
'''实现条件随机场预测问题的维特比算法
'''
def __init__(self, V, VW, E, EW):
'''
:param V:是定义在节点上的特征函数,称为状态特征
:param VW:是V对应的权值
:param E:是定义在边上的特征函数,称为转移特征
:param EW:是E对应的权值
'''
self.V = V #点分布表
self.VW = VW #点权值表
self.E = E #边分布表
self.EW = EW #边权值表
self.D = [] #Delta表,最大非规范化概率的局部状态路径概率
self.P = [] #Psi表,当前状态和最优前导状态的索引表s
self.BP = [] #BestPath,最优路径
return
def Viterbi(self):
'''
条件随机场预测问题的维特比算法,此算法一定要结合CRF参数化形式对应的状态路径图来理解,更容易理解.
'''
self.D = np.full(shape=(np.shape(self.V)), fill_value=.0)
self.P = np.full(shape=(np.shape(self.V)), fill_value=.0)
for i in range(np.shape(self.V)[0]):
#初始化
if 0 == i:
self.D[i] = np.multiply(self.V[i], self.VW[i])
self.P[i] = np.array([0, 0])
print('self.V[%d]='%i, self.V[i], 'self.VW[%d]='%i, self.VW[i], 'self.D[%d]='%i, self.D[i])
print('self.P:', self.P)
pass
#递推求解布局最优状态路径
else:
for y in range(np.shape(self.V)[1]): #delta[i][y=1,2...]
for l in range(np.shape(self.V)[1]): #V[i-1][l=1,2...]
delta = 0.0
delta += self.D[i-1, l] #前导状态的最优状态路径的概率
delta += self.E[i-1][l,y]*self.EW[i-1][l,y] #前导状态到当前状体的转移概率
delta += self.V[i,y]*self.VW[i,y] #当前状态的概率
print('(x%d,y=%d)-->(x%d,y=%d):%.2f + %.2f + %.2f='%(i-1, l, i, y, \
self.D[i-1, l], \
self.E[i-1][l,y]*self.EW[i-1][l,y], \
self.V[i,y]*self.VW[i,y]), delta)
if 0 == l or delta > self.D[i, y]:
self.D[i, y] = delta
self.P[i, y] = l
print('self.D[x%d,y=%d]=%.2f\n'%(i, y, self.D[i,y]))
print('self.Delta:\n', self.D)
print('self.Psi:\n', self.P)
#返回,得到所有的最优前导状态
N = np.shape(self.V)[0]
self.BP = np.full(shape=(N,), fill_value=0.0)
t_range = -1 * np.array(sorted(-1*np.arange(N)))
for t in t_range:
if N-1 == t:#得到最优状态
self.BP[t] = np.argmax(self.D[-1])
else: #得到最优前导状态
self.BP[t] = self.P[t+1, int(self.BP[t+1])]
#最优状态路径表现在存储的是状态的下标,我们执行存储值+1转换成示例中的状态值
#也可以不用转换,只要你能理解,self.BP中存储的0是状态1就可以~~~~
self.BP += 1
print('最优状态路径为:', self.BP)
return self.BP
def CRF_manual():
S = np.array([[1,1], #X1:S(Y1=1), S(Y1=2)
[1,1], #X2:S(Y2=1), S(Y2=2)
[1,1]]) #X3:S(Y3=1), S(Y3=1)
SW = np.array([[1.0, 0.5], #X1:SW(Y1=1), SW(Y1=2)
[0.8, 0.5], #X2:SW(Y2=1), SW(Y2=2)
[0.8, 0.5]])#X3:SW(Y3=1), SW(Y3=1)
E = np.array([[[1, 1], #Edge:Y1=1--->(Y2=1, Y2=2)
[1, 0]], #Edge:Y1=2--->(Y2=1, Y2=2)
[[0, 1], #Edge:Y2=1--->(Y3=1, Y3=2)
[1, 1]]])#Edge:Y2=2--->(Y3=1, Y3=2)
EW= np.array([[[0.6, 1], #EdgeW:Y1=1--->(Y2=1, Y2=2)
[1, 0.0]], #EdgeW:Y1=2--->(Y2=1, Y2=2)
[[0.0, 1], #EdgeW:Y2=1--->(Y3=1, Y3=2)
[1, 0.2]]])#EdgeW:Y2=2--->(Y3=1, Y3=2)
crf = CRF(S, SW, E, EW)
ret = crf.Viterbi()
print('最优状态路径为:', ret)
return
if __name__=='__main__':
CRF_manual()