1239 字
6 分钟
ELMo:上下文相关的动态词向量

静态词向量的局限#

Word2Vec、GloVe 和 fastText 都为每个词学一个固定向量。同一个词无论在什么句子里都使用同一个表示,因此无法区分多义词:

  • “bank”在“river bank”中是河岸,在“financial bank”中是银行;
  • “苹果”在“吃苹果”和“苹果发布会”中指代不同事物。

ELMo(Embeddings from Language Models)的做法是:先在大规模无标注语料上预训练一个双向语言模型,再把每个词在具体句子中的各层隐藏状态组合起来,作为该词的表示。词向量不再是查表结果,而是上下文和网络层数的函数。

TIP

以ELMo为代表的动态词向量模型是预训练语言模型的早期尝试:::

字符级表示#

ELMo 的输入不是词表索引,而是词的字符序列。对词 ww 的字符序列 [c1,…,ck],ci∈C[c_1,\dots,c_k],c_i \in \mathcal{C},先查字符向量嵌入:

vci=Wcharecivw=[vc1,…,vck]∈Rd×∣C∣\mathbf{v}_{c_i} = \mathbf{W}^{\text{char}} \mathbf{e}_{c_i}\\ \mathbf{v}_w=[\mathbf{v}_{c_1},\dots,\mathbf{v}_{c_k}] \in \mathbb{R}^{d \times |\mathcal{C}|}

其中:

  • vw\mathbf{v}_w:词 ww 的 字符向量 表示
  • ∣C∣|\mathcal{C}| : 字符库大小
  • dd:字符向量 嵌入维度
  • eci∈{0,1}∣C∣\mathbf{e}_{c_i}\in \{0,1\}^{|\mathcal{C}|}:字符的 one-hot 编码;
  • Wchar\mathbf{W}^{\text{char}}:字符嵌入矩阵。
例子

w=token→[c1=t,c2=o,c3=k,c4=e,c5=n]vw=[vt,vo,vk,ve,vn]←w=\text{token}\rightarrow[c_1=\text{t},c_2=\text{o},c_3=\text{k},c_4=\text{e},c_5=\text{n}] \\ \mathbf{v}_w = [\mathbf{v}_{t}, \mathbf{v}_{o}, \mathbf{v}_{k}, \mathbf{v}_{e}, \mathbf{v}_{n}]\leftarrow 词 ww 的字符向量表示

↓(convolution)\downarrow(convolution)

hw=[ht,ho,hk,he,hn]←\mathbf{h}_w = [\mathbf{h}_{t}, \mathbf{h}_{o}, \mathbf{h}_{k}, \mathbf{h}_{e}, \mathbf{h}_{n}] \leftarrow 词 ww 的字符卷积特征图

↓(max−pooling)\downarrow(max-pooling)

v^w←\mathbf{\hat{v}}_w \leftarrow 词 ww 的字符级表示

拿到了词的 字符向量 表示后,得到其 词级 表示的步骤如下:

  • 用多个不同宽度的 1D 卷积核提取不同长度的字符 n-gram 特征;
  • 对每个特征图做最大池化;
  • 拼接池化结果,得到词 ww 的字符级表示 v^w\hat{\mathbf{v}}_w。

字符级编码的好处是:即使某个词不在词表中,只要字符组合见过,仍能构造出有意义的表示,从而缓解 OOV 问题。

Highway 网络#

字符 CNN 的输出经过 Highway 网络:

vw=g(v^w)⊙v^w+(1−g(v^w))⊙Wprojv^w\mathbf{v}_w = g(\hat{\mathbf{v}}_w) \odot \hat{\mathbf{v}}_w + \big(1 - g(\hat{\mathbf{v}}_w)\big) \odot \mathbf{W}^{\text{proj}} \hat{\mathbf{v}}_wg(v^w)=σ(Wgatev^w+bgate)g(\hat{\mathbf{v}}_w) = \sigma(\mathbf{W}^{\text{gate}} \hat{\mathbf{v}}_w + \mathbf{b}^{\text{gate}})

门控 gg 在“直接保留输入”和“经过投影变换”之间做插值,类似残差连接,缓解深层网络的梯度问题。Wproj\mathbf{W}^{\text{proj}} 同时把字符级表示投影到目标维度。此时得到的 vw\mathbf{v}_w 仍是上下文无关的。

双向语言模型#

把句子 [w1,…,wn][w_1,\dots,w_n] 的词向量序列送入 LL 层双向 LSTM。前向和后向是两个独立的 LSTM,各自优化自己的语言模型目标,不共享参数,只在每个位置的输出端拼接。

前向语言模型建模序列概率:

P(w1,…,wn)=∏t=1nP(wt∣w1,…,wt−1)P(w_1,\dots,w_n) = \prod_{t=1}^{n} P(w_t \mid w_1,\dots,w_{t-1})

训练目标是最大化对数似然,等价于最小化:

Lforward=−∑t=1nlog⁡P(wt∣w1,…,wt−1)\mathcal{L}_{\text{forward}} = -\sum_{t=1}^{n} \log P(w_t \mid w_1,\dots,w_{t-1})

后向语言模型反过来,用右侧上下文预测当前词:

Lbackward=−∑t=1nlog⁡P(wt∣wt+1,…,wn)\mathcal{L}_{\text{backward}} = -\sum_{t=1}^{n} \log P(w_t \mid w_{t+1},\dots,w_n)

总损失为两者之和:

LELMo=Lforward+Lbackward\mathcal{L}_{\text{ELMo}} = \mathcal{L}_{\text{forward}} + \mathcal{L}_{\text{backward}}

注意前向和后向是分别训练的:

  • 前向:只看左侧上下文;
  • 后向:只看右侧上下文。

二者没有在同一个概率模型里联合归一化。它们提供的是两个方向的互补表示,而不是一个真正的双向联合似然。

多层表示与加权组合#

对第 tt 个词,LL 层 biLSTM 给出 2L+12L+1 个表示:

  • ht,0LM=vwt\mathbf{h}_{t,0}^{LM} = \mathbf{v}_{w_t}:字符 CNN 得到的上下文无关表示;
  • ht,jLM=[h→t,j;h←t,j]\mathbf{h}_{t,j}^{LM} = [\overrightarrow{\mathbf{h}}_{t,j}; \overleftarrow{\mathbf{h}}_{t,j}]:第 jj 层前向与后向隐藏状态的拼接,j=1,…,Lj=1,\dots,L。

不同层编码的信息不同:低层更偏向词形和句法,高层更偏向语义和语境。ELMo 不强制只用最后一层,而是让下游任务学习各层的权重:

ELMo⁡(wt)=γ∑j=0Lsjht,jLM\operatorname{ELMo}(w_t) = \gamma \sum_{j=0}^{L} s_j \mathbf{h}_{t,j}^{LM}

其中:

  • sjs_j:经 softmax 归一化的层权重;
  • γ\gamma:可学习的缩放标量。

下游任务可以把 ELMo 表示与原始词向量拼接:

xttask=[vwt;ELMo⁡(wt)]\mathbf{x}_t^{\text{task}} = [\mathbf{v}_{w_t}; \operatorname{ELMo}(w_t)]

使用方式与意义#

ELMo 采用“预训练 + 特征提取”的范式:预训练好的双向语言模型参数冻结,ELMo 表示作为额外特征输入下游模型。这与后来 BERT 的“预训练 + 微调”不同——BERT 会把整个预训练模型放到下游任务中继续训练。

ELMo 的意义在于:

  • 证明了大规模无标注语料上的语言模型预训练能学到通用语言知识;
  • 词表示从静态查表变成随上下文变化的动态表示;
  • 多层加权组合的思路影响了后续模型对中间层的利用。

局限也很明显:biLSTM 训练和推理都是串行的,长距离依赖仍受循环结构限制;前向和后向独立训练,无法在每一层同时利用完整上下文。这些限制促使后续模型转向 Transformer 和 BERT 的掩码语言模型。

相关阅读#

ELMo:上下文相关的动态词向量
https://biscuit0613.github.io/posts/nlp/06-06-elmo/
作者
Biscuit
发布于
2026-10-20
许可协议
CC BY-NC-SA 4.0
神经网络语言模型:NNLM 与 RNNLM
NLP 评价指标:从分类、回归到文本生成