目录
骚年,来一份“人民日报”吗?
骚年,你搞懂了LSTM了没?
有“人民日报”懂LSTM,我们就开车出发啦!
NER 的各种方法
对于NER 的各种方法基本上归于三类方法:
1. 基于规则的方法:利用手工编写的规则,将文本与规则进行匹配来识别出命名实体。例如,对于中文来说,“说”、“老师”等词语可作为人名的下文,“大学”、“医院”等词语可作为组织机构名的结尾,还可以利用到词性、句法信息。在构建规则的过程中往往需要大量的语言学知识,不同语言的识别规则不尽相同,而且需要谨慎处理规则之间的冲突问题;此外,构建规则的过程费时费力、可移植性不好。
2. 基于特征模板的方法:
统计机器学习方法将 NER 视作序列标注任务,利用大规模语料来学习出标注模型,从而对句子的各个位置进行标注。常用的应用到 NER 任务中的模型包括生成式模型HMM、判别式模型CRF等。比较流行的方法是特征模板 + CRF的方案:特征模板通常是人工定义的一些二值特征函数,试图挖掘命名实体内部以及上下文的构成特点。对于句子中的给定位置来说,提特征的位置是一个窗口,即上下文位置。而且,不同的特征模板之间可以进行组合来形成一个新的特征模板。CRF的优点在于其为一个位置进行标注的过程中可以利用到此前已经标注的信息,利用Viterbi解码来得到最优序列。对句子中的各个位置提取特征时,满足条件的特征取值为1,不满足条件的特征取值为0;然后把特征喂给CRF,training阶段建模标签的转移,进而在inference阶段为测试句子的各个位置做标注。关于这种方法可以参阅文献 [2] 和 [3]。
3. 基于神经网络的方法:
近年来,随着硬件能力的发展以及词的分布式表示(word embedding)的出现,神经网络成为可以有效处理许多NLP任务的模型。这类方法对于序列标注任务(如CWS、POS、NER)的处理方式是类似的,将token从离散one-hot表示映射到低维空间中成为稠密的embedding,随后将句子的embedding序列输入到RNN中,用神经网络自动提取特征,Softmax来预测每个token的标签。这种方法使得模型的训练成为一个端到端的整体过程,而非传统的pipeline,不依赖特征工程,是一种数据驱动的方法;但网络变种多、对参数设置依赖大,模型可解释性差。此外,这种方法的一个缺点是对每个token打标签的过程中是独立的分类,不能直接利用上文已经预测的标签(只能靠隐状态传递上文信息),进而导致预测出的标签序列可能是非法的,例如标签B-PER后面是不可能紧跟着I-LOC的,但Softmax不会利用到这个信息。
学界提出了 LSTM-CRF 模型做序列标注。文献[4][5]在LSTM层后接入CRF层来做句子级别的标签预测,使得标注过程不再是对各个token独立分类。引入CRF这个idea最早其实可以追溯到文献[6]中。文献[5]还提出在英文NER任务中先使用LSTM来为每个单词由字母构造词并拼接到词向量后再输入到LSTM中,以捕捉单词的前后缀等字母形态特征。文献[8]将这个套路用在了中文NER任务中,用偏旁部首来构造汉字。关于神经网络方法做NER,可以看博客[9] ,介绍的非常详细~
基于字的BiLSTM-CRF模型
使用基于字的BiLSTM-CRF,主要参考的是文献[4][5]。使用Bakeoff-3评测中所采用的的BIO标注集,即B-PER、I-PER代表人名首字、人名非首字,B-LOC、I-LOC代表地名首字、地名非首字,B-ORG、I-ORG代表组织机构名首字、组织机构名非首字,O代表该字不属于命名实体的一部分。如:
这里当然也可以采用更复杂的BIOSE标注集。
以句子为单位,将一个含有 个字的句子(字的序列)记作,
其中 表示句子的第个字在字典中的id,进而可以得到每个字的one-hot向量,维数是字典大小。
模型的第一层是 look-up 层,利用预训练或随机初始化的embedding矩阵将句子 中的每个字由one-hot向量映射为低维稠密的字向量(character embedding) , 是embedding的维度。在输入下一层之前,设置dropout以缓解过拟合。
模型的第二层是双向LSTM层,自动提取句子特征。将一个句子的各个字的char embedding序列作为双向LSTM各个时间步的输入,再将正向LSTM输出的隐状态序列与反向LSTM的 在各个位置输出的隐状态进行按位置拼接 ,得到完整的隐状态序列
在设置dropout后,接入一个线性层,将隐状态向量从 维映射到 维, 是标注集的标签数,从而得到自动提取的句子特征,记作矩阵 。可以把的每一维都视作将字分类到第 个标签的打分值,如果再对进行Softmax的话,就相当于对各个位置独立进行 类分类。但是这样对各个位置进行标注时无法利用已经标注过的信息,所以接下来将接入一个CRF层来进行标注。
模型的第三层是CRF层,进行句子级的序列标注。CRF层的参数是一个 的矩阵 A ,表示的是从第 个标签到第个标签的转移得分,进而在为一个位置进行标注的时候可以利用此前已经标注过的标签,之所以要加2是因为要为句子首部添加一个起始状态以及为句子尾部添加一个终止状态。如果记一个长度等于句子长度的标签序列 ,那么模型对于句子的标签等于的打分为
可以看出整个序列的打分等于各个位置的打分之和,而每个位置的打分由两部分得到,一部分是由LSTM输出的 决定,另一部分则由CRF的转移矩阵 决定。进而可以利用Softmax得到归一化后的概率:
模型训练时通过最大化对数似然函数,下式给出了对一个训练样本 的对数似然:
如果这个算法要自己实现的话,需要注意的是指数的和的对数要转换成 ,在CRF中上式的第二项使用前向后向算法来高效计算。
模型在预测过程(解码)时使用动态规划的Viterbi算法来求解最优路径:
CRF层详解
我们重点关注一下CRF层:
回顾一下整个模型,我们将embedding的字(或词或字和词的拼接)。(anyway,这些embeddings在训练的时候都会fine-tuned的),数据经过模型处理,得到所有词的labels。
其中,数据在经过biLSTM后的形式如下图所示:
比如,BiLSTM 对应的输出是1.5 (B-Person), 0.9 (I-Person), 0.1 (B-Organization), 0.08 (I-Organization) and 0.05 (O). 接着输入CRF layer, .CRF layer将选出最大分值的labels 序列作为输出结果。
表面上,经过BILSTM,我们已经获得了各个词在不同label上的得分。比如对应“B-Person”, 得分 (1.5),我们仅需要选择每个词对应的最高得分的label最为输出就可以了,但这样得到的并非是好的结果。这也是为什么要接入CRFlayer的原因。
比如上图中,我们得到的结果: “I-Organization I-Person” 和 “B-Organization I-Person”.显然是不合理的。
CRF层可以为输出的预测标签添加一些约束以确保它们有效。 在训练过程中,CRF层可以自动从训练数据集中学习这些约束。从而提升labels的准确性。
这些约束可能是:
- 句子中第一个单词的标签应以“B-”或“O”开头,而不是“I-”
- “B-label1 I-label2 I-label3 I- ...”,这样的输出中,label1,label2,label3 ......应该是相同的命名实体标签。 例如,“B-Person I-Person”是有效的,但“B-Person I-Organization”这样的预测无效。
- “O I-label”是无效的。 一个命名实体的第一个标签应以“B-”而非“I-”开头,有效的输出模式应为“O B-label”
- ...
CRF层的loss function包含两个重要的score,Emission score 和 Transition score。
Emission score
Emission score 通过biLSTM层的输出计算。
按照上图所示的输出逻辑,我们定义label对应的对应的index如下表:
Label | Index |
---|---|
B-Person | 0 |
I-Person | 1 |
B-Organization | 2 |
I-Organization | 3 |
O | 4 |
定义 emission score符号为 ,其中单词 对应的输出label为 ,如上图所示,,表示的 emission score 为0.1。
Transition score
定义Transition score符号为,表示label之间的转移关系,如上图所示,,表示的label transition 为0.9.我们建立transition score matrix 来表示所有标签之间的转移关系。另外为了让transition score matrix 是稳定的,我们额外加入 START 和 END标签,他们分别表示句子的开始和结束。transition score matrix示例如下表:
START | B-Person | I-Person | B-Organization | I-Organization | O | END | |
---|---|---|---|---|---|---|---|
START | 0 | 0.8 | 0.007 | 0.7 | 0.0008 | 0.9 | 0.08 |
B-Person | 0 | 0.6 | 0.9 | 0.2 | 0.0006 | 0.6 | 0.009 |
I-Person | -1 | 0.5 | 0.53 | 0.55 | 0.0003 | 0.85 | 0.008 |
B-Organization | 0.9 | 0.5 | 0.0003 | 0.25 | 0.8 | 0.77 | 0.006 |
I-Organization | -0.9 | 0.45 | 0.007 | 0.7 | 0.65 | 0.76 | 0.2 |
O | 0 | 0.65 | 0.0007 | 0.7 | 0.0008 | 0.9 | 0.08 |
END | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
从上表可以看出:
- 句子中第一个单词的标签应以“B-”或“O”开头,而不是“I-”(从“START”到“I-Person或I-Organization”的转换分数非常低。)
- “B-label1 I-label2 I-label3 I- ...”,的输出标签序列中,label1,label2,label3 ......应该是相同的命名实体标签。 例如,“B-Person I-Person”有效,若是“B-Person I-Organization”则不合理。 (从“B-Organization”到“I-Person”的得分仅为0.0003,远低于其他值。)
- “O I-label”也是无效的。 一个命名实体的第一个标签应该以“B-”而不是“I-”开头,换句话说,有效的输出模式应该是“O B-label”(我们可以看到都非常小)
- ....
transition score matrix 不是人为给的,它本身是模型的参数,一开始他是随机值,在模型的训练过程中,完成fine-tuning.
CRF loss function
定义最优的label序列为real path,其得分score 为real path score ,其他可能的label序列为possible paths。
损失函数由real path score 和其他 possible paths score来构建。real path score表示最优的label序列得分。该分数应该是所有path中的最高分。
Label | Index |
---|---|
B-Person | 0 |
I-Person | 1 |
B-Organization | 2 |
I-Organization | 3 |
O | 4 |
START | 5 |
END | 6 |
比如我们由5个words组成的sentence,可能的路径:
- 1) START B-Person B-Person B-Person B-Person B-Person END
- 2) START B-Person I-Person B-Person B-Person B-Person END
- …
- 10) START B-Person I-Person O B-Organization O END
- …
- N) O O O O O O O
如果条possible paths 分别有score ,那么所有paths的所有score 为 。假设训练集得出第10条path 是real path, 应该在 所有score ()中占比最大。
因此损失函数可以定义为:
也许您会问, 中,是什么?换句话说,我们的 score 怎么求?
Real path score
我们之前的公式中,定义了表示第个path的score. 那么对于第10个path(the real path)“START B-Person I-Person O B-Organization O END”,我们这样计算 :
原句子包含7个词:。其中,分别表示句子的开始标记START和结束标记END。
其中,。正如之前介绍的,EmissionScore 是根据bilstm layer 的输出来统计的。例如,在我们的示意图中,。我们可以设定和为0。
正如之前介绍的, 即表示从label 到 的TransitionScore,他们的值在模型训练的时候得到。
The total score of all the paths
对于一个NER识别任务,BILSTM层输出的label 有很多种,假设每一个 输出的 对应 个。那么可能的path 有个,这么多的可能,如果考虑累加来求所有possible paths 的 显然是不太实际的。
我们将损失函数变为 log loss function:
因为我们的train 目标是最小化loss,所以我们加一个负号(目标变为最大化该函数):
上式中,前两项我们已经知道如何求得,我们要解决的是
假设我们的训练数据是一个只有3个word 的句子:,输出2个label:,Emission scores 对应如下表:
CRF Layer 中, Transition scores 对应如下表:
我们的计算过程应该是这样的,先计算到的所有possible paths(也就是),在此基础上计算的possible paths,最后计算 的 possible paths。
设previous 为上一步的结果result,obs 为当前word 对应的的信息。我们开始计算
前面没有产生result,故previous 为None, 对应的观测值有,我们看到,每一个此时没有Transition scores,只有EmissionScore,因此 的所有possible paths score:
- 展开previous:
- 展开obs:
- 将前一步()的result 当前的EmissionScore,TransitionScore相加:
- 构建下一步的previous:
- 依照前计算的totalScore,我们有:
我们可以看出上式中,S与path的对应关系:
- 展开previous:
- 展开obs:
- 将前一步的result 当前的EmissionScore,TransitionScore相加:
- 构建下一步的previous:
class My_CRF():
def __init__():
#[Initialization]
'''
Randomly initialize transition scores
'''
def __call__(training_data_set):
#[Loss Function]
Total Cost = 0.0
#Compute CRF Loss
'''
for sentence in training_data_set:
1) The real path score of current sentence according the true labels
2) The log total score of all the possbile paths of current sentence
3) Compute the cost on this sentence using the results from 1) and 2)
4) Total Cost += Cost of this sentence
'''
return Total Cost
def argmax(new sentences):
#[Prediction]
'''
Predict labels for new sentences
'''
模型效果
1. 总的来说,经过仔细选择特征模板的CRF模型在人名上的识别效果要优于BiLSTM-CRF,但后者在地名、组织机构名上展现了更好的性能。究其原因,可能是因为:
(1) 人名用字较灵活且长度比较短,用特征模板在窗口内所提取的特征要比神经网络自动学习的特征更有效、干扰更少
(2) 地名、组织机构名的构成复杂、长度较长,使用双向LSTM能够更好地利用句子级的语义特征,而特征模板只能在窗口内进行提取,无法利用整句话的语义。
2. 对于CRF模型来说,使用 {字符,词性,词边界,实体列表} 这一组合模板的效果在CRF模型系列中表现最好(各个单一模板以及其他组合模板的结果未列出)。
3. 对于BiLSTM-CRF模型来说,这里在每一层的处理都是比较简单的,还有可以提高的空间。例如字向量embedding的初始化方式,这里只是用了最简单的随机初始化,然而由于语料规模比较小,所以不太合适。可以考虑对句子做分词,然后将字向量初始化为该字所在词的词向量(可以用在别的大型语料上的预训练值)。此外,还可以尝试文献[5][7][8]的思路,将low-level的特征经过一个RNN或CNN,进而通过“组合”的方式来得到字级别的embedding(英文是用字母构造单词,中文是用偏旁部首构造汉字),将其与随机初始化的字向量拼接在一起。
另外要提的一点是BiLSTM-CRF在这应该是过拟合了,迭代轮数(120轮)给大了,测试集指标在大约60轮之后已经开始下降。应该划个验证集做early stopping。
BiLSTM-CRF模型的代码在GitHub上,pytorch版本请参考tutorial,以及代码Bi-LSTM-CRF。README.md里介绍了如何训练、测试。我是用笔记本的显卡训练的,batch_size 取64,Adam优化器训练120个epoch,大概用了4个多小时。如果机器条件允许,不妨试试 batch_size 直接取1,优化器用 SGD+Momentum 。
[1] https://www.cnblogs.com/Determined22/p/7238342.html
[2] 向晓雯. 基于条件随机场的中文命名实体识别[D]. , 2006.
[3] 张祝玉, 任飞亮, 朱靖波. 基于条件随机场的中文命名实体识别特征比较研究[C]//第 4 届全国信息检索与内容安全学术会议论文集. 2008.
[4] Huang Z, Xu W, Yu K. Bidirectional LSTM-CRF models for sequence tagging[J]. arXiv preprint arXiv:1508.01991, 2015.
[5] Lample G, Ballesteros M, Subramanian S, et al. Neural Architectures for Named Entity Recognition[C]//Proceedings of NAACL-HLT. 2016: 260-270.
[6] Collobert R, Weston J, Bottou L, et al. Natural language processing (almost) from scratch[J]. Journal of Machine Learning Research, 2011, 12(Aug): 2493-2537.
[7] Ma X, Hovy E. End-to-end sequence labeling via bi-directional lstm-cnns-crf[J]. arXiv preprint arXiv:1603.01354, 2016.
[8] Dong C, Zhang J, Zong C, et al. Character-Based LSTM-CRF with Radical-Level Features for Chinese Named Entity Recognition[C]//International Conference on Computer Processing of Oriental Languages. Springer International Publishing, 2016: 239-250.
[9] http://www.cnblogs.com/robert-dlut/p/6847401.html