Ref: https://www.cnblogs.com/Determined22/p/7238342.html
命名实体识别(Named Entity Recognition, NER)是 NLP 里的一项很基础的任务,就是指从文本中识别出命名性指称项,为关系抽取等任务做铺垫。狭义上,是识别出人名、地名和组织机构名这三类命名实体(时间、货币名称等构成规律明显的实体类型可以用正则等方式识别)。当然,在特定领域中,会相应地定义领域内的各种实体类型。
汉语作为象形文字,相比于英文等拼音文字来说,针对中文的NER任务来说往往要更有挑战性,下面列举几点:
(1) 中文文本里不像英文那样有空格作为词语的界限标志,而且“词”在中文里本来就是一个很模糊的概念,中文也不具备英文中的字母大小写等形态指示
(2) 中文的用字灵活多变,有些词语在脱离上下文语境的情况下无法判断是否是命名实体,而且就算是命名实体,当其处在不同的上下文语境下也可能是不同的实体类型
(3) 命名实体存在嵌套现象,如“北京大学第三医院”这一组织机构名中还嵌套着同样可以作为组织机构名的“北京大学”,而且这种现象在组织机构名中尤其严重
(4) 中文里广泛存在简化表达现象,如“北医三院”、“国科大”,乃至简化表达构成的命名实体,如“国科大桥”。
专著 [1] 里比较详细地介绍了 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,主要参考的是文献[4][5]。使用Bakeoff-3评测中所采用的的BIO标注集,即B-PER、I-PER代表人名首字、人名非首字,B-LOC、I-LOC代表地名首字、地名非首字,B-ORG、I-ORG代表组织机构名首字、组织机构名非首字,O代表该字不属于命名实体的一部分。如下面这一句话,这里当然也可以采用更复杂的BIOSE标注集。
整个模型的结构如下图所示:
1. 输入层:比如一句话有n个单词 首先将n个单词做one-hot得到稀疏向量,再通过look-up table得到n个单词的d维稠密词向量,
2. 双向LSTM层:共有n*s个LSTM模型, 用来自动提取句子特征(具体原理不懂啊),得到n个m维向量,在设置droupout之后 通过一个全连接层(线性层y=wx+b) 降维到k维向量(k也就是标注集的标签数)其中pij 都视作将字 xi 分类到第 j 个标签的打分值。
3. CRF层:给句子添加起始位和结束位可以构建一个(k+2)*(k+2) 的状态转移矩阵,
模型训练时通过最大化对数似然函数即可就得最优化的LSTM,CRF参数。
实验结果
关于CRF模型的特征模板就不细讲了,是参考 [3] 来做的。提好特征之后用CRF++工具包即可,这部分是小伙伴做的~
实验结果如下表:
下面开始一本正经地胡说八道:
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上,README.md里介绍了如何训练、测试。我是用笔记本的显卡训练的,batch_size 取64,Adam优化器训练120个epoch,大概用了4个多小时。如果机器条件允许,不妨试试 batch_size 直接取1,优化器用 SGD+Momentum 。