作者:杨开漠、韩绘锦
本课程主要对概率图模型中采用的几个模型(随机场、马尔可夫过程、HMM、MEMM、CRF)进行介绍,为了帮助大家理解这些模型,我们将以时间轴的形式介绍各个模型,并以上一个模型所存在的问题,下一个模型如何针对该模型进行改进的方式进行讲解,为了方便大家理解,建议大家 在看这个教程时,先看一下 CRF 视频介绍,并结合着李航老师的《统计学习方法》中CRF章节进行学习。
这里举一个简单的例子:假设有Bob一天从早到晚的一系列照片,Bob想考考我们,要我们猜这一系列的每张照片对应的活动,比如: 工作的照片,吃饭的照片,唱歌的照片等等。一个比较直观的办法就是,我们找到Bob之前的日常生活的一系列照片,然后找Bob问清楚这些照片代表的活动标记,这样我们就可以用监督学习的方法来训练一个分类模型,比如逻辑回归,接着用模型去预测这一天的每张照片最可能的活动标记。
这种办法虽然是可行的,但是却忽略了一个重要的问题,就是这些照片之间的顺序其实是有很大的时间顺序关系的,而用上面的方法则会忽略这种关系。比如我们现在看到了一张Bob闭着嘴的照片,那么这张照片我们怎么标记Bob的活动呢?比较难去打标记。但是如果我们有Bob在这一张照片前一点点时间的照片的话,那么这张照片就好标记了。如果在时间序列上前一张的照片里Bob在吃饭,那么这张闭嘴的照片很有可能是在吃饭咀嚼。而如果在时间序列上前一张的照片里Bob在唱歌,那么这张闭嘴的照片很有可能是在唱歌。
为了让我们的分类器表现的更好,可以在标记数据的时候,可以考虑相邻数据的标记信息。这一点,是普通的分类器难以做到的。而这一块,也是CRF比较擅长的地方。
非常简单的,就是给一个句子中的每个单词注明词性。比如这句话:“Bob drank coffee at Starbucks”,注明每个单词的词性后是这样的:“Bob (名词) drank(动词) coffee(名词) at(介词) Starbucks(名词)”。
下面,就用条件随机场来解决这个问题。
以上面的话为例,有5个单词,我们将:(名词,动词,名词,介词,名词)作为一个标注序列,称为l,可选的标注序列有很多种,比如l还可以是这样:(名词,动词,动词,介词,名词),我们要在这么多的可选标注序列中,挑选出一个最靠谱的作为我们对这句话的标注。
怎么判断一个标注序列靠谱不靠谱呢?
就我们上面展示的两个标注序列来说,第二个显然不如第一个靠谱,因为它把第二、第三个单词都标注成了动词,动词后面接动词,这在一个句子中通常是说不通的。
假如我们给每一个标注序列打分,打分越高代表这个标注序列越靠谱,我们至少可以说,凡是标注中出现了动词后面还是动词的标注序列,要给它负分!!
上面所说的动词后面还是动词就是一个特征函数,我们可以定义一个特征函数集合,用这个特征函数集合来为一个标注序列打分,并据此选出最靠谱的标注序列。也就是说,每一个特征函数都可以用来为一个标注序列评分,把集合中所有特征函数对同一个标注序列的评分综合起来,就是这个标注序列最终的评分值。
在实际应用中,对于序列排序或序列标注(eg:词性标注(POS Tagging))就是非常适合CRF使用的地方。词性标注的目标是给出一个句子中每个词的词性(名词,动词,形容词等)。而这些词的词性往往和上下文的词的词性有关,因此,使用CRF来处理是很适合的,当然CRF不是唯一的选择,也有很多其他的词性标注方法。
每个位置按照某种分布随机赋予一个值 所构成 的 整体。
假设一个随机过程中,$t_n$ 时刻的状态$x_n$的条件发布,只与其前一状态$x_{n-1}$ 相关,即:
则将其称为 马尔可夫过程。
对于 马尔可夫过程 的 思想,用一句话去概括:当前时刻状态 仅与上一时刻状态相关,与其他时刻不相关。
可以从 马尔可夫过程 图 去理解,由于 每个状态间 是以 有向直线连接,也就是 当前时刻状态 仅与上一时刻状态相关。
隐马尔科夫算法是对含有未知参数(隐状态)的马尔可夫链进行建模的生成模型,如下图所示:
在隐马尔科夫模型中,包含隐状态 和 观察状态,隐状态
- 两序列
- 隐藏序列:隐状态
$i_i$ 对于观察者而言是不可见的 - 观测序列:$o_i$ 对于观察者而言是可见的
- 隐藏序列:隐状态
- 三矩阵
- 初始状态矩阵:每个标签的概率矩阵
- 发射状态矩阵:一个字变成每个标签的概率 $B=\left[b_{i j}\right]{N \times M}$($N$为隐藏状态集元素个数,M为观测集元素个数),其中$b{i j}=P\left(o_{t} | i_{t}\right)$,$(o_{t}$为第i个观测节点 ,$i_t$ 为第i个隐状态节点,即所谓的观测概率(发射概率);
- 状态转移级证:标签到每个标签的概率 $A=\left[a_{i j}\right]{N \times N}$ (N 表示隐藏状态集元素的个数),其中 $a{i j}=P\left(i_{t+1} | i_{t}\right)$,$i_t$ 即第i个隐状态节点,即所谓的状态转移;
- 两假设
- 假设一:输出观测值间严格独立,仅取决于对应隐状态
- 假设二:状态转移过程中,当前状态只与前一状态相关
- 假设隐状态$x_i$ 的状态满足马尔可夫过程,i时刻的状态$x_i$ 的条件分布,仅与其前一个状态$x_{i-1}$相关,即:
- 假设观测序列中各个状态仅取决于它所对应的隐状态,即:
- 隐状态节点
$i_t$ 是不能直接观测到的数据节点,$o_t$ 才是能观测到的节点,并且注意箭头的指向表示了依赖生成条件关系; -
$i_t$ 在$A$的指导下生成下一个隐状态节点$i_{t+1}$; -
$i_t$ 在$B$的指导下生成依赖于该$i_t$的观测节点$o_{t}$;
由于 为有向图,而且属于生成式模型,直接对联合概率分布建模
- 思想
找出数据的分布情况,也就是模型参数的确定;
- 常用方法
- 极大似然估计:该算法在训练数据是会 将 观测状态序列
$O$ 和 隐状态序列$I$ ; - Baum-Welch(前向后向):该算法在训练数据是只会 将 观测状态序列
$O$ ;
- 思想
也就是“预测过程”,通常称为解码过程。在给定的观测序列下找出一条隐状态序列,条件是这个隐状态序列的概率是最大的那个
- 常用方法:Viterbi算法
Viterbi计算有向无环图的一条最大路径:
- 思想
如何对一条序列计算其整体的概率。即目标是计算出
- 常用方法
- 直接计算法(穷举搜索)
- 前向算法
- 后向算法
在序列标注问题中,隐状态(标注)不仅和单个观测状态相关,还和观察序列的长度、上下文等信息相关。例如词性标注问题中,一个词被标注为动词还是名词,不仅与它本身以及它前一个词的标注有关,还依赖于上下文中的其他词。
HMM中,观测节点
通过 “定义特征” 的方式,学习条件概率:
并且,
重点来了,这是ME的内容,也是理解MEMM的关键:
定义特征函数:
其中,特征函数
所以总体上,MEMM的建模公式这样:
请务必注意,理解判别模型和定义特征两部分含义,这已经涉及到CRF的雏形了。
- 在前面介绍 HMM 时,HMM 提出了 观测节点
$o_i$ 依赖隐藏状态节点$i_i$ 假设,该假设不合理的,针对该问题, MEMM 提出 观测节点$i_i$ 依赖隐藏状态节点$o_i$ 以及上一时刻的隐藏节点$i_{i-1}$ 假设。(HMM 和 MEMM 箭头);
- 定义特征函数
$f_{a}(o,i)$ ; - 在给定的数据上,训练 MEMM 模型参数;
- 利用 MEMM 做序列标注问题或者序列求概率问题;
- 问题简述
MEMM 容易出现标注偏置问题,MEMM倾向于选择拥有更少转移的状态。
- 问题介绍
用Viterbi算法解码MEMM,状态1倾向于转换到状态2,同时状态2倾向于保留在状态2。 解码过程细节(需要会viterbi算法这个前提):
但是得到的最优的状态转换路径是1->1->1->1,为什么呢?因为状态2可以转换的状态比状态1要多,从而使转移概率降低,即MEMM倾向于选择拥有更少转移的状态。
- 问题原因分析
对于MEMM公式:
求和的作用在概率中是归一化,但是这里归一化放在了指数内部,管这叫local归一化。 来了,viterbi求解过程,是用dp的状态转移公式(MEMM的没展开,请参考CRF下面的公式),因为是局部归一化,所以MEMM的viterbi的转移公式的第二部分出现了问题,导致dp无法正确的递归到全局的最优。
给定
则称为 P(Y|X) 为线性链条件随机场。
通过去除了隐马尔科夫算法中的观测状态相互独立假设,使算法在计算当前隐状态$x_i$时,会考虑整个观测序列,从而获得更高的表达能力,并进行全局归一化解决标注偏置问题。
其中:
$Z(x)$ 为归一化因子,是在全局范围进行归一化,枚举了整个隐状态序列$x_{1…n}$的全部可能,从而解决了局部归一化带来的标注偏置问题。
$t_k$ 为定义在边上的特征函数,转移特征,依赖于前一个和当前位置
$s_1$ 为定义在节点上的特征函数,状态特征,依赖于当前位置。
因为条件随机场中同一特征在各个位置都有定义,所以可以对同一个特征在各个位置求和,将局部特征函数转化为一个全局特征函数,这样就可以将条件随机场写成权值向量和特征向量的内积形式,即条件随机场的简化形式。
将转移特征和状态特征及其权值用统一的符号表示,设有k1个转移特征,$k_2$个状态特征,$K=k_1+k_2$,记
对转移与状态特征在各个位置i求和,记作
将
转化后的条件随机场可表示为:
若
以
则,条件随机场写成内积形式为:
条件随机场包含概率计算问题、学习问题和预测问题三个问题。
- 概率计算问题:已知模型的所有参数,计算观测序列
$Y$ 出现的概率,常用方法:前向和后向算法;
- 学习问题:已知观测序列
$Y$ ,求解使得该观测序列概率最大的模型参数,包括隐状态序列、隐状态间的转移概率分布和从隐状态到观测状态的概率分布,常用方法:Baum-Wehch 算法;
- 预测问题:一直模型所有参数和观测序列
$Y$ ,计算最可能的隐状态序列$X$ ,常用算法:维特比算法。
给定条件随机场$P(Y|X)$,输入序列
$x$ 和 输出序列$y$ ;
计算条件概率
计算相应的数学期望问题;
对观测序列
对每个指标
其中,
对每个指标
所以,标注序列在位置
其中,
通过利用前向-后向向量,计算特征函数关于联合概率分布
其中:
这里主要介绍一下 BFGS 算法的思路。
输入:特征函数
输出:最优参数值
- 选定初始点 w^{(0)}, 取
$B_0$ 为正定对称矩阵,k = 0; - 计算
$g_k = g(w^(k))$ ,若$g_k = 0$ ,则停止计算,否则转 (3) ; - 利用
$B_k p_k = -g_k$ 计算$p_k$ ; - 一维搜索:求
$\lambda_k$ 使得
![路径](img/学习问题1.png)
-
设
$w^{(k+1)} = w^{(k)} + \lambda_k * p_k$ -
计算
$g_{k+1}$ = g(w^{(k+1)}),若
$g_k = 0$ , 则停止计算;否则,利用下面公式计算$B_{k+1}$ : -
令
$k=k+1$ ,转步骤(3);
对于预测问题,常用的方法是维特比算法,其思路如下:
输入:模型特征向量
输出:条件概率最大的输出序列(标记序列)$y^{}= (y_1^,y_2^,...,y_n^)$,也就是最优路径;
- 初始化
- 递推,对$i=2,3,...,n$
- 终止
- 返回路径
求得最优路径 $y^{}= (y_1^,y_2^,...,y_n^)$
利用维特比算法计算给定输入序列$x$ 对应的最优输出序列$y^*$:
- 初始化
- 递推,对$i=2,3,...,n$
- 终止
- 返回路径
求得最优路径 $y^{}= (y_1^,y_2^,...,y_n^) = (1,2,1)$
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()
-
LSTM
- 优点
- 在序列任务中,能够 capture 长远的上下文信息;
- 具有神经网络的拟合非线性的能力;
- 缺点
-
$y_t$ 与$y_{t}'$ 相互独立(point wise)- 解释:因为对于
$t$ 时刻,输出层$y_t$ 仅受隐层$h_{t}$ (包含上下文信息)和输入层$x_t$(当前输入)的影响;通过去概率最大的标注作为$y_t$,与$y_{t}'$无关;
- 解释:因为对于
-
- 数据规模大时,有优势
- 优点
-
CRF
- 优点
- 考虑的是整个句子的局部特征的线性加权组合(通过特征模版去扫描整个句子)
- 解释:CRF的模型为$p(y|x, w)$,注意这里y和x都是序列,它有点像list wise,优化的是一个序列$y = (y_1, y_2, …, y_n)$,而不是某个时刻的y_t,即找到一个概率最高的序列$y = (y_1, y_2, …, y_n)$使得$p(y_1, y_2, …, y_n| x, w)$最高,它计算的是一种联合概率,优化的是整个序列(最终目标),而不是将每个时刻的最优拼接起来,在这一点上CRF要优于LSTM。
- 考虑的是整个句子的局部特征的线性加权组合(通过特征模版去扫描整个句子)
- 缺点
- 无法考虑长远的上下文信息;
- 不具有神经网络的拟合非线性的能力;
- 数据规模小时,有优势
- 优点
-
HMM
- CRF不管是在实践还是理论上都要优于HMM,HMM模型的参数主要是“初始的状态分布”,“状态之间的概率转移矩阵”,“状态到观测的概率转移矩阵”,这些信息在CRF中都可以有,例如:在特征模版中考虑$h(y1), f(y_i-1, y_i), g(y_i, x_i)$等特征。
- CNN-CRF
- 应用:处理英文序列标注问题
- 原因:英文单词是由更细粒度的字母组成,这些字母潜藏着一些特征(例如:前缀后缀特征),通过CNN的卷积操作提取这些特征
- 应用:处理英文序列标注问题
- BILSTM-CRF
- 应用:处理英文序列标注问题
- 原因:以字为单位,无法分解
- 应用:处理英文序列标注问题