听说最好用的词向量ELMo效果非常好,笔者拿小样本中文情感二分类集合试了一下,发现与word2vec差异不大,可能是数据集的问题,而且elmo训练难度高但效率极低,所以还得具体看任务来定夺是否使用elmo,这里简单分享一下笔者在这过程中看到的内容综述。
Elmo简述
人们已经提出了大量可能的词嵌入方法。最常用的模型是 word2vec 和 GloVe,它们都是基于分布假设的无监督学习方法(在相同上下文中的单词往往具有相似的含义)。
虽然有些人通过结合语义或句法知识的有监督来增强这些无监督的方法,但纯粹的无监督方法在 2017-2018 中发展非常有趣,最著名的是 FastText(word2vec的扩展)和 ELMo(最先进的上下文词向量)。
之前的做法的缺点是对于每一个单词都有唯一的一个embedding表示, 而对于多义词显然这种做法不符合直觉, 而单词的意思又和上下文相关,
ELMo的做法是我们只预训练language model, 而word embedding是通过输入的句子实时输出的, 这样单词的意思就是上下文相关的了, 这样就很大程度上缓解了歧义的发生.
它首先在大文本语料库上预训练了一个深度双向语言模型(biLM),然后把根据它的内部状态学到的函数作为词向量。
2 ELMo与word2vec最大的不同:
词向量不是一成不变的,而是根据上下文而随时变化,这与word2vec或者glove具有很大的区别:
举个例子:针对某一词多义的词汇w="苹果"文本序列1=“我 买了 六斤 苹果。”文本序列2=“我 买了一个 苹果 7。”
上面两个文本序列中都出现了“苹果”这个词汇,但是在不同的句子中,它们我的含义显示是不同的,一个属于水果领域,一个属于电子产品呢领域,如果针对“苹果”这个词汇同时训练两个词向量来分别刻画不同领域的信息呢?
答案就是使用ELMo。
3 哈工大的一些任务测评
来自知乎刘一佳的回答(参考:ttps://www.zhihu.com/question/288565744)。
这边哈工大自己提供了与AllenNLP不一样的训练算法,并且应用在多国语言CoNLL评测之中,可参考论文:《Towards Better UD Parsing: Deep Contextualized Word Embeddings, Ensemble, and Treebank Concatenation》
在繁体中文词性、句法分析中效果:
词性UPOS:baseline(biaffine-parser) -94.6+elmo -94.3
句法LAS:baseline -79.7 + elmo 79.85
效果略好。
他们的算法ELMO用的20M词的生语料训练的,有的是他们自己训练算法,比bilm-tf显存效率高一点,训练稳定性高一些。他们也给出以下几个经验:
句法任务中,OOV比例高的数据ELMo效果好,多国语言中OOV rate与ELMo带来的提升 最为明显;
训练数据少或接近zero-shot,one-shot,ELMo表现更好;
训练数据较多,譬如dureader数据,elmo没啥效果;
有些公司用了,觉得效果明显,甚至上生产环境,有的公司则效果不佳,具体任务来看。
4 ELMo的效率低一种解决方案
ELMo的效率非常低,在博文《NAACL2018 一种新的embedding方法–原理与实验 Deep contextualized word representations (ELMo)》提到:
ELMo的效果非常好, 我自己在SQuAD数据集上可以提高3个左右百分点的准确率. 因为是上下文相关的embedding,
所以在一定程度上解决了一词多义的语义问题.
ELMo速度非常慢, 数据集中包含越10万篇短文, 每篇约400词, 如果将batch设置为32, 用glove词向量进行编码, 过3个biLSTM, 3个Linear, 3个softmax/logsoftmax(其余dropout, relu这种忽略不计), 在1080Ti(TiTan XP上也差不多)总共需要约15分钟训练完(包括bp)一个epoch.
而如果用ELMo对其进行编码, 仅编码时间就近一个小时, 全部使用的话因为维度非常大, 显存占用极高, 需要使用多张卡, 加上多张卡之间调度和数据传输的花销一个epoch需要2+小时(在4张卡上).
文中提出的效率解决的方式:
ELMo虽然对同一个单词会编码出不同的结果, 但是上下文相同的时候ELMo编码出的结果是不变的(这里不进行回传更新LM的参数)因为论文中发现不同任务对不同层的LM编码信息的敏感程度不同, 比如SQuAD只对第一和第二层的编码信息敏感, 那我们保存的时候可以只保存ELMo编码的一部分, 在SQuAD中只保存前两层, 存储空间可以降低1/3, 需要320G就可以了,
如果我们事先确定数据集对于所有不同层敏感程度(即上文提到的sj), 我们可以直接用系数超参sj对3层的输出直接用∑Lj=0staskjhLMk,j压缩成一个1024的向量, 这样只需要160G的存储空间即可满足需求.
5 英文预训练模型可直接试用tensorflow hub
elmo的训练这边笔者看到的有两个项目:allenai/bilm-tf 和 UKPLab/elmo-bilstm-cnn-crf。
elmo是原生于该项目allenai/bilm-tf,py3.5,tf1.2就可以运行,当然有些时间需要预装他们的allennlp,原生的是自带训练模块。
那么基于此,UKPlab(deeplearning4)改编了一个版本UKPLab/elmo-bilstm-cnn-crf,配置为py3 + tf1.8,而且应用在了bilstm-cnn-crf任务之中。两个版本因为对tf版本要求不一,所以最好用他们的docker。
tensorflow hub之中(双版本,1版、2版),有英文的预训练模型,可以直接拿来用的那种。
6 中文训练模型比较少
笔者比较推荐的中文训练项目有:
(1)博文《如何将ELMo词向量用于中文》
把详细训练步骤已经说了一下,结合allennlp官方教程就能串起来,比较好懂,使用预训练好的词向量作为句子表示直接传入到RNN中(也就是不使用代码中默认的先过CNN),在训练完后,将模型保存,在需要用的时候load进来,对于一个特定的句子,首先将其转换成预训练的词向量,传入language model之后最终得到ELMo词向量。
(2)github项目:HIT-SCIR/ELMoForManyLangs
哈工大不是沿用allennlp的bilm-tf,而自己写了一个,可参考该项目,并用在多国语言之中。
领取专属 10元无门槛券
私享最新 技术干货