ELMo模型计算详解
写在前面
本文记录本人在学习ELMo模型时的记录,具体为解析了在Google的开源实现中给出的源码中,论文中各个模块的输入输出维度变化。希望可以对读者学习ELMo模型时有些帮助。
另外,本章图片内容参考了b站up主自然卷小蛮的视频,在此声明(https://www.bilibili.com/video/BV12L411T7Vh)
ELMo(Embeddings from Language Models)是一个深度学习框架,用于生成上下文感知的词嵌入。这个模型由Allen Institute for Artificial Intelligence的研究人员在2018年开发,并在论文“Deep contextualized word representations”中提出。ELMo的出现标志着自然语言处理(NLP)技术在理解语言上下文和词义的深度方面迈出了重要的一步。
在ELMo之前,词向量技术如Word2Vec和GloVe已经能够捕获一定的语义信息,并在各种NLP任务中取得了显著的成功。然而,这些模型生成的是静态的词嵌入,即每个词在任何上下文中的表示都是固定不变的。这种静态表示无法解决词义消歧问题,也无法充分捕捉语言的复杂性和动态性。ELMo模型的出现旨在解决这一问题。
模型方法
ELMo 模型的网络的整体结构如下图所示。 输入是一个句子,将句子输入到 Character-aware highway encoder 字符编码层,然后经过两层双向 LSTM ,最后通过 softmax 层,然后得到预测的单词结果或者进行损失计算。
ELMo模型输入
ELMo模型的输入是一个句子,例如"She opened her book."。由于在Character-aware highway encoder中我们会详细处理单词并提取其特征,所以这里我们将句子作为ELMo模型的输入传入到Character-aware highway encoder层中。
Character-aware highway encoder
character-CNN
我们首先来看 Character-aware highway encoder 层,总体结构如图下所示。
Character-CNN层的输入是单个单词的字符序列。我们会对每个单词进行处理得到固定维度的向量,然后使用CNN卷积进行特征提取。下面进行依次介绍。char-CNN展开后的模型细节如图所示。
首先,每个字符通过字符嵌入(character embeddings)被转换为固定维度的向量。设字符总数为
n
n
n,字符嵌入的维度为
d
d
d,单词最多由
L
L
L个字符组成,句子最多有
k
k
k个单词,则输入的每个单词将会转化成矩阵
V
c
h
a
r
n
e
w
∈
R
L
×
d
V_{char}^{new} \in \mathbb{R}^{L \times d}
Vcharnew∈RL×d。具体来说,将每个字符用one-hot的方式进行表示,每个字符就是
n
×
1
n \times 1
n×1维的向量,我们通过线性变换,将每个字符的维度从
n
n
n压缩为
d
d
d,然后限定单词的最大字符数,即可把每个单词的维度固定为
d
×
L
d \times L
d×L,即
V
c
h
a
r
n
e
w
=
V
c
h
a
r
o
n
e
−
h
o
t
W
c
+
b
c
V_{char}^{new} = V_{char}^{one-hot} W_c + b_c
Vcharnew=Vcharone−hotWc+bc
其中
W
c
∈
R
n
×
d
W_c \in \mathbb{R}^{n \times d}
Wc∈Rn×d 是对应的权重矩阵,
b
c
∈
R
d
×
1
b_c \in \mathbb{R}^{d \times 1}
bc∈Rd×1 为权重矩阵
W
c
W_c
Wc对应的置偏值,
V
c
h
a
r
o
n
e
−
h
o
t
∈
R
d
×
n
V_{char}^{one-hot} \in \mathbb{R}^{d \times n}
Vcharone−hot∈Rd×n为字符的one-hot向量,
V
c
h
a
r
n
e
w
V_{char}^{new}
Vcharnew为
V
c
h
a
r
o
n
e
−
h
o
t
V_{char}^{one-hot}
Vcharone−hot从维度
n
×
1
n \times 1
n×1 映射为维度
d
×
1
d \times 1
d×1后的字符的向量,通常
n
>
d
n > d
n>d。
这种字符嵌入的方式与Word2Vec中的两种词嵌入方式不同,Word2Vec中的两种方法都是把 单词 转换为one-hot向量,而在ELMo的输入中,将 字符 转换为one-hot向量,使用矩阵表示单词,这样可以从字符层面挖掘单词的特征。
通过上面的字符嵌入,我们就可以用字符的向量来构建单词的向量。在ELMo中,规定一个单词的最大字符个数不超过
L
L
L,超过
L
L
L时会进行截断,不足
L
L
L时会使用特殊字符的字符编码进行末尾填充。这样我们可以用
V
w
o
r
d
∈
R
d
×
L
V_{word} \in \mathbb{R}^{d \times L}
Vword∈Rd×L表示一个单词,即
V
w
o
r
d
=
V
t
=
[
V
c
h
a
r
1
n
e
w
,
V
c
h
a
r
2
n
e
w
,
…
,
V
c
h
a
r
L
n
e
w
]
=
[
V
c
h
a
r
1
o
n
e
−
h
o
t
,
V
c
h
a
r
2
o
n
e
−
h
o
t
,
…
,
V
c
h
a
r
L
o
n
e
−
h
o
t
]
W
c
+
b
c
V_{word} = V_{t} = [V_{char1}^{new},V_{char2}^{new},\dots, V_{charL}^{new}] = [V_{char1}^{one-hot},V_{char2}^{one-hot}, \dots, V_{charL}^{one-hot}]W_c + b_c
Vword=Vt=[Vchar1new,Vchar2new,…,VcharLnew]=[Vchar1one−hot,Vchar2one−hot,…,VcharLone−hot]Wc+bc
V
w
o
r
d
=
[
v
1
,
1
w
o
r
d
v
1
,
2
w
o
r
d
…
v
1
,
L
w
o
r
d
v
2
,
1
w
o
r
d
v
2
,
2
w
o
r
d
…
v
2
,
L
w
o
r
d
…
…
…
…
v
d
,
1
w
o
r
d
v
d
,
2
w
o
r
d
…
v
d
,
L
w
o
r
d
]
V_{word} = \left[\begin{matrix} v_{1,1}^{word} & v_{1,2}^{word} & \dots & v_{1,L}^{word} \\ v_{2,1}^{word} & v_{2,2}^{word} & \dots & v_{2,L}^{word} \\ \dots & \dots & \dots & \dots \\ v_{d,1}^{word} & v_{d,2}^{word} & \dots & v_{d,L}^{word} \\ \end{matrix}\right]
Vword=
v1,1wordv2,1word…vd,1wordv1,2wordv2,2word…vd,2word…………v1,Lwordv2,Lword…vd,Lword
其中,
V
c
h
a
r
i
n
e
w
V_{chari}^{new}
Vcharinew是单词中第
i
i
i个字符的嵌入向量。这样我们就完成了character-embedding的过程。
V
w
o
r
d
=
V
t
V_{word} = V_{t}
Vword=Vt 表示当前输入的第
t
t
t个单词的单词矩阵。
下面介绍AllenNLP中实现的ELMo,character-embedding处理的方式。
在AllenNLP的ELMo的character-embedding中,利用Unicode 字符级对单词的每个字符进行编码。在Unicode 字符集中 0 − 255 0-255 0−255共有 256 256 256个字符,加上(单词的开始)、(单词的结束)、 (句子的开始)、(句子的结束)、(单词补齐符)和(句子补齐符)这 6 6 6个特殊字符,一共有 262 262 262个字符,构成了字符集表示中的字符表,即 n = 262 n = 262 n=262。ELMo的思想是给每个字符生成一个固定维度地随机向量,在AllenNLP的ELMo的character-embedding实现中,这 262 262 262 个字符向量会被固定为维度为 16 × 1 16 \times 1 16×1(字符嵌入维度为 16 16 16, d = 16 d = 16 d=16)的向量,采用的方法是将 262 262 262 个字符以one-hot向量的形式进行表示,随后通过线性变换的形式转为换固定维度为 16 × 1 16 \times 1 16×1的向量。
在AllenNLP的ELMo实现中, L = 50 L = 50 L=50、 n = 262 n = 262 n=262、 d = 16 d = 16 d=16,我们以单词 opened 为例子,首先将其分解成 ‘o’,‘p’,‘e’,‘n’,‘e’,‘d’,共 6 6 6个字符,分别使用相应的字符向量表示,由于单词向量使用 50 50 50个字符向量固定,后面 44 44 44个 字符均使用填充,这样我们就将其固定成字符数量大小为 50 50 50 。于是我们就可以完成 opened 这个单词的编码。此时单词的维度$ 16 \times 50$。这里由于AllenNLP中的嵌入维度较大不方便展示,简单的嵌入例子参考章节ELMo-demo简单的ELMo例子中的字符嵌入过程。
CNN
对于一个句子经过 character-embedding 之后,就会进入 CNN 层,CNN 的核心是使用卷积神经网络。我们考虑一个单词,其字符表示为
v
w
o
r
d
v_{word}
vword,
v
w
o
r
d
v_{word}
vword是一个
d
×
L
d \times L
d×L的矩阵
d
d
d是每个字符的嵌入维度,
L
L
L是单词的最大长度,则我们可以定义卷积操作:
对于给定卷积核
K
K
K,
K
=
[
K
1
,
K
2
,
…
,
K
f
]
,
K
j
=
[
k
1
,
1
,
j
k
1
,
2
,
j
…
k
1
,
w
,
j
k
2
,
1
,
j
k
2
,
2
,
j
…
k
2
,
w
,
j
…
…
…
…
k
d
,
1
,
j
k
d
,
2
,
j
…
k
d
,
w
,
j
]
K = [K_1, K_2, \dots, K_f] , \quad K_j = \left[\begin{matrix} k_{1,1,j} & k_{1,2,j} & \dots & k_{1,w,j} \\ k_{2,1,j} & k_{2,2,j} & \dots & k_{2,w,j} \\ \dots & \dots & \dots & \dots \\ k_{d,1,j} & k_{d,2,j} & \dots & k_{d,w,j} \end{matrix}\right]
K=[K1,K2,…,Kf],Kj=
k1,1,jk2,1,j…kd,1,jk1,2,jk2,2,j…kd,2,j…………k1,w,jk2,w,j…kd,w,j
其尺寸为
d
×
w
×
f
d\times w \times f
d×w×f,其中:
- K K K表示卷积核矩阵集合(张量), K j K_j Kj表示卷积核矩阵, k d , w , j k_{d,w,j} kd,w,j表示卷积核矩阵中各个位置的元素值。
- d d d是卷积核覆盖的字符嵌入维度(与输入维度相匹配),
- w w w是卷积核的宽度(覆盖的字符数) ,
- f f f是该卷积核输出的特征数量(或称为过滤器数量)。
- j = 1 , 2 , … , f j = 1, 2, \dots, f j=1,2,…,f。
卷积操作的输出
c
c
c对于每个特征图
j
j
j的每个位置
i
i
i在单词长度方向上可以表示为:
c
i
,
j
=
∑
m
=
1
d
∑
n
=
1
w
v
m
,
n
w
o
r
d
k
m
,
n
,
j
+
b
c
n
n
j
c_{i, j} = \sum_{m = 1}^{d} \sum_{n = 1}^{w} v^{word}_{m,n} k_{m,n,j} + b_{cnn}^{j}
ci,j=m=1∑dn=1∑wvm,nwordkm,n,j+bcnnj
这里,
b
C
N
N
j
∈
R
b_{CNN}^{j} \in \textbf{R}
bCNNj∈R是与过滤器
K
j
K_j
Kj关联的偏置项。输出的维度
c
c
c为
(
L
−
w
+
1
)
×
f
(L - w + 1) \times f
(L−w+1)×f,假设没有填充(padding)和步长(stride)为
1
1
1。
在卷积后进行最大池化操作,最大池化在每个特征图上独立进行,选取每个特征图中的最大值。对于每个过滤器
K
j
K_j
Kj,池化操作可表示为
c
^
j
=
max
(
c
1
,
j
,
c
2
,
j
,
…
,
c
L
−
w
+
1
,
j
)
,
(
j
=
1
,
2
,
…
,
f
)
\hat{c}_j = \max(c_{1,j}, c_{2,j}, \dots, c_{L- w + 1, j}), \quad (j = 1, 2, \dots, f)
c^j=max(c1,j,c2,j,…,cL−w+1,j),(j=1,2,…,f)
最终,池化后的所有特征
c
^
j
\hat{c}_j
c^j被拼接起来形成一个特征向量
y
y
y,用作单词的嵌入表示:
y
t
=
(
c
^
1
,
c
^
2
,
…
,
c
^
F
)
y_t = (\hat{c}_1, \hat{c}_2, \dots, \hat{c}_F)
yt=(c^1,c^2,…,c^F)
其中
F
F
F是过滤器的总数量(每个卷积核的过滤器相加求和得到总的过滤器数量),则
Y
=
[
y
1
,
y
2
,
…
,
y
t
,
…
,
y
n
]
Y = [y_1, y_2, \dots, y_t, \dots, y_n]
Y=[y1,y2,…,yt,…,yn]为
F
×
n
F \times n
F×n维向量。随后,我们将一个个的单词向量
y
t
y_t
yt传入 highway-connection层。
在AllenNLP的ELMo的character-CNN中,包含了 7 种过滤器,分别是 16 × \times × 1 × \times × 32、16 × \times × 2 × \times × 32、16 × \times × 3 × \times × 64、16 × \times × 4 × \times × 128、16 × \times × 5 × \times × 256、16 × \times × 6 × \times × 512、16 × \times × 7 × \times × 1024。过滤器尺寸依次为32、32、64、128、256、512、1024。
通过卷积层后通过池化层,顺着 1 1 1 这一维度进行取最大(MaxPool)也就是将 16 行(在图中就是纵向压缩)通过取最大压缩成 1 1 1 行,也就是将 16 × 50 16 \times 50 16×50 通过池化(取最大)变成 1 × 50 1 \times 50 1×50。我们将得到一个个的 vector 顺着 1 1 1 这一维度进行拼接,可以得到一个 1 × 2048 1 \times 2048 1×2048 的 vector。
highway-connection
接下来是两层的 highway-connection,Highway 网络层的输出是经过门控调节的特征表示,这些表示为后续层(如双向LSTM层)提供了更加精细调整的输入,对于每个时间步的输入是 y t y_t yt。输出的特点包括:
- 保留与变换:Highway层通过两个主要的门控机制实现信息的保留与变换——一个是变换门(T门),另一个是携带门(C门)。变换门控制有多少当前层的原始信息需要被变换,而携带门控制有多少原始信息需要不加修改地传递到下一层。
- 门控特征表示:因此,Highway层的输出是原始输入特征的一个门控版本,其中一部分特征被保留并直接传递,而另一部分特征经过变换以提供额外的信息或调整。
变换门:
T
=
σ
(
W
T
y
t
+
b
T
)
T = \sigma(W_Ty_t + b_T)
T=σ(WTyt+bT)
其中 σ \sigma σ 是sigmoid激活函数,确保输出在0和1之间,表示每个特征的转换程度。 y t ∈ R p × 1 y_t \in \mathbb{R}^{p \times 1} yt∈Rp×1 是输入特征, W T ∈ R p × p W_T \in \mathbb{R}^{p \times p} WT∈Rp×p和 b T ∈ R p × 1 b_T \in \mathbb{R}^{p \times 1} bT∈Rp×1 是变换门的权重和偏置, T ∈ R p × 1 T \in \mathbb{R}^{p \times 1} T∈Rp×1。
携带门:
C
=
1
−
T
C = 1 - T
C=1−T
携带门的计算很简单,就是1减去变换门的输出,确保变换和携带的总和为1,这样可以保持信息的完整性,
C
∈
R
p
×
1
C \in \mathbb{R}^{p \times 1}
C∈Rp×1。
输出:
z
t
=
T
⊙
g
(
W
H
y
t
+
b
H
)
+
C
⊙
y
t
z_t = T \odot g(W_Hy_t + b_H) + C \odot y_t
zt=T⊙g(WHyt+bH)+C⊙yt
其中,
y
t
∈
R
p
×
1
y_t \in \mathbb{R}^{p \times 1}
yt∈Rp×1 是输入特征,
W
H
∈
R
p
×
p
W_H \in \mathbb{R}^{p \times p}
WH∈Rp×p是变换操作的权重,
b
H
∈
R
p
×
1
b_H \in \mathbb{R}^{p \times 1}
bH∈Rp×1为对应的置偏值,
g
(
W
H
y
t
+
b
H
)
g(W_Hy_t + b_H)
g(WHyt+bH)
是对输入
y
t
y_t
yt 的非线性变换(通常是ReLU激活函数),
T
T
T是变换门的激活,
C
C
C是携带门的激活,而
z
t
∈
R
p
×
1
z_t \in \mathbb{R}^{p \times 1}
zt∈Rp×1 是该 Highway 层的输出,
⊙
\odot
⊙ 是点乘。
通过这样的设计,Highway 层使得网络能够自适应地调节信息的流动,既能保留对后续处理有用的重要信息,也能对输入特征进行必要的变换,这对于深层次的语义理解尤为重要。
在AllenNLP的ELMo中,进行运算完highway-connection后我们得到结果还是 1 × 2048 1 \times 2048 1×2048 的 vector。最后的 MLP 层就是一层线性映射,将维度为 2048 2048 2048 的 vector 压缩成 512 512 512 维的 vector。
MLP
MLP在此处就是对highway-connection得到的特征进行压缩,然后输入给双向LSTM,具体来说就是一个简单的线性映射,即
u
t
=
W
c
h
a
r
−
c
n
n
−
m
l
p
z
t
+
b
c
h
a
r
−
c
n
n
−
m
l
p
u_t = W_{char-cnn-mlp}z_t + b_{char-cnn-mlp}
ut=Wchar−cnn−mlpzt+bchar−cnn−mlp
其中,
z
t
∈
R
p
×
1
z_t \in \mathbb{R}^{p \times 1}
zt∈Rp×1是输入特征。假设需要映射到的维度大小是
m
m
m,则
u
t
∈
R
m
×
1
u_t \in \mathbb{R}^{m \times 1}
ut∈Rm×1,
W
c
h
a
r
−
c
n
n
−
m
l
p
∈
R
m
×
p
W_{char-cnn-mlp} \in \mathbb{R}^{m \times p}
Wchar−cnn−mlp∈Rm×p和
b
c
h
a
r
−
c
n
n
−
m
l
p
∈
R
m
×
1
b_{char-cnn-mlp} \in \mathbb{R}^{m \times 1}
bchar−cnn−mlp∈Rm×1是该全连接层的权重矩阵和置偏。
在AllenNLP的ELMo的此处的MLP中,使用 MLP 对 1 × \times × 2048 的 vector 进行处理,得到 1 × \times × 2048 的 vector 作为输入进入双向 LSTM 层。
bidrectional LSTM
接下来就是 ELMo 的核心,两层双向 LSTM。双层双向LSTM得输入是上层输出的单词向量得集合,即
U
=
(
u
1
,
u
2
,
…
,
u
n
)
U = (u_1, u_2, \dots, u_n)
U=(u1,u2,…,un)
其中
u
t
∈
R
m
×
1
u_t \in \mathbb{R}^{m \times 1}
ut∈Rm×1 表示当前单词的向量表示(或者当前时刻单词的向量表示),
n
n
n表示一共有多少个单词(有多少个时刻),且
U
∈
R
m
×
n
U \in \mathbb{R}^{m \times n}
U∈Rm×n。
双向LSTM结构包括前向和后向两个LSTM网络,能够捕获上下文信息。我们从LSTM再到双向LSTM对其进行描述,具体如下一小结。
LSTM
我们先简单回忆LSTM的结构与计算方法。LSTM的模型结构如图\ref{ELMo-LSTM}所示。
u
t
u_t
ut 是时间步
t
t
t 的输入,维度为
m
×
1
m \times 1
m×1 ,
h
t
h_t
ht表示当前时刻隐藏层输入,
c
t
c_t
ct表示当前时刻当前状态单元
W
f
W_f
Wf,
b
f
b_f
bf,
W
i
W_i
Wi,
b
i
b_i
bi,
W
C
W_C
WC,
b
C
b_C
bC,
W
o
W_o
Wo,
b
o
b_o
bo分别为LSTM层各个门和模块的权重矩阵和置偏,
h
0
h_0
h0、
c
0
c_0
c0通常初始化为
0
0
0向量,权重矩阵和置偏通常随机初始化。
遗忘门(Forget Gate)
遗忘门的计算公式为
f
t
=
σ
(
W
f
⋅
[
h
t
−
1
,
u
t
]
+
b
f
)
f_t = \sigma(W_f \cdot [h_{t-1}, u_t] + b_f)
ft=σ(Wf⋅[ht−1,ut]+bf)
其中,
W
f
W_f
Wf 是权重矩阵,维度为
h
×
(
h
+
m
)
h \times (h + m)
h×(h+m),
b
f
b_f
bf 是偏置,维度为
h
×
1
h \times 1
h×1,
h
h
h是隐藏层维度,
σ
\sigma
σ 是sigmoid函数。
输入门(Input Gate)
输入门的计算公式为
i
t
=
σ
(
W
i
⋅
[
h
t
−
1
,
u
t
]
+
b
i
)
i_t = \sigma(W_i \cdot [h_{t-1}, u_t] + b_i)
it=σ(Wi⋅[ht−1,ut]+bi)
c
~
t
=
tanh
(
W
C
⋅
[
h
t
−
1
,
u
t
]
+
b
C
)
\tilde{c}_t = \tanh(W_C \cdot [h_{t-1}, u_t] + b_C)
c~t=tanh(WC⋅[ht−1,ut]+bC)
W
i
W_i
Wi 和
W
C
W_C
WC 是权重矩阵,维度为
h
×
(
h
+
m
)
h \times (h + m)
h×(h+m),
b
i
b_i
bi 和
b
C
b_C
bC 是偏置,维度为
h
×
1
h \times 1
h×1。
单元状态更新
单元状态更新计算公式为
c
t
=
f
t
⊙
c
t
−
1
+
i
t
⊙
c
~
t
c_t = f_t \odot c_{t-1} + i_t \odot \tilde{c}_t
ct=ft⊙ct−1+it⊙c~t
c
t
c_t
ct 和
c
t
−
1
c_{t-1}
ct−1 的维度为
h
×
1
h \times 1
h×1。
输出门(Output Gate)
输出门的计算公式为
o
t
=
σ
(
W
o
⋅
[
h
t
−
1
,
u
t
]
+
b
o
)
o_t = \sigma(W_o \cdot [h_{t-1}, u_t] + b_o)
ot=σ(Wo⋅[ht−1,ut]+bo)
h
t
=
o
t
⊙
tanh
(
c
t
)
h_t = o_t \odot \tanh(c_t)
ht=ot⊙tanh(ct)
W
o
W_o
Wo 是权重矩阵,维度为
h
×
(
h
+
m
)
h \times (h + m)
h×(h+m),
b
o
b_o
bo 是偏置,维度为
h
×
1
h \times 1
h×1。
以上就是LSTM模块的计算,理解了单个LSTM的计算我们就可以进一步计算双向LSTM和双层双向LSTM。为了方便表示,我们将计算过程封装为
h
t
=
LSTM
(
u
t
,
h
t
−
1
)
h_t = \text{LSTM}(u_t, h_{t - 1})
ht=LSTM(ut,ht−1)
双向结构
双向LSTM的模型结构如图下所示,在ELMo模型的bidLSTM中的LSTM模块的输入 u t u_t ut 是时间步 t t t 的字符嵌入或词嵌入,维度为 m × 1 m \times 1 m×1 , h → t \overrightarrow{h}_t ht表示当前时刻正向LSTM隐藏层输入, h ← t \overleftarrow{h}_t ht 表示当前时刻反向LSTM隐藏层输入,其维度为 m × 1 m \times 1 m×1,通常正向的隐藏层 h → 0 \overrightarrow{h}_0 h0和反向的隐藏层 h ← t \overleftarrow{h}_t ht均随机初始化或者初始化为值全为 0 0 0的向量或者值全为 1 1 1的向量。 u t u_t ut通过与 h → t − 1 \overrightarrow{h}_{t-1} ht−1拼起来构成LSTM的输入,传入正向的LSTM,进行LSTM中的步骤计算,输出 h → t \overrightarrow{h}_{t} ht传入后一个LSTM模块,不断迭代,将每个时间步的隐藏层输出 h → t \overrightarrow{h}_{t} ht序列作为该正向LSTM模块的输出。同理, u t u_t ut通过与 h ← t + 1 \overleftarrow{h}_{t+1} ht+1拼起来构成LSTM的输入,传入正向的LSTM,进行LSTM中的步骤计算,输出 h ← t \overleftarrow{h}_{t} ht传入前一个LSTM模块,不断迭代,将每个时间步的隐藏层输出 h ← t \overleftarrow{h}_{t} ht序列作为该反向LSTM模块的输出。
对于每一个
u
t
u_t
ut,正向LSTM计算表示为
h
→
t
=
LSTM
+
(
h
→
t
−
1
,
u
t
)
\overrightarrow{h}_{t} = \text{LSTM}_{+}(\overrightarrow{h}_{t-1}, u_t)
ht=LSTM+(ht−1,ut)
其中
h
t
→
\overrightarrow{h_t}
ht、
h
t
−
1
→
∈
R
m
×
1
\overrightarrow{h_{t-1}} \in \mathbb{R}^{m \times 1}
ht−1∈Rm×1,
LSTM
+
\text{LSTM}_{+}
LSTM+表示正向的LSTM运算。
对于每一个
u
t
u_t
ut,反向LSTM计算表示为
h
←
t
=
LSTM
−
(
h
←
t
+
1
,
u
t
)
\overleftarrow{h}_{t} = \text{LSTM}_{-}(\overleftarrow{h}_{t+1}, u_t)
ht=LSTM−(ht+1,ut)
其中
h
t
←
\overleftarrow{h_t}
ht、
h
t
−
1
←
∈
R
m
×
1
\overleftarrow{h_{t-1}} \in \mathbb{R}^{m \times 1}
ht−1∈Rm×1,
LSTM
−
\text{LSTM}_{-}
LSTM−表示正向的LSTM运算。
于是有
- 前向LSTM从左到右处理输入序列,生成隐藏状态序列 h → 1 , h → 2 , … , h → n \overrightarrow{h}_1, \overrightarrow{h}_2, \dots, \overrightarrow{h}_n h1,h2,…,hn.
- 后向LSTM从右到左处理输入序列,生成隐藏状态序列 h ← 1 , h ← 2 , … , h ← n \overleftarrow{h}_1, \overleftarrow{h}_2, \dots, \overleftarrow{h}_n h1,h2,…,hn.
我们将结果记为
H
→
=
[
h
→
1
,
h
→
2
,
…
,
h
→
n
]
\overrightarrow{H} = [\overrightarrow{h}_1, \overrightarrow{h}_2, \dots, \overrightarrow{h}_n]
H=[h1,h2,…,hn]
H
←
=
[
h
←
1
,
h
←
2
,
…
,
h
←
n
]
\overleftarrow{H} = [\overleftarrow{h}_1, \overleftarrow{h}_2, \dots, \overleftarrow{h}_n]
H=[h1,h2,…,hn]
其中
h
←
t
\overleftarrow{h}_t
ht、
h
→
t
∈
R
m
×
1
\overrightarrow{h}_t\in \mathbb{R}^{m \times 1}
ht∈Rm×1,
H
←
\overleftarrow{H}
H、
H
→
∈
R
m
×
n
\overrightarrow{H} \in \mathbb{R}^{m \times n}
H∈Rm×n
双层双向LSTM
在ELMo中并不是简单地设置一层双向LSTM,而是使用两层。具体计算方式是将第一层双向LSTM中得到的正向LSTM的隐藏层向量传入第二层正向的LSTM,将第一层的双向LSTM中的得到的反向LSTM的隐藏层向量传入第二层反向的LSTM。ELMo中的双层双向LSTM如图\ref{ELMo-double-ward-Bid-LSTM}所示。
与上面计算第一层的双向LSTM类似,我们用公式进行描述对于每一个
h
→
t
\overrightarrow{h}_{t}
ht,正向LSTM计算表示为
h
→
t
n
e
w
=
LSTM
+
(
h
→
t
−
1
n
e
w
,
h
→
t
)
\overrightarrow{h}_{t}^{new} = \text{LSTM}_{+}(\overrightarrow{h}_{t-1}^{new},\overrightarrow{h}_{t})
htnew=LSTM+(ht−1new,ht)
其中
h
t
→
n
e
w
\overrightarrow{h_t}^{new}
htnew、
h
t
−
1
n
e
w
→
∈
R
m
×
1
\overrightarrow{h_{t-1}^{new}} \in \mathbb{R}^{m \times 1}
ht−1new∈Rm×1,
LSTM
+
\text{LSTM}_{+}
LSTM+表示正向的LSTM运算。
对于每一个
h
←
t
\overleftarrow{h}_{t}
ht,反向LSTM计算表示为
h
←
t
n
e
w
=
LSTM
−
(
h
←
t
+
1
n
e
w
,
h
←
t
)
\overleftarrow{h}_{t}^{new} = \text{LSTM}_{-}(\overleftarrow{h}_{t+1}^{new}, \overleftarrow{h}_{t})
htnew=LSTM−(ht+1new,ht)
其中
h
t
←
n
e
w
\overleftarrow{h_t}^{new}
htnew、
h
t
←
n
e
w
∈
R
m
×
1
\overleftarrow{h_t}^{new} \in \mathbb{R}^{m \times 1}
htnew∈Rm×1,
LSTM
−
\text{LSTM}_{-}
LSTM−表示正向的LSTM运算。
于是有
- 前向LSTM从左到右处理输入序列将上面生成的第一层隐藏状态传递给下一层,生成隐藏状态序列 h → 1 n e w , h → 2 n e w , … , h → n n e w \overrightarrow{h}_1^{new}, \overrightarrow{h}_2^{new}, \dots, \overrightarrow{h}_n^{new} h1new,h2new,…,hnnew.
- 后向LSTM从右到左处理输入序列将上面生成的第一层隐藏状态传递给下一层,生成隐藏状态序列 h ← 1 n e w , h ← 2 n e w , … , h ← n n e w \overleftarrow{h}_1^{new}, \overleftarrow{h}_2^{new}, \dots, \overleftarrow{h}_n^{new} h1new,h2new,…,hnnew.
我们将结果记为
H
→
n
e
w
=
[
h
→
1
n
e
w
,
h
→
2
n
e
w
,
…
,
h
→
n
n
e
w
]
\overrightarrow{H}^{new} = [\overrightarrow{h}_{1}^{new}, \overrightarrow{h}_{2}^{new}, \dots, \overrightarrow{h}_{n}^{new}]
Hnew=[h1new,h2new,…,hnnew]
H
←
n
e
w
=
[
h
←
1
n
e
w
,
h
←
2
n
e
w
,
…
,
h
←
n
n
e
w
]
\overleftarrow{H}^{new} = [\overleftarrow{h}_{1}^{new}, \overleftarrow{h}_{2}^{new}, \dots, \overleftarrow{h}_{n}^{new}]
Hnew=[h1new,h2new,…,hnnew]
其中
h
←
t
n
e
w
\overleftarrow{h}_{t}^{new}
htnew、
h
→
t
n
e
w
∈
R
m
×
1
\overrightarrow{h}_{t}^{new}\in \mathbb{R}^{m \times 1}
htnew∈Rm×1,
H
←
n
e
w
\overleftarrow{H}^{new}
Hnew、
H
→
n
e
w
∈
R
m
×
n
\overrightarrow{H}^{new} \in \mathbb{R}^{m \times n}
Hnew∈Rm×n
bid-LSTM输出
在通常情况下,最终输出
S
=
[
s
1
⃗
,
s
2
⃗
,
…
,
s
2
m
⃗
]
S = [\vec{s_1}, \vec{s_2}, \dots, \vec{s_{2m}}]
S=[s1,s2,…,s2m] 是对前面的双层双向LSTM进行了如下操作:
对于每个时间步,将两层得到的正向LSTM的隐藏层输出与反向LSTM的隐藏层输出相加,即
h
→
t
+
h
→
t
n
e
w
,
h
←
t
+
h
←
t
n
e
w
\overrightarrow{h}_t + \overrightarrow{h}_t^{new}, \quad \overleftarrow{h}_t + \overleftarrow{h}_t^{new}
ht+htnew,ht+htnew
然后再将得到的结果拼成一个更长的向量得到结果,即
s
t
⃗
=
[
h
→
t
+
h
→
t
n
e
w
;
h
←
t
+
h
←
t
n
e
w
]
\vec{s_t} = [\overrightarrow{h}_t + \overrightarrow{h}_t^{new}; \overleftarrow{h}_t + \overleftarrow{h}_t^{new}]
st=[ht+htnew;ht+htnew]
如果每个方向的隐藏状态维度为
m
m
m,则
s
t
⃗
\vec{s_t}
st 的维度为
2
m
×
1
2m \times 1
2m×1。
于是我们得到
S
=
[
s
1
⃗
,
s
2
⃗
,
…
,
s
2
m
⃗
]
S = [\vec{s_1}, \vec{s_2}, \dots, \vec{s_{2m}}]
S=[s1,s2,…,s2m]
其中
s
t
⃗
∈
R
2
m
×
1
\vec{s_t} \in \mathbb{R}^{2m \times 1}
st∈R2m×1,
S
∈
R
2
m
×
n
S \in \mathbb{R}^{2m \times n}
S∈R2m×n
MLP and Softmax
为了得到对应的单词,我们通过一层线性映射,将单词向量表示转换为高维的表示,然后通过Softmax得到每个时刻
t
t
t单词的概率分布,从而得到要预测的单词。即对于每一个时间步
q
t
⃗
=
W
s
s
t
⃗
+
b
s
\vec{q_t} = W_s \vec{s_t} + b_s
qt=Wsst+bs
其中,
q
t
⃗
∈
R
V
×
1
\vec{q_t} \in \mathbb{R}^{V \times 1}
qt∈RV×1为映射后的向量、
W
s
∈
R
V
×
2
h
W_s \in \mathbb{R}^{V \times 2h}
Ws∈RV×2h为映射的权重矩阵、
b
s
∈
R
V
×
1
b_s \in \mathbb{R}^{V \times 1}
bs∈RV×1为对应的置偏,
V
V
V为单词表的维度。
写成矩阵的形式为
Q
=
W
s
S
+
b
s
Q = W_s S + b_s
Q=WsS+bs
其中,
Q
=
[
q
1
⃗
,
q
2
⃗
,
…
,
q
n
⃗
]
∈
R
V
×
n
Q = [\vec{q_1}, \vec{q_2}, \dots, \vec{q_n}] \in \mathbb{R}^{V \times n}
Q=[q1,q2,…,qn]∈RV×n,
q
t
⃗
∈
R
V
×
1
\vec{q_t} \in \mathbb{R}^{V \times 1}
qt∈RV×1,
S
∈
R
2
m
×
n
S \in \mathbb{R}^{2m \times n}
S∈R2m×n,
s
t
⃗
∈
R
2
m
×
1
\vec{s_t} \in \mathbb{R}^{2m \times 1}
st∈R2m×1。
随后我们使用Softmax将向量
q
t
⃗
=
[
q
1
,
q
2
,
…
,
q
V
]
T
\vec{q_t} = [q_1, q_2, \dots, q_V]^T
qt=[q1,q2,…,qV]T转换为概率分布向量
p
i
⃗
\vec{p_i}
pi,即
p
i
⃗
=
Softmax
(
q
i
⃗
)
=
exp
(
q
i
)
∑
k
=
1
V
exp
(
q
k
)
\vec{p_i} = \text{Softmax}(\vec{q_i}) = \frac{\exp(q_i)}{ \sum\limits_{k=1}^{V} \exp(q_k)}
pi=Softmax(qi)=k=1∑Vexp(qk)exp(qi)
其中,
q
t
⃗
∈
R
V
×
1
\vec{q_t} \in \mathbb{R}^{V \times 1}
qt∈RV×1为映射后的向量、
p
t
⃗
∈
R
V
×
1
\vec{p_t} \in \mathbb{R}^{V \times 1}
pt∈RV×1为转换为概率分布后的向量。
写成矩阵的形式为
P
=
(
p
1
⃗
,
p
2
⃗
,
…
,
p
n
⃗
)
P = (\vec{p_1},\vec{p_2}, \dots, \vec{p_n})
P=(p1,p2,…,pn)
其中
p
t
⃗
∈
R
V
×
1
\vec{p_t} \in \mathbb{R}^{V \times 1}
pt∈RV×1 为每个单词对应位置的词向量表示的概率分布,
P
∈
R
V
×
n
P \in \mathbb{R}^{V \times n}
P∈RV×n为整个句子的矩阵向量。
ELMo模型输出
实际上MLP and Softmax层输出的概率分布矩阵实际上就是ELMo模型的输出,即上下文感知的表示。通过这个概率分布,我们可以从词汇表中查出需要预测的单词。
损失函数
在计算得到bid-LSTM的结果之后,我们将得到的词向量表示映射到整个单词集合,然后使用Softmax计算概率分布,然后使用交叉熵来计算ELMo模型的损失。
在此处的Softmax运算之前,由于我们的在双向LSTM中的输出维度是
2
h
2h
2h,我们要将其映射为词汇表的维度
V
V
V,随后我们使用softmax将向量q转换为概率分布,最后使用交叉熵损失来计算ELMo模型的损失,即正确的标签为one-hot向量,然后与预测的向量一起进行交叉熵损失计算,得到每一时刻的损失,即
Loss
t
=
−
∑
i
=
1
V
t
a
g
i
log
(
p
i
)
\text{Loss}_t= - \sum_{i = 1}^{V} tag_i\log(p_i)
Losst=−i=1∑Vtagilog(pi)
其中,
p
∈
R
V
×
1
p \in \mathbb{R}^{V \times 1}
p∈RV×1 为预测概率分布向量,
t
a
g
∈
R
V
×
1
tag \in \mathbb{R}^{V \times 1}
tag∈RV×1为正确的标签,
Loss
t
\text{Loss}_t
Losst表示在
t
t
t时刻时得到的损失。
最后再将所有的损失进行求均值得到总的损失,即
Loss
=
1
T
∑
i
=
1
T
Loss
i
\text{Loss} = \frac{1}{T} \sum_{i = 1}^{T} \text{Loss}_i
Loss=T1i=1∑TLossi
其中,
T
T
T为总的时刻数,
Loss
i
\text{Loss}_i
Lossi为
t
t
t时刻的损失。