关于ELMo的若干问题整理记录

以下是关于ELMo的若干问题整理记录,自己在网上找了一些问题,对每个问题收集了一些资料,并做了整理,有些问题还写了一些自己的看法,可能会有纰漏,甚至还有错误,还请大家赐教

1.ELMo的基本原理是什么?

ELMO采用了典型的两阶段过程,第一个阶段是利用语言模型进行预训练;第二个阶段是在做下游任务时,从预训练网络中提取对应单词的网络各层的Word Embedding作为新特征补充到下游任务中。

第一阶段:利用语言模型进行预训练

第一阶段模型总览:

ELMo第一阶段模型

上图展示的是其预训练过程,它的网络结构采用了双层双向LSTM,其中单词(token)特征这一块采用的是单词的embedding(是否是预训练好的论文中没有告知)或者采用字符卷积得到其embedding表示(论文原文中说的是:via token embeddings or a CNN over characters,字符卷积可以参考论文:Character-Aware Neural Language Models),目前语言模型训练的任务目标是根据单词​ W_i 的上下文去正确预测单词 W_i ​, ​ W_i 之前的单词序列Context-before称为上文, W_i 之后的单词序列Context-after称为下文。

上图中左端的前向双层LSTM代表正方向编码器,输入的是从左到右顺序的除了预测单词外 W_i ​的上文Context-before;右端的逆向双层LSTM代表反方向编码器,输入的是从右到左的逆序的句子下文Context-after;每个编码器的深度都是两层LSTM叠加。

需要注意的是上述残差结构是在训练深层LSTM网络时常用的结构,简单做法就是将LSTM层的输入加到输出上,在官方tensorflow源码中token的embedding没有加到第一层LSTM的输出上

使用这个网络结构利用大量语料做语言模型任务就能预先训练好这个网络,如果训练好这个网络后,输入一个新句子​ S_{new} ,句子中每个单词都能得到对应的三个Embedding:

  • 最底层是单词的Word Embedding
  • 往上走是第一层双向LSTM中对应单词位置的Embedding,这层编码单词的句法信息更多一些;
  • 再往上走是第二层LSTM中对应单词位置的Embedding,这层编码单词的语义信息更多一些。

也就是说,ELMO的预训练过程不仅仅学会单词的Word Embedding,还学会了一个双层双向的LSTM网络结构,而这两者后面都有用。

第二阶段:下游任务利用预训练好的embedding

第二阶段模型总览:



以QA问题为例,展示下游任务如何利用预训练好的embedding。对于问句X,我们可以先将句子X作为预训练好的ELMO网络的输入,这样句子X中每个单词在ELMO网络中都能获得对应的三个Embedding,之后给予这三个Embedding中的每一个Embedding一个权重a,这个权重可以学习得来,根据各自权重累加求和,将三个Embedding整合成一个。然后将整合后的这个Embedding作为X句在自己任务的那个网络结构中对应单词的输入,以此作为补充的新特征给下游任务使用。对于上图所示下游任务QA中的回答句子Y来说也是如此处理。因为ELMO给下游提供的是每个单词的特征形式,所以这一类预训练的方法被称为“Feature-based Pre-Training”。

2.ELMo的训练过程是什么样的?损失函数是什么?

ELMo的训练过程实际上指的是其第一阶段的预训练过程,第一阶段实际上就是在训练一个双向语言模型,假设给定一个序列,该序列含有 N ​个token \left(t_{1}, t_{2}, \ldots, t_{N}\right) ​ ,那么:

  • 前向语言模型通过在给定上文 \left(t_{1}, \ldots, t_{k-1}\right) ​(Context-before)的情况下对token ​ t_k 的概率建模来计算序列出现的概率:
    p\left(t_{1}, t_{2}, \ldots, t_{N}\right)=\prod_{k=1}^{N} p\left(t_{k} | t_{1}, t_{2}, \ldots, t_{k-1}\right)
    • 许多主流的神经语言模型都会先给序列中的token计算一个上下文无关的token表示 \mathbf{x}_{k}^{L M} ​,然后将它传递给L层前向LSTM。这样的话,在每个位置 k ​,每个LSTM层输出一个上下文相关的表示 \overrightarrow{\mathbf{h}}_{k, j}^{L M} ​,其中​ j = 1, \ldots, L (在ELMo中L取2)
  • 后向语言模型与前向类似,但是它是“从后往前建模的”,通过在给定下文 \left(t_{k+1}, \ldots, t_{N}\right) ​(Context-after)的情况下对token t_k ​的概率建模来计算序列出现的概率:
    p\left(t_{1}, t_{2}, \ldots, t_{N}\right)=\prod_{k=1}^{N} p\left(t_{k} | t_{k+1}, t_{k+2}, \ldots, t_{N}\right)
    • 与前向语言模型类似,后向语言模型在每个位置​,每个LSTM层同样会输出一个上下文相关的表示 \overleftarrow{\mathbf{h}}_{k, j}^{L M} ​,其中​ j = 1, \ldots, L
    • 需要注意的是,上述上下文无关的token表示​ \mathbf{x}_{k}^{L M} 是前后向语言模型共享的

因此,由于ELMo结合了前后向语言模型,故其目标是同时最大化前后向语言模型的对数似然:

\begin{array}{l}{\sum_{k=1}^{N}\left(\log p\left(t_{k} | t_{1}, \ldots, t_{k-1} ; \Theta_{x}, \overrightarrow{\Theta}_{L S T M}, \Theta_{s}\right)\right.} \\ {\left.\quad+\log p\left(t_{k} | t_{k+1}, \ldots, t_{N} ; \Theta_{x}, \overleftarrow \Theta_{L S T M}, \Theta_{s}\right)\right)}\end{array}

其中:

  • \Theta_{x} 为token表示的参数(前后向语言模型共享)
  • \Theta_{s} 为softmax分类的参数(前后向语言模型共享)
  • \overrightarrow{\Theta}_{L S T M}, \overleftarrow \Theta_{L S T M} 分别表示前后向语言模型LSTM层的参数

综上所述,ELMo的训练过程即为一个前后向语言模型的训练过程,通过上述描述则一目了然,而其损失函数即为简单的分类损失,取决于源码实现,不同源码中的实现可能略有不同。

3.ELMo训练好了之后如何使用?

ELMo训练好了该如何使用实际上指的是其第一阶段的预训练过程训练完毕,下游任务如何利用预训练好的embedding,在问题1中已经有了比较详细的解读,在该问题则对其进行公式化的说明。首先由1可知,对于序列中的每个token,一个L层的双向语言模型就会得到其2L+1个表示,即为:

\begin{aligned} R_{k} &=\left\{\mathbf{x}_{k}^{L M}, \overrightarrow{\mathbf{h}}_{k, j}^{L M}, \overleftarrow{\mathbf{h}}_{k, j}^{L M} | j=1, \ldots, L\right\} \\ &=\left\{\mathbf{h}_{k, j}^{L M} | j=0, \ldots, L\right\} \end{aligned}

其中,​ \mathbf{h}_{k, 0}^{L M} 为token的表示(即 \mathbf{h}_{k, 0}^{L M} = \mathbf{x}_{k}^{L M}​),​ \mathbf{h}_{k, j}^{L M}=[\overrightarrow{\mathbf{h}}_{k, j}^{L M} ; \overleftarrow{\mathbf{h}}_{k, j}^{L M}] 为每个双向LSTM层得到的表示。

需要注意的是,这里是将整个句子输入到双向语言模型(这里用的是双向LSTM网络)中,正向和反向LSTM网络共享token embedding的输入,源码中token embedding、正向、反向LSTM的hidden state均为512维度,一个长度为nsentences的句子,经过ELMo预训练网络,最后得到的embedding的维度为:(n_sentences, 3, max_sentence_length, 1024)

那么下游任务如何利用这些表示呢?下游任务将所有表示都利用起来,并给他们分配权重,即为:

\mathbf{E} \mathbf{L} \mathbf{M} \mathbf{o}_{k}^{t a s k}=E\left(R_{k} ; \Theta^{t a s k}\right)=\gamma^{t a s k} \sum_{j=0}^{L} s_{j}^{t a s k} \mathbf{h}_{k, j}^{L M},\quad s_{j}^{t a s k}=e^{s_{j}} / \sum_{i}^{N} e^{s_{i}}

其中,  s^{t a s k} ​是经过softmax归一化之后的权重,标量参数 \gamma^{t a s k} ​允许任务模型缩放整个ELMo向量。需要注意的是,​ \gamma^{t a s k} 是一个超参数,实际上这个参数是经验参数,一定程度上能够增强模型的灵活性。总结起来,整个为下游任务获取embedding的过程即为:

利用ELMo预训练模型获取embedding的过程

4.ELMo的优点是什么?ELMo为什么有效?

ELMo利用了深度上下文单词表征,该模型的优点:

  • 引入双向语言模型,其实是 2 个单向语言模型(前向和后向)的集成;
  • 通过保存预训练好的 2 层 biLSTM,通过特征集成或 finetune 应用于下游任务;

总结来说,通过上述结构,ELMo能够达到区分多义词的效果,每个单词(token)不再是只有一个上下文无关的embedding表示。

那么ELMo为什么有效呢?我认为主要原因有以下几点:

  • 首先,ELMo的假设前提是一个词的词向量不应该是固定的,所以在多义词区分方面ELMo的效果必然比word2vec要好。
  • 另外,ELMo通过语言模型生成的词向量是通过特定上下文的“传递”而来,再根据下游任务,对原本上下文无关的词向量以及上下文相关的词向量表示引入一个权重,这样既在原来的词向量中引入了上下文的信息,又能根据下游任务适时调整各部分的权重(权重是在网络中学习得来的),因此这也是ELMo有效的一个原因。

5.ELMo为什么能够达到区分多义词的效果?

在ELMo第一阶段训练完成之后,将句子输入模型中在线提取各层embedding的时候,每个单词(token)对应两边LSTM网络的对应节点,那两个节点得到的embedding是动态改变的,会受到上下文单词的影响,周围单词的上下文不同应该会强化某种语义,弱化其它语义,这样就达到区分多义词的效果了。需要注意的是,第一个单词和最后一个单词也是有上下文的,譬如说第一个单词的上文是一个特殊的token <BOS>,下文是除第一个单词外的所有单词,最后一个单词的下文是一个特殊的token <EOS>,上文是除最后一个单词外的所有单词。

论文中也举例说明了这个问题,图示如下:

ELMo区分一词多义的例子

上图对于Glove训练出的word embedding来说,多义词比如play,根据它的embedding找出的最接近的其它单词大多数集中在体育领域,这很明显是因为训练数据中包含play的句子中体育领域的数量明显占优导致;而使用ELMo,根据上下文动态调整后的embedding不仅能够找出对应的“演出”的相同语义的句子,而且还可以保证找出的句子中的play对应的词性也是相同的,这是超出期待之处(当然也可能是因为论文中给出的例子都是比较好的例子,不过ELMo这样的做法是值得学习的)。

6.ELMo把三种不同的向量叠加的意义是什么?这样做能达到什么样的效果?

因为通过ELMo模型,句子中每个单词都能得到对应的三个Embedding:最底层是单词的Word Embedding,往上走是第一层双向LSTM中对应单词位置的Embedding,这层编码单词的句法信息更多一些;再往上走是第二层LSTM中对应单词位置的Embedding,这层编码单词的语义信息更多一些。需要注意的是,这里得到的结论是通过实验验证的,是在这样的模型设计中,能够得到上述结论,可能不同模型结构,得到的结论又是不一样的。

ELMo把三种不同的向量叠加的意义主要体现在以下两个点:

  • 一是之前很多方法都只用了最顶层LSTM的hidden state,但是通过实验验证,在很多任务中,将每一层hidden state融合在一起会取得更好的效果;
  • 二是在上述实验中得到结论,每一层LSTM得到单词的embedding所蕴含的信息是不一样的,因此将所有信息融合起来,会让单词embedding的表达更丰富。

这样做能够起到区分多义词的效果,如问题5,而且在论文展示的6个任务中都取得了SOTA的效果。

参考:

从Word Embedding到Bert模型—自然语言处理中的预训练技术发展史

The Illustrated BERT, ELMo, and co. (How NLP Cracked Transfer Learning)

ELMo-TensorFlow源码

发布于 2019-09-15

文章被以下专栏收录