动态词向量在序列标注任务中的应用与实践
什么是动态词向量?
在说明什么是动态词向量前,首先稍微提一下现有的词向量(word embedding)。
学过 NLP 的人都知道有很多方法来表示一个文本句子,比如 BoW 模型(建立一个维度为语料库词表大小的一维向量进行表示),而在表示一个词时,一般采用one-hot编码。可实际应用时,我们将这些基础的表示方法,直接在自己领域的数据集进行 NLP 任务时,往往得不到理想的效果。其原因可能是训练的语料不够多,模型甚至学习不到文本中的上下文语法信息,更别说去学习任务所需的信息了。所以这种表示方式一般也只有一些语言模型(language model)才用得上,例如 Bert。而不需要关注基本上下文信息的、希望直接学习更“高级”的信息的任务,就需要用到词向量了。
词向量主要的一个优点是:向量中往往包含着该词在语料库中丰富的上下文信息,相比之前的基本表示方法,已经提前学习到了基本的文法等信息,更易于关注下游的任务。词向量的另一个优点是:可以将One-hot这种高维稀疏向量的表示,压缩到一个低维的空间,使得模型能够更好的学习,如下图所示。
词向量其实是语言模型的产物,而语言模型说起来就复杂了,这里只说它的作用是学习大量的文本数据,从而预测一个句子是否成立的概率。通过语言模型得到的词向量,我们可以对任意的一句话用数学的方法进行表示,而完全不丢失到词语的一些基本信息,这在实际任务中是非常重要的。
通常,我们也不会为了词向量每次都从头到尾去训练语言模型,一是耗时,二是也没有那么大的语料库可供训练。这时我们就可以将语言模型中的词向量保存下来,以供下次使用。目前常用的词向量有 Word2Vec,Glove 等。
由于每个词的词向量训练完都是固定不变的,每次使用时都是直接加载来,既快捷也有效。但这也是其缺点所在:由于词向量固定不变,导致词不管在句子中什么位置,词向量都是一致的。比如下面这两句话:
上个月的电 费 该交了。
这篇文章理解起来太 费 脑了。
上面两句话中都有 “费” 这个字,但明显上面的表示钱,下面的表示消耗,甚至连词性都不一样,将这两个字使用同样的词向量来表示显然是不合适的。
于是动态词向量应运而生。每个词的动态词向量会根据上下文动态的进行变化,从而更好的处理 “一词多义” 的现象。为了以示区别,Word2Vec 等这类词向量就统称之为静态词向量。
动态词向量现在有哪些?
同静态词向量一致,目前已知的动态词向量均由语言模型训练而来,例如 ELMo ,Flair embedding,Bert 等等。Bert 比较复杂且规模较大,这里简单介绍下前两种:
ELMo: 在EMLo中,首先需要大的语料库上预训练一个双向语言模型(biLM)。模型由两个两层Bi-LSTM LM组成,其中包含一个前向和一个后向语言模型。在使用模型获取词向量时,就比较灵活了,可以取最后一层的输出,或者倒数第二层的输出,甚至可以直接取两层输出的平均值。作者认为低层的Bi-LSTM层能提取语料中的句法信息,高层的bi-LSTM能提取语料中的语义信息。
Flair embedding: 与ELMo类似,同样也是使用了两个两层的 Bi-LSTM 作为前向和后向模型进行训练,但是不同于 ELMo, Flair embedding 是基于char的。如下图,Flair embedding是针对word中的每一个char进行编码。在后续的多篇论文中, Flair embedding 都表现出比ELMo更好的效果,尤其是在序列标注任务上。由于中文的每一个字就是最小单位,所以对中文来说如果ELMo只取最上面一层作为动态词向量表示,两者就是一致的。
动态词向量如何在序列标注任务中应用?
目前已知的序列标注任务有:中文分词、词性标注、命名体识别、关键词抽取 等等。本文以命名体识别任务为例,讲述如何在任务中使用动态词向量进行预测。
看到这里,相信你们很多人都发现了,全文提的词向量都是基于单字的,这里没有涉及到中文分词。由于分词很多情况会将一些词进行误分,所以要不要使用因人而异。而且在序列标注任务中,我们需要对一句话中的每个字进行预测,例如:
现在香楠小区有一套65平的两房,小区中心位置,报价338万。
在上面这句中,通过 BIO 标注方案,我们需要识别出以下几个实体:位置(local)、面积(area)、价格(price),则模型需要预测对应下图的一个序列。
相比于中文分词过后的词语,通过对单字进行预测,我们能更精细地预测每一个字的标签。
结合动态词向量进行 NLP 任务的流程相较使用一般的词向量而言并不复杂,目前已经有比较多的研究工作在结合动态词向量进行序列标注任务的研究,近期主要是基于Flair embedding。以 NER 任务为例,动态词向量应用的步骤有以下:
1. 准备语料库,训练动态词向量模型(ELMo或者Flair embedding均可,本文使用使用Flair embedding)。
2. 准备 NER 任务的训练语料,通过动态词向量模型,获取训练语料的动态词向量表示。
3. 训练 NER 模型并评测。
如果不想训练自己的动态词向量模型,也可以直接使用哈工大开源的 pytorch 版的ELMo预训练模型(https://github.com/HIT-SCIR/ELMoForManyLangs),强烈建议在自己的语料上进行 pre-train。
动态词向量实际表现如何?有比 Word2Vec 这类词向量好吗?
首先给出结论:根据笔者自己的实验,在 NER 任务上,动态词向量确实比 Word2Vec 这类静态词向量好, 能够提升预测的精度 。
先简单介绍一下本文实验进行的 NER 任务,主要是在文本中提取以下5类房源的实体信息:
位置(local)、面积(area)、价格(price)、户型(layout)、装修(decoration)
实验使用的数据和参数如下:
1. 训练动态词向量 Flair embedding 的语料库:包含约 152万 个中文句子。
2. Flair 模型为两层双向 LSTM 模型,取最后一层输出作为词向量。这边可以直接使用作者发布的 pytorch 代码进行模型训练(https://github.com/flairNLP/flair)。
3. 为保证模型可以学习到上下文特征,因此分别训练两个 Flair 模型,实际使用时进行拼接即可:
基于 Flair 的前向模型(forward embedding):用于动态获得当前词学习 上文 信息后得到的词向量。
基于 Flair 的后向模型(back embedding):用于动态获得当前词学习 下文 信息后得到的词向量。
4. NER模型使用现在较为通用的 Bi-LSTM + CRF,其中Bi-LSTM的层数为2。
5. NER 模型的训练集为 120000 条,测试集为 533 条。
实验结果和分析
实验最终取得的准确率为 92.08%,相较于原来的 85.45%,提升了 6.63%。
总体上来看,动态词向量相较于静态词向量准确率提升明显,各个实体类型的预测精度均有不同程度地提升。从结果看,动态词向量根据上下文动态变化,有助于提高 NER 任务的预测精度。但是,我们也发现,召回率有所下降。分析其原因,有可能是以下几个:
1. 训练 Flair 模型的语料库较为小。目前使用的语料库仅为 152万 个句子,而通常所需的语料库基本都为亿级,相比来说,实验所用的语料库还是太小了。
2. NER 模型的标注语料并非人工精心审核,部分标注存在一定的问题或者不统一,有待改善。
3. 两个模型的一些超参数也没有细调,部分超参数可能还需要进行多次尝试,比如LSTM 的隐含层单元数等。
讨论:NER模型真的有必要同时用到 forward embedding 和 back embedding 两种动态词向量?
答案是肯定的,非常有必要!实际实验时,仅使用单向的 embedding,与使用双向的embedding 结果有着比较大的差距:
仅使用单向 embedding 时,准确率仅为 84.75%,甚至比静态词向量还要差一些。当使用双向 embedding 后,准确率提升至最优的 92.08% 。
由此来看,双向的 embedding 比单向 embedding,更适用于 NER 任务。
未来工作展望
2. 在有了更多的语料库后,可以使用更大更复杂的模型进行动态词向量生成,例如 Bert,并进一步调整预训练的方法,例如 RoBerta。
彭彬彬,58同城AI Lab算法高级工程师,2019年7月加入58,2019年6月硕士毕业于中国科学院大学,目前主要负责智能语音分析的算法工作。