序列标注含义

序列标注是一个比较广泛的任务,包括分词,词性标注(POS),命名实体识别(NER),关系抽取等等,甚至你也可以用来做抽取式QA,直接在文章中标注出答案。

序列标注任务的一般形式:
对于待标注的一段序列序列标注 - 图1,我们需要给每个序列标注 - 图2预测一个tag,先定义Tag集合是 序列标注 - 图3,比如,分词的Tag可以定义为{Begin,Middle,End,Single},命名实体识别的Tag可以定义为{形容词,名词,动词,…..},假设预测序列是序列标注 - 图4,那我们要计算 序列标注 - 图5从而得到序列序列标注 - 图6,再定义对应的真实Label序列是序列标注 - 图7 ,那我们就对Y和L使用交叉熵计算Loss,通过梯度下降来求解参数。
总的来说,就是说对于一个一维线性输入序列:
序列标注 - 图8
给线性序列中的每个元素打上标签集合中的某个标签:
序列标注 - 图9

所以,其本质上是对线性序列中每个元素根据上下文内容进行分类的问题。一般情况下,对于NLP任务来说,线性序列就是输入的文本,往往可以把一个汉字看做线性序列的一个元素,而不同任务其标签集合代表的含义可能不太相同,但是相同的问题都是:如何根据汉字的上下文给汉字打上一个合适的标签(无论是分词,还是词性标注,或者是命名实体识别,道理都是想通的)。
这么说来,他比较像序列分类,但是和普通分类不一样的是,这些预测的tag之间可能是有关联的,我们可能需要通过上一个tag的信息去预测下一个tag,比如分词,如果上一个预测的tag是Begin,那么下一个tag就不应该是Single。
序列标注常见的算法有HMM(隐马尔科夫模型),MEMM(最大熵隐马尔科夫模型),CRF(条件随机场),以及LSTM-CRF模型,其中HMM和CRF都是概率图模型,而LSTM本身也很适合序列建模问题,LSTM-CRF是目前比较主流的做法,本文主要介绍HMM,CRF和LSTM-CRF,怎么用于序列标注任务。

与分类任务的区别

假设你有一组关于 Justin Bieber的日常生活照(你可以想像成Bieber是个自拍狂,经常在朋友圈晒自拍),你想标注一下这些照片描绘的活动场景(比如Bieber是在吃饭、参加舞会、开车,还是在睡觉呢),你会怎么做呢?
一种方法是不考虑照片的发生先后关系,通过svm、决策树之类的分类方法,对每张照片单独分类。比如,你有事先标注的关于Bieber的一个月的日常生活照,你可以通过这些标注集训练一个分类器,通过这些标注集合,你可能得到一个这样的分类器:拍摄于晚上6点之后光线很暗的照片是在睡觉,拍摄于晚上灯光闪烁的照片是在参加舞会…..
通过上述方法虽然也能解决问题,但是会丢失一些信息,比如有一张照片是bieber嘴的一个特写,你怎么判断他是在吃法还是在唱歌呢?如果你能知道,这张照片的前一张是关于Bieber在做饭的照片,那这张嘴的特写照很可能就是在吃饭;反之,前一张照片是在参加舞会,那这张特写就更可能是在唱歌。
因此,为了提高照片标注的准确性,我们就需要参考相邻照片的标注,这就是序列标注问题,也是条件随机场能大显身手的场景。
当然,你也许会说我在训练分类器的时候也可以加上跟时间有关的特征,比如上面的例子,在训练分类器的时候,可以把标注集按时间排序,然后把每张图前后的图片的类别作为分类器特征,来训练分类器。但是仔细想下,就会发现其中的问题,你在用这些分类器模型预测上面例子中的问题时,你是不知道每张图片的前后相邻图片的类别的,它们也是需要预测的;那你可能又说,预测出第一张图片类别后,可以把这个图片的类别作为特征预测下一张,但是这样做引入的问题就是如果第一张预测错了,就会影响第二张的预测,即引起误差传递。而序列标注模型是把这一组照片的类别作为一个整体来预测,是这个整体预测准确率最高。
知乎上有人做了一下总结,我觉得总结的不错:
标注跟分类最大的区别就是:标注采的特征里面有上下文分类结果,这个结果你是不知道的,他在“分类”的时候是跟上下文一起”分类的”。因为你要确定这个词的分类得先知道上一个词的分类,所以这个得整句话的所有词一起解,没法一个词一个词解。
而分类是根据当前特征确定当前类别,分类的时候不需要考虑上下文的分类结果,但可以引入上下文的特征。
**

HMM(隐马尔科夫模型)

一. 基本概念

HMM是一种生成式有向图模型,对联合分布进行建模求解p(x, y),大家可以去看一看西瓜书,写得通俗又易懂,有所掌握的同学可以跳过这一段。
序列标注 - 图10参考自周志华的机器学习西瓜书
如图,HMM包括两组变量x和y:
x={x1,x2,…,xn}属于观测变量,也就是我们观测到的信息,定义观测值集合为O 序列标注 - 图11 {o1,…,oM},其中M为可能的观测值。
y={y1,y2,…,yn}属于状态变量,或者叫隐变量,因为y是不可观测的,系统通常会在状态值集合S 序列标注 - 图12 {s1,s2,…,sN}中进行状态转换,其中N为可能的状态数。

首先我们来定义以下两个隐马尔科夫假设
1)观测独立性假设:在任意时刻t下,观察值 序列标注 - 图13 仅与当前的状态值 序列标注 - 图14 有关
(也正是这个假设限制了HMM的特征选择,无法考虑到上下文特征)
2)齐次马尔科夫假设:在任意时刻t下,状态 序列标注 - 图15 只和前一个状态 序列标注 - 图16 有关,与其他状态及观察值无关,和 序列标注 - 图17 无关,和 序列标注 - 图18 也无关
因此,HMM所求解的联合概率分布可以定义为:
序列标注 - 图19

接下来还会涉及到以下三组概率参数
状态转移矩阵:A = 序列标注 - 图20 ,表示在 t 时刻下,状态 序列标注 - 图21 转移到状态 序列标注 - 图22 的概率:
序列标注 - 图23
观测概率矩阵:B = 序列标注 - 图24 ,表示在状态 序列标注 - 图25 下生成观测 序列标注 - 图26 的概率:
序列标注 - 图27
初始状态概率分布: 序列标注 - 图28 ,表示初始时刻下各状态出现的概率:
序列标注 - 图29

HMM可以解决以下三类推断问题
1)似然问题:给定模型 序列标注 - 图30 ,求解 序列标注 - 图31
2)解码问题:给定模型 序列标注 - 图32 和观测序列x,求解 状态序列 y
3)学习问题:给定观测序列x,求解模型参数 序列标注 - 图33

二. HMM解决序列标注问题

回到我们的序列标注问题,也就是解码问题,这里以分词为例,状态集合可以定义为{B,M,E,S},观测序列就是我们的句子,状态序列y是我们的分词结果,我们用Viterbi算法来求解最大概率对应的状态序列y,也就是最有可能出现的状态序列。

三.求解:Viterbi算法

Viterbi算法阅读
大家不要把viterbi算法和HMM绑定到一起,这个算法本来是用动态规划来求最短路的,不是专门给HMM设计的,只是恰好可以求解HMM的解码问题。
算法基于这样的前提:最优路径的子路径也一定是最优的。
算法思路大概是:从根节点出发,每走一步,比较根节点到上层节点的最短路径+上层节点到当前节点的最短距离,递归计算到达该点的最短路径,一直走到终点。
序列标注 - 图34
那么viterbi算法用于HMM,就是求解给定观测值x后概率最大的状态序列y,如果使用穷举法会带来巨大的计算量,所以viterbi对状态进行转移,而状态数往往是比较少的。
回到分词任务,tag集合是{B,M,E,S},假设现在观测序列是“我喜欢吃海底捞”:
第一步“我”对应的状态y1有4种取值,取最大概率应该是tag S
第二步“喜”对应的状态y2也有4种,根据y1计算出最大概率应该是tag B
第三步“欢”对应的状态y3也有4种,根据y2计算出最大概率是tag E
……
可以看到,这里只需要计算447次,而穷举法却需要计算4^7次!

另外,结巴分词对viterbi算法做了一些改进:
1)PrevStatus转移条件,比如,状态B的前一状态只能是E或者S。
2)终止条件,最后一个状态只能是E或者S,表示词的结尾。
3)取log把概率连乘转化为连加,所以概率矩阵中可能有负数。

CRF原理

https://www.cnblogs.com/pinard/p/7048333.html

从随机场到马尔科夫随机场

  1. 首先,我们来看看什么是随机场。“随机场”的名字取的很玄乎,其实理解起来不难。随机场是由若干个位置组成的整体,当给每一个位置中按照某种分布随机赋予一个值之后,其全体就叫做随机场。还是举词性标注的例子:假如我们有一个十个词形成的句子需要做词性标注。这十个词每个词的词性可以在我们已知的词性集合(名词,动词...)中去选择。当我们为每个词选择完词性后,这就形成了一个随机场。<br /> 了解了随机场,我们再来看看马尔科夫随机场。马尔科夫随机场是随机场的特例,它假设随机场中某一个位置的赋值仅仅与和它相邻的位置的赋值有关,和与其不相邻的位置的赋值无关。继续举十个词的句子词性标注的例子: 如果我们假设所有词的词性只和它相邻的词的词性有关时,这个随机场就特化成一个马尔科夫随机场。比如第三个词的词性除了与自己本身的位置有关外,只与第二个词和第四个词的词性有关。

从马尔科夫随机场到条件随机场

理解了马尔科夫随机场,再理解CRF就容易了。CRF是马尔科夫随机场的特例,它假设马尔科夫随机场中只有X和Y两种变量,X一般是给定的,而Y一般是在给定X的条件下我们的输出。这样马尔科夫随机场就特化成了条件随机场。在我们十个词的句子词性标注的例子中,X是词,Y是词性。因此,如果我们假设它是一个马尔科夫随机场,那么它也就是一个CRF。
对于CRF,我们给出准确的数学语言描述:
设X与Y是随机变量,P(Y|X)是给定X时Y的条件概率分布,若随机变量Y构成的是一个马尔科夫随机场,则称条件概率分布P(Y|X)是条件随机场。

从条件随机场到线性链条件随机场(linear-CRF)

注意在CRF的定义中,我们并没有要求X和Y有相同的结构。而实现中,我们一般都假设X和Y有相同的结构,即:
X=(X1,X2,…Xn),Y=(Y1,Y2,…Yn)
我们一般考虑如下图所示的结构:X和Y有相同的结构的CRF就构成了线性链条件随机场(Linear chain Conditional Random Fields,以下简称 linear-CRF)。
序列标注 - 图35
在我们的十个词的句子的词性标记中,词有十个,词性也是十个,因此,如果我们假设它是一个马尔科夫随机场,那么它也就是一个linear-CRF。
我们再来看看 linear-CRF的数学定义:
设X=(X1,X2,…Xn),Y=(Y1,Y2,…Yn)均为线性链表示的随机变量序列,在给定随机变量序列X的情况下,随机变量Y的条件概率分布P(Y|X)构成条件随机场,即满足马尔科夫性: P(Yi|X,Y1,Y2,…Yn)=P(Yi|X,Yi−1,Yi+1)
则称P(Y|X)为线性链条件随机场。

线性链条件随机场的参数化形式

  1. 对于上一节讲到的linear-CRF,我们如何将其转化为可以学习的机器学习模型呢?这是通过特征函数和其权重系数来定义的。什么是特征函数呢?<br /> linear-CRF中,特征函数分为两类,第一类是定义在Y节点上的节点特征函数,这类特征函数只和当前节点有关,记为:<br />sl(yi,x,i),l=1,2,...L<br /> 其中L是定义在该节点的节点特征函数的总个数,i是当前节点在序列的位置。<br /> 第二类是定义在Y上下文的局部特征函数,这类特征函数只和当前节点和上一个节点有关,记为:<br />tk(yi1,yi,x,i),k=1,2,...K<br /> 其中K是定义在该节点的局部特征函数的总个数,i是当前节点在序列的位置。之所以只有上下文相关的局部特征函数,没有不相邻节点之间的特征函数,是因为我们的linear-CRF满足马尔科夫性。<br /> 无论是节点特征函数还是局部特征函数,它们的取值只能是0或者1。即满足特征条件或者不满足特征条件。同时,我们可以为每个特征函数赋予一个权值,用以表达我们对这个特征函数的信任度。假设tk的权重系数是λk,sl的权重系数是μl,则linear-CRF由我们所有的tkk,sll共同决定。<br /> 此时我们得到了linear-CRF的参数化形式如下:<br />![](https://cdn.nlark.com/yuque/__latex/f0f48e86b6494472df8bf6395a7875fc.svg#card=math&code=%5CLarge%0AP%28y%7Cx%29%20%3D%20%5Cfrac%7B1%7D%7BZ%28x%29%7Dexp%28%5Csum_%7Bi%2Ck%7D%5Clambda_k%20t_k%28y_%7Bi-1%7D%29%2Cy_i%2Cx%2Ci%20%29%2B%5Csum_%7Bi%2Cl%7D%5Cmu_l%20s_l%28y_i%2Cx%2Ci%20%29&height=69&width=630)<br /> 其中,Z(x)为规范化因子:<br />![](https://cdn.nlark.com/yuque/__latex/8d293ac2858318950578f60d6e46232b.svg#card=math&code=%5CLarge%0AZ%28x%29%20%3D%20%5Csum_yexp%28%5Csum_%7Bi%2Ck%7D%5Clambda_k%20t_k%28y_%7Bi-1%7D%29%2Cy_i%2Cx%2Ci%20%29%2B%5Csum_%7Bi%2Cl%7D%5Cmu_l%20s_l%28y_i%2Cx%2Ci%20%29&height=60&width=590)<br /> 回到特征函数本身,每个特征函数定义了一个linear-CRF的规则,则其系数定义了这个规则的可信度。所有的规则和其可信度一起构成了我们的linear-CRF的最终的条件概率分布。

线性链条件随机场实例

  1.  这里我们给出一个linear-CRF用于词性标注的实例,为了方便,我们简化了词性的种类。假设输入的都是三个词的句子,即X=(X1,X2,X3),输出的词性标记为Y=(Y1,Y2,Y3),其中Y∈{1(名词),2(动词)}<br /> 这里只标记出取值为1的特征函数如下:<br />t1=t1(yi1=1,yi=2,x,i),i=2,31=1<br />t2=t2(y1=1,y2=1,x,22=0.5<br />t3=t3(y2=2,y3=1,x,33=1<br />t4=t4(y1=2,y2=1,x,24=1<br />t5=t5(y2=2,y3=2,x,35=0.2<br />s1=s1(y1=1,x,11=1<br />s2=s2(yi=2,x,i),i=1,22=0.5<br />s3=s3(yi=1,x,i),i=2,33=0.8<br />s4=s4(y3=2,x,34=0.5<br /> 求标记(1,2,2)的非规范化概率。<br /> 利用linear-CRF的参数化公式,我们有:<br />P(y|x)∝exp[∑k=15λki=23tk(yi1,yi,x,i)+∑l=14μli=13sl(yi,x,i)]<br /> 带入(1,2,2)我们有:<br />P(y1=1,y2=2,y3=2|x)∝exp(3.2)

BiLSTM-CRF


序列标注任务

序列标注问题之中文分词

  以中文分词任务来说明序列标注的过程。假设现在输入句子“跟着他学左手右手一个慢动作”,我们的任务是正确地把这个句子进行分词。首先,把句子看做是一系列单字组成的线性输入序列,即:
    “跟 着 他 学 左 手 右 手 一 个 慢 动 作”
  序列标注的任务就是给每个汉字打上一个标签,对于分词任务来说,我们可以定义标签集合为(jieba分词中的标签集合也是这样的):
    
序列标注 - 图36
  其中B代表这个汉字是词汇的开始字符,M代表这个汉字是词汇的中间字符,E代表这个汉字是词汇的结束字符,而S代表单字词。
  有了这四个标签就可以对中文进行分词了。这时你看到了,中文分词转换为对汉字的序列标注问题,假设我们已经训练好了序列标注模型,那么分别给每个汉字打上标签集合中的某个标签,这就算是分词结束了,因为这种形式不方便人来查看,所以可以增加一个后处理步骤,把B开头,后面跟着M的汉字拼接在一起,直到碰见E标签为止,这样就等于分出了一个单词,而打上S标签的汉字就可以看做是一个单字词。于是我们的例子就通过序列标注,被分词成如下形式:
    “跟着 他 学 左手 右手 一个 慢动作”
  在这里我们可以采用双向LSTM来处理该类问题,双向会关注上下文的信息。
  在NLP中最直观的处理问题的方式就是要把问题转换为序列标注问题,思考问题的思维方式也就转换为序列标注思维,这个思维很重要,决定你能否真的处理好NLP问题。

序列标注之命名实体识别(NER)

  我们再来看看命名实体识别问题中的序列标注,命名实体识别任务是识别句子中出现的实体,通常识别人名、地名、机构名这三类实体。现在的问题是:假设输入中文句子
    序列标注 - 图37
  我们要识别出里面包含的人名、地名和机构名。如果以序列标注的角度看这个问题,我们首先得把输入序列看成一个个汉字组成的线性序列,然后我们要定义标签集合,标签集合如下(在这里的标签用什么代表不重要,重要的是它代表的含义):  
    序列标注 - 图38
  其中,BA代表这个汉字是地址首字,MA代表这个汉字是地址中间字,EA代表这个汉字是地址的尾字;BO代表这个汉字是机构名的首字,MO代表这个汉字是机构名称的中间字,EO代表这个汉字是机构名的尾字;BP代表这个汉字是人名首字,MP代表这个汉字是人名中间字,EP代表这个汉字是人名尾字,而O代表这个汉字不属于命名实体。
    
  有了输入汉字序列,也有了标签集合,那么剩下的问题是训练出一个序列标注ML系统,能够对每一个汉字进行分类,假设我们已经学好了这个系统,那么就给输入句子中每个汉字打上标签集合中的标签,于是命名实体就被识别出来了,为了便于人查看,增加一个后处理步骤,把人名、地名、机构名都明确标识出来即可。
  除了上面的分词和命名实体标注,很多其他的NLP问题同样可以转换为序列标注问题,比如词性标注、CHUNK识别、句法分析、语义角色识别、关键词抽取等。
  传统解决序列标注问题的方法包括HMM/MaxEnt/CRF等,很明显RNN很快会取代CRF的主流地位,成为解决序列标注问题的标准解决方案,那么如果使用RNN来解决各种NLP基础及应用问题,我们又该如何处理呢,下面我们就归纳一下使用RNN解决序列标注问题的一般优化思路。
  对于分词、词性标注(POS)、命名实体识别(NER)这种前后依赖不会太远的问题,可以用RNN或者BiRNN处理就可以了。而对于具有长依赖的问题,可以使用LSTM、RLSTM、GRU等来处理。关于GRU和LSTM两者的性能差不多,不过对于样本数量较少时,有限考虑使用GRU(模型结构较LSTM更简单)。此外神经网络在训练的过程中容易过拟合,可以在训练过程中加入Dropout或者L1/L2正则来避免过拟合。

CRF和LSTM在序列标注上的优劣

  LSTM:像RNN、LSTM、BILSTM这些模型,它们在序列建模上很强大,它们能够capture长远的上下文信息,此外还具备神经网络拟合非线性的能力,这些都是crf无法超越的地方,对于t时刻来说,输出层y受到隐层h(包含上下文信息)和输入层x(当前的输入)的影响,但是y和其他时刻的y是相互独立的,感觉像是一种point wise,对当前t时刻来说,我们希望找到一个概率最大的y,但其他时刻的y对当前y没有影响,如果y之间存在较强的依赖关系的话(例如,形容词后面一般接名词,存在一定的约束),LSTM无法对这些约束进行建模,LSTM模型的性能将受到限制。
  CRF:它不像LSTM等模型,能够考虑长远的上下文信息,它更多考虑的是整个句子的局部特征的线性加权组合(通过特征模版去扫描整个句子)。关键的一点是,CRF的模型为p(y | x, w),注意这里y和x都是序列,它有点像list wise,优化的是一个序列y = (y, y, …, y),而不是某个时刻的y,即找到一个概率最高的序列y = (y, y, …, y)使得p(y, y, …, y| x, w)最高,它计算的是一种联合概率,优化的是整个序列(最终目标),而不是将每个时刻的最优拼接起来,在这一点上CRF要优于LSTM。
  HMM:CRF不管是在实践还是理论上都要优于HMM,HMM模型的参数主要是“初始的状态分布”,“状态之间的概率转移矩阵”,“状态到观测的概率转移矩阵”,这些信息在CRF中都可以有,例如:在特征模版中考虑h(y), f(y, y), g(y, x)等特征。
  CRF与LSTM:从数据规模来说,在数据规模较小时,CRF的试验效果要略优于BILSTM,当数据规模较大时,BILSTM的效果应该会超过CRF。从场景来说,如果需要识别的任务不需要太依赖长久的信息,此时RNN等模型只会增加额外的复杂度,此时可以考虑类似科大讯飞FSMN(一种基于窗口考虑上下文信息的“前馈”网络)。
  CNN+BILSTM+CRF:这是目前学术界比较流行的做法,BILSTM+CRF是为了结合以上两个模型的优点,CNN主要是处理英文的情况,英文单词是由更细粒度的字母组成,这些字母潜藏着一些特征(例如:前缀后缀特征),通过CNN的卷积操作提取这些特征,在中文中可能并不适用(中文单字无法分解,除非是基于分词后),这里简单举一个例子,例如词性标注场景,单词football与basketball被标为名词的概率较高, 这里后缀ball就是类似这种特征。