天天看点

漫谈ELMo

词嵌入在很长一段时间内对NLP领域有很大的推动的作用,以至于embedding已经成为NLP任务中的一个标准操作。而研究人员却发现,词嵌入虽好,但弊端也明显,于是乎,语言模型就上位了……如果说Word2Vec是NLP领域里面的一个重要里程碑,那么ELMo的诞生应该可以算得上另外一个里程碑了吧!最近我正是在学习ELMo,因此想整理一下跟大家探讨。

词嵌入到底出了什么问题?

词嵌入(如想详细了解可戳这里)操作在NLP中已经成为常规操作,它也使得词义可以通过稠密向量来表达。但人们开始发现这种操作虽然好,但是仍然有一些问题:

  1. 集外词怎么办?统一使用UNK作为oov的token并不能区分各个集外词的词义。
  2. 多义词怎么办?每个词只对应一个向量,对于多语义或者有多层意思的词语而言这样是不够的。

第一个问题中,人们尝试使用字符级的嵌入操作来代替,毕竟字符是可以有限数量的。但第二个问题就是词嵌入的天然硬伤了,因为词语无论出现在什么场景,都只有一个向量作为表示,举个例子说,

spark

这个词出现在日常对话里面一般都是表示“星火”,但如果出现在一些数据科学技术文章中则可能表示spark这个并行计算平台。

这个问题归根结底就是,词向量只在训练过程考虑了训练语料上下文赋予其语义,而在使用过程没有考虑它在特定的语义环境中到底表达何种意思,所以预训练的词向量是“上下文独立”(context-independent)的。

那么我们在使用词向量时进行fine-tune可以解决这个问题吗?很遗憾,也是不行的,人类语言实在太复杂了,有时不仅仅像上面举例的

spark

这种领域区别问题,更有可能是表达程度等方面的问题。

所以,我们必须赋予词嵌入一些更大的弹性,即让每个词在特定的词义环境中表达出它该有的意思,也即我们追求的是获得“特定上下文”(context-specific)的表征。

ELMo诞生的前夕

等等,还记得语言模型吗?语言模型每个时间步输出的表征 h t = f ( x t − 1 , h t − 1 ) h_t = f(x_{t-1},h_{t-1}) ht​=f(xt−1​,ht−1​)不就正是综合上下文的表征吗?!于是乎,有人就拍案而起:就是你了!

TagLM大概是第一个使用这种想法的模型,咱们直接上图

漫谈ELMo

图一 TagLM模型

咱们先看图的右手边。右手边是一个bi-RNN实现的语言模型(我又要打广告了!如果不了解语言模型请戳这里,不了解RNN请戳这里),即对前向RNN是用前文 [ x 1 , x 2 , . . . , x t − 1 ] [x_1,x_2,...,x_{t-1}] [x1​,x2​,...,xt−1​]预测 x t x_{t} xt​,而后向RNN用后文 [ x t + 1 , x t + 2 , . . . , x T ] [x_{t+1},x_{t+2},...,x_T] [xt+1​,xt+2​,...,xT​]预测 x t x_{t} xt​,每个词 x t x_t xt​进入这个LM都会得到一个hidden state,咱们把它标记为 h t L M = [ h t f o r w a r d ; h t b a c k w a r d ] h_{t}^{LM} = [h_{t}^{forward};h_{t}^{backward}] htLM​=[htforward​;htbackward​]。这一部分是预训练的,跟咱们使用Word2Vec预训练词向量一个道理。

再看左图下方。每个输入词都会同时经过两个嵌入操作,分别是char-level和word-level的嵌入,两个嵌入操作得到的向量会拼接起来,作为网络主体bi-RNN的input。

然后看左图中部。词向量通过一个L层的bi-RNN得到每个time step的hidden state,咱们标记为 h t , l h_{t,l} ht,l​,

l

表示所在的层标,

t

则表示输入序列的时间步。以两层的bi-RNN为例,第一层输出的hidden state会拼接上预训练的bi-LM得到的双向隐藏特征,再进入下一层,最后用以NER等序列标注任务。

简单来说,tagLM对之前单纯使用预训练词向量的NLP任务做了简单的优化,就是加上LM embedding,因此同时考虑了上下文独立特征和特定上下文特征。

ELMo的降临

受到TagLM的启发,ELMo就应运而生,它的降临将彻底改变之前的局面:词嵌入不再是一个向量查找表,而是一个function!换句话说,以前咱们可以根据单个词的index查找出对应的词向量,但现在不一样了,我们需要把整句话放进这个函数里面,我们才能获得每个词的表征向量。而且以前同一个index查找出来的词向量肯定是相同的,但现在每个词在任何不同语境下都会有不同的表征。

老规矩先上图

漫谈ELMo

图二 ELMo模型

这个大概是我能找到的最棒的动图了。ELMo是在TagLM的基础上进行了若干的优化。

  1. 与TagLM只采用顶层输出不同,ELMo的representation使用了bi-LSTM所有层的hidden state的以及token的表征。以L=2为例,bi-LM输出的表征为

    R k = { x k L M , h k , j f o r w a r d , h k , j b a c k w a r d ∣ j = 1 , 2 } = { h k , j L M ∣ j = 0 , 1 , 2 } \begin{aligned} R_k &=\{x_k^{LM},h_{k,j}^{forward},h_{k,j}^{backward}|j=1,2\}\\ &=\{h_{k,j}^{LM}|j=0,1,2\} \end{aligned} Rk​​={xkLM​,hk,jforward​,hk,jbackward​∣j=1,2}={hk,jLM​∣j=0,1,2}​

    当j=0时表示输入token的表征,这一部分大体跟TagLM是一样的。原论文作者指出,低层表征容易捕获语法信息,语法信息在序列标注如POS、NER等任务中作用比较大,而高层表征却更好地捕获语义信息,在机器翻译、智能问答等任务里面比较有用。为了综合语义和语法信息,最好的办法就是将所有信息汇总起来。

  2. 各表征的汇总方式是

    E L M o k t a s k = γ t a s k ∑ j = 0 L s j t a s k h k , j L M ELMo_{k}^{task} = {\gamma}^{task}\sum_{j=0}^{L}s_{j}^{task}h_{k,j}^{LM} ELMoktask​=γtaskj=0∑L​sjtask​hk,jLM​

    其中 γ t a s k \gamma^{task} γtask是一个可训练单值参数,用于对特定任务场景下对表征向量的调整; s j t a s k s_{j}^{task} sjtask​是softmax正则化的参数。(原文没有细说,经过查证,这个应该是一个用作加权平均各层表征的向量,即 s ∈ R 1 × L s{\in}R^{1{\times}L} s∈R1×L,只是各层权重归一化的方法是使用softmax)

    累加号要成立的话,那么意味着各层的output都必须是相同维度的,对LSTM来说这个还是比较好操作的东西,毕竟输出维度(即units)多少都是可以设定的,但是要求输入token表征也是一样的维度。原论文说每层units都是4096,但都会映射到512进行skip-connection(按原论文的描述,第一层与第二层的映射output应该相加,这个结构在上图中没有画出来)。

  3. 最后一点,ELMo只采用char-level的特征,就是每个词采用多个kernel size一共2048个卷积核/层的CNN获得字符序列特征,默认设置是两层,这个CNN也使用了skip-connection,并同样映射到512维,而且模型参数在每个时间步是共享的。

至此,ELMo的细节应该都抠完了。

ELMo咋用?

ELMo其实就是多层bi-LM,所以它需要在大规模unlabel语料中进行预训练。在具体的NLP任务中,预训练好的ELMo相当于一个函数,将输入句子中每个词映射成对应的实数向量,然后再将其feed到后续的模型里面。

在具体NLP任务中,最简单的做法是将ELMo的模型参数固定住,这样梯度信号并不会backprop过来,整个ELMo唯一受影响的就是 γ \gamma γ参数和 s s s参数。但更通行的,也是效果更好的做法,就是在具体的NLP任务中做transfer learning,即对预训练模型做fine-tune,就像在各种CV任务中一样。

所以说ELMo开启了NLP的新历程,因为从这之后,NLP任务也可以像CV任务一样,选择一个合适的back bone,再针对自己需要解决任务去设计模型。

参考资料

  • https://www.analyticsvidhya.com/blog/2019/03/learn-to-use-elmo-to-extract-features-from-text/
  • https://arxiv.org/pdf/1802.05365.pdf
  • https://blog.csdn.net/sinat_29819401/article/details/90669304
  • https://blog.csdn.net/sinat_29819401/article/details/94015798
  • https://blog.csdn.net/sinat_29819401/article/details/94176245

继续阅读