所以作者提出,显式地构造一个identity mapping,使得深层模型的精度至少不会变得更差。作者将其称为deep residual learning framework。 假设我们要学的是
H
(
x
)
H(x)
H(x) ,在原有层上 添加一些新的层时,新的层不是直接学
H
(
x
)
H(x)
H(x) ,而是学习
H
(
x
)
−
x
H(x) -x
H(x)−x,这部分用
F
(
x
)
F(x)
F(x)表示。(其中,
x
x
x是原有层的输出。)即,新加入的层不用全部重新学习,而是学习原来已经学习到的
x
x
x和真实的
H
(
x
)
H(x)
H(x)之间的残差就行 。最后模型的输出是
F
(
x
)
+
x
F(x)+x
F(x)+x。这种新加入的层就是residual,结构如下图所示:
F
(
x
)
+
x
F(x)+x
F(x)+x在数学上就是直接相加,在神经网络中是通过‘shortcut connections’实现(shortcut就是跳过一个或多个层,将输入直接加到这些跳过的层的输出上)。shortcut其实做的是一个identity mapping(恒等映射),而且这个操作不需要学习任何参数,不增加模型的复杂度。就多了一个加法,也不增加计算量,网络结构基本不变,可以正常训练。
A. pad补0,使维度一致; B. 维度不一致的时候,使其映射到统一维度,比如使用全连接或者是CNN中的1×1卷积(输出通道是输入的两倍)。 C. 不管输入输出维度是否一致,都进行投影映射。 下面作者对这三种操作进行效果验证。从下面结果可以看到,B和C效果差不多,都比A好。但是做映射会增加很多复杂度,考虑到ResNet中大部分情况输入输出维度是一样的(也就是4个模块衔接时通道数会变),作者最后采用了方案B。
大部分神经序列转换模型都使用encoder-decoder 结构 (引用)。编码器把一个输入序列
(
x
1
,
.
.
.
x
n
)
(x_{1},...x_{n})
(x1,...xn)映射到一个连续的表示
z
=
(
z
1
,
.
.
.
z
n
)
z=(z_{1},...z_{n})
z=(z1,...zn)中。解码器对z中的每个元素,生成输出序列
(
y
1
,
.
.
.
y
m
)
(y_{1},...y_{m})
(y1,...ym),一个时间步生成一个元素。在每一步中,模型都是自回归的(auto-regressive)(引用),在生成下一个结果时,会将先前生成的结果加入输入序列来一起预测。(自回归模型的特点,过去时刻的输出可以作为当前时刻的输入)
其输入为query、key(维度是
d
k
d_k
dk)以及values(维度是
d
v
d_v
dv)。
计算query和所有key的点积,得到两个向量的相似度(结果越大相似度越高);然后对每个点积结果除以
d
k
\sqrt{d_k}
dk,
点积结果输入softmax函数获得value的权重。
最后对value进行加权求和
在实践中,我们同时计算一组query的attention函数,并将它们组合成一个矩阵
Q
Q
Q。key和value也一起组成矩阵
K
K
K和
V
V
V。 我们计算的输出矩阵为:
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
=
s
o
f
t
m
a
x
(
Q
K
T
d
k
)
V
\mathrm{Attention}(Q, K, V) = \mathrm{softmax}(\frac{QK^T}{\sqrt{d_k}})V
Attention(Q,K,V)=softmax(dkQKT)V
加法attention(cite):
s
=
A
T
T
a
n
h
(
q
W
+
k
U
)
s=A^{T}Tanh(qW+kU)
s=ATTanh(qW+kU),使用具有单个隐层的前馈网络计算,q和k维度不一致也可以进行;
上面提到的点积(乘法)attention
除了缩放因子
1
d
k
\frac{1}{\sqrt{d_k}}
dk1 之外,点积Attention跟我们的算法一样(所以作者的注意力叫缩放点积注意力)。虽然理论上点积attention和加法attention复杂度相似,但在实践中,点积attention可以使用高度优化的矩阵乘法来实现,因此点积attention计算更快、更节省空间。 当dk的值比较小的时候,这两个机制的性能相差相近,当dk比较大时,加法attention比不带缩放的点积attention性能好。我们怀疑,维度dk很大时,点积结果也变得很大,将softmax函数推向具有极小梯度的区域。为了抵消这种影响,我们将点积缩小
1
d
k
\frac{1}{\sqrt{d_k}}
dk1倍。
2.4.2.2 多头注意力
M
u
l
t
i
H
e
a
d
(
Q
,
K
,
V
)
=
C
o
n
c
a
t
(
h
e
a
d
1
,
.
.
.
,
h
e
a
d
h
)
W
O
where
h
e
a
d
i
=
A
t
t
e
n
t
i
o
n
(
Q
W
i
Q
,
K
W
i
K
,
V
W
i
V
)
\mathrm{MultiHead}(Q, K, V) = \mathrm{Concat}(\mathrm{head_1}, ..., \mathrm{head_h})W^O \\ \text{where}~\mathrm{head_i} = \mathrm{Attention}(QW^Q_i, KW^K_i, VW^V_i)
MultiHead(Q,K,V)=Concat(head1,...,headh)WOwhereheadi=Attention(QWiQ,KWiK,VWiV) 其中映射由权重矩阵完成:
W
i
Q
∈
R
d
model
×
d
k
W^Q_i \in \mathbb{R}^{d_{\text{model}} \times d_k}
WiQ∈Rdmodel×dk,
W
i
K
∈
R
d
model
×
d
k
W^K_i \in \mathbb{R}^{d_{\text{model}} \times d_k}
WiK∈Rdmodel×dk,
W
i
V
∈
R
d
model
×
d
v
W^V_i \in \mathbb{R}^{d_{\text{model}} \times d_v}
WiV∈Rdmodel×dv and
W
O
∈
R
h
d
v
×
d
model
W^O \in \mathbb{R}^{hd_v \times d_{\text{model}}}
WO∈Rhdv×dmodel。 我们采用
h
=
8
h=8
h=8个平行attention层或者叫head。对于这些head中的每一个,我们使用
d
k
=
d
v
=
d
model
/
h
=
64
d_k=d_v=d_{\text{model}}/h=64
dk=dv=dmodel/h=64,总计算成本与具有全部维度的单个head attention相似。
输入 X 和8组权重矩阵
W
Q
W^Q
WQ,
W
K
W^K
WK
W
V
W^V
WV相乘,得到 8 组 Q, K, V 矩阵。进行attention计算,得到 8 组 Z 矩阵(假设head=8)
把8组矩阵拼接起来,乘以权重矩阵
W
O
W^O
WO,将其映射回 d 维向量(相当于多维特征进行汇聚),得到最终的矩阵 Z。这个矩阵包含了所有 attention heads(注意力头) 的信息。
多语义匹配:本身缩放点积注意力是没什么参数可以学习的,就是计算点积、softmax、加权和而已。但是使用Multi-head attention之后,投影到低维的权重矩阵
W
Q
W^Q
WQ,
W
K
W^K
WK ,
W
V
W^V
WV是可以学习的,而且有h=8次学习机会。使得模型可以在不同语义空间下学到不同的的语义表示,也扩展了模型关注不同位置的能力。类似卷积中多通道的感觉。 例如,“小明养了一只猫,它特别调皮可爱,他非常喜欢它”。“猫”从指代的角度看,与“它”的匹配度最高,但从属性的角度看,与“调皮”“可爱”的匹配度最高。标准的 Attention 模型无法处理这种多语义的情况。
编码器和解码器中的每个层都包含一个全连接的前馈网络,该前馈网络分别且相同地应用于每个位置。该前馈网络包括两个线性变换,并在两个线性变换中间有一个ReLU激活函数。
F
F
N
(
x
)
=
max
(
0
,
x
W
1
+
b
1
)
W
2
+
b
2
\mathrm{FFN}(x)=\max(0, xW_1 + b_1) W_2 + b_2
FFN(x)=max(0,xW1+b1)W2+b2 Position就是序列中每个token,Position-wise 就是把MLP对每个token作用一次,且作用的是同一个MLP。说白了就是MLP只作用于最后一个维度d=512。 因为前面的attention层以及抓取了输入序列的相关信息,并做了一次汇聚(拼接后W映射回d维)。所以attention层结果已经有了序列中我感兴趣的信息,所以后面在做MLP投影映射到想要的语义空间时,只需要对每个position(token)单独做MLP就行。 从attention抽取序列信息到MLP映射到需要的语义空间(非线性变换),就整个是transformer的处理信息的基础过程。
尽管两层都是线性变换,但它们在层与层之间使用不同的参数。另一种描述方式是两个内核大小为1的卷积。 输入和输出的维度都是
d
model
=
512
d_{\text{model}}=512
dmodel=512, 内层维度是
d
f
f
=
2048
d_{ff}=2048
dff=2048。(也就是第一层输入512维,输出2048维;第二层输入2048维,输出512维)
我们使用学习到的embedding将输入token和输出token转换为
d
model
d_{\text{model}}
dmodel维的向量。我们还使用普通的线性变换和softmax函数将解码器输出转换为预测的下一个token的概率。在我们的模型中,输入输出两个嵌入层,和pre-softmax线性变换共享相同的权重矩阵(这样训练起来简单一些)。最后我们将这些权重乘以
d
model
\sqrt{d_{\text{model}}}
dmodel(比如512)。
这是因为一般会把一个向量的L2Norm学到接近1,这样向量维度越大,这样学到的权重值就会很小。但是位置编码是不会这样学成L2Norm(L2范数)接近1的。所以把权重乘上
d
model
\sqrt{d_{\text{model}}}
dmodel之后,token embedding和位置编码Positional Encoding才接近统一量级。(都在-1到1之间)
2.4.5 位置编码(Positional Encoding)
Attention计算时本身是不考虑位置信息的,这样序列顺序变化结果也是一样的。所以我们必须在序列中加入关于词符相对或者绝对位置的一些信息。 为此,我们将“位置编码”添加到token embedding中。二者维度相同(例如
d
model
\sqrt{d_{\text{model}}}
dmodel=512),所以可以相加。有多种位置编码可以选择,例如通过学习得到的位置编码和固定的位置编码。 在这项工作中,我们使用不同频率的正弦和余弦函数:
P
E
(
p
o
s
,
2
i
)
=
s
i
n
(
p
o
s
/
1000
0
2
i
/
d
model
)
PE_{(pos,2i)} = sin(pos / 10000^{2i/d_{\text{model}}})
PE(pos,2i)=sin(pos/100002i/dmodel)
P
E
(
p
o
s
,
2
i
+
1
)
=
c
o
s
(
p
o
s
/
1000
0
2
i
/
d
model
)
PE_{(pos,2i+1)} = cos(pos / 10000^{2i/d_{\text{model}}})
PE(pos,2i+1)=cos(pos/100002i/dmodel) 其中
p
o
s
pos
pos 是位置,
i
i
i 是维度。也就是说,位置编码的每个维度对应于一个正弦曲线。 这些波长形成一个从
2
π
2\pi
2π 到
10000
⋅
2
π
10000 \cdot 2\pi
10000⋅2π的集合级数。我们选择这个函数是因为我们假设它会让模型很容易学习对相对位置的关注,因为对任意确定的偏移
k
k
k,
P
E
p
o
s
+
k
PE_{pos+k}
PEpos+k 可以表示为
P
E
p
o
s
PE_{pos}
PEpos的线性函数。最终编码向量每个元素值都是在-1到1之间。
此外,我们会将编码器和解码器堆栈中的embedding和位置编码的和再加一个dropout。对于基本模型,我们使用的dropout比例是
P
d
r
o
p
=
0.1
P_{drop}=0.1
Pdrop=0.1。
我们使用Adam优化器(cite),其中
β
1
=
0.9
\beta_1=0.9
β1=0.9,
β
2
=
0.98
\beta_2=0.98
β2=0.98并且
ϵ
=
1
0
−
9
\epsilon=10^{-9}
ϵ=10−9。我们根据以下公式在训练过程中改变学习率:
l
r
a
t
e
=
d
model
−
0.5
⋅
min
(
s
t
e
p
_
n
u
m
−
0.5
,
s
t
e
p
_
n
u
m
⋅
w
a
r
m
u
p
_
s
t
e
p
s
−
1.5
)
lrate = d_{\text{model}}^{-0.5} \cdot \min({step\_num}^{-0.5}, {step\_num} \cdot {warmup\_steps}^{-1.5})
lrate=dmodel−0.5⋅min(step_num−0.5,step_num⋅warmup_steps−1.5) 这对应于在第一次
w
a
r
m
u
p
_
s
t
e
p
s
warmup\_steps
warmup_steps步中线性地增加学习速率,并且随后将其与步数的平方根成比例地减小。我们使用
w
a
r
m
u
p
_
s
t
e
p
s
=
4000
warmup\_steps=4000
warmup_steps=4000。
深度学习不仅是学习网络,更是对数据分布的一种表示。这和统计学习方法里面的观点不谋而合,后者认为机器学习模型从概率论的角度讲,就是一个概率分布
P
θ
(
X
)
P_{\theta }(X)
Pθ(X) (这里以概率密度函数来代表概率分布) 机器学习的任务就是求最优参数
θ
t
\theta_{t}
θt ,使得概率分布
P
θ
(
X
)
P_{\theta }(X)
Pθ(X) 最大(即已发生的事实,其对应的概率理应最大)。
θ
t
=
a
r
g
m
a
x
θ
P
θ
X
\theta_{t} =\underset{\theta}{argmax}P_{\theta }X
θt=θargmaxPθX argmax 函数代表的是取参数使得数据的概率密度最大。求解最优参数
θ
t
\theta_{t}
θt的过程,我们称之为模型的训练过程( Training )
a. 生成器从均匀分布学成绿色实线表示的高斯分布,这时候判别器还很差; b. 判别器学成图b所示的分布,可以把真实数据和生成数据区别开来; c.生成器波峰靠向真实数据波峰,自然就使得判别器难以分辨了;辨别器为了更准,其分布也往真实数据靠拢; d.最终训练的结果,生成器拟合真实分布,判别器难以分辨,输出概率都为0.5 。
3.3.2 迭代求解过程
下面是具体的算法过程:
k是一个超参数,不能太小也不能太大。要保证判别器D可以足够更新,但也不能更新太好。
如果D更新的不够好,那么G训练时在一个判别很差的模型里面更新参数,继续糊弄D意义不大;
如果D训练的很完美,那么
l
o
g
(
1
−
D
(
G
(
z
)
)
)
log(1-D(G(z)))
log(1−D(G(z)))趋近于0,求导结果也趋近于0,生成器难以训练
整体来说GAN的收敛是很不稳定的,所以之后有很多工作对其进行改进。
早期G非常弱,所以很容易把D训练的很好,这样就造成刚刚说的G训练不动了。所以作者建议此时,G的目标函数改为最大化
l
o
g
D
(
G
(
z
)
)
logD(G(z))
logD(G(z))(就算D训练的好,这部分也是有梯度的)。带来的问题是,
l
o
g
D
(
G
(
z
)
)
→
0
logD(G(z))\rightarrow 0
logD(G(z))→0的时候,log0是负无穷大,会带来数值上的问题。(后面的工作会对其进行改进)
3.4 理论结果
3.4.1 全局最优解
p
g
=
p
d
a
t
a
p_g=p_{data}
pg=pdata
这部分需要证明目标函数
m
i
n
G
m
a
x
D
V
(
D
,
G
)
\underset{G}{min}\underset{D}{max}V(D,G)
GminDmaxV(D,G)有全局最优解,且这个解当且仅当
p
g
=
p
d
a
t
a
p_g=p_{data}
pg=pdata时成立,也就是生成器学到的分布等于真实数据的分布。
p
g
(
x
)
p_g(x)
pg(x)和
p
d
a
t
a
(
x
)
p_{data}(x)
pdata(x)表示x在生成器拟合的分布里面,和真实数据的分布里面,它的概率分别是多少。
当
p
g
(
x
)
=
p
d
a
t
a
(
x
)
p_g(x)=p_{data}(x)
pg(x)=pdata(x)时,结果为1/2,表示两个分布完全相同,最优的判别器也无法将其分辨出来。
这个公式的意义是,从两个分布里面分别采样数据,用目标函数
m
i
n
G
m
a
x
D
V
(
D
,
G
)
\underset{G}{min}\underset{D}{max}V(D,G)
GminDmaxV(D,G)训练一个二分类器,如果分类器输出的值都是0.5,则可以认为这两个分布是完全重合的。在统计学上,这个叫two sample test,用于判断两块数据是否来自同一分布。
two sample test是一个很实用的技术,比如在一个训练集上训练了一个模型,然后部署到另一个环境,需要看看测试数据的分布和训练数据是不是一样的,就可以像这样训练一个二分类器就行了,避免部署的环境和我们训练的模型不匹配。
把D的最优解代回目标函数,目标函数之和G相关,写作C(G):
现在只需要最小化这一项就行。
证明当且仅当
p
g
=
p
d
a
t
a
p_g=p_{data}
pg=pdata时有最优解
C
(
G
)
=
−
l
o
g
4
C(G)=-log4
C(G)=−log4。
上式两项可以写成KL散度,即:
又因为JS散度定义为:
所以进一步化简成:
要求
m
i
n
C
(
G
)
minC(G)
minC(G),只有最后一项等于0的时候成立(JS散度≥0),此时
p
g
=
p
d
a
t
a
p_g=p_{data}
pg=pdata。
JS散度跟KL散度的区别是前者是对称的,
p
g
p_g
pg和
p
d
a
t
a
p_{data}
pdata可以互换,而后者不对称。
难以收敛(non-convergence) 目前面临的基本问题是:所有的理论都认为 GAN 应该在纳什均衡(Nash equilibrium)上有卓越的表现,但梯度下降只有在凸函数的情况下才能保证实现纳什均衡。当博弈双方都由神经网络表示时,在没有实际达到均衡的情况下,让它们永远保持对自己策略的调整是可能的【OpenAI Ian Goodfellow的Quora】。
无需预先建模,模型过于自由不可控。 与其他生成式模型相比,GAN不需要构造分布函数,而是使用一种分布直接进行采样,从而真正达到理论上可以完全逼近真实数据,这也是GAN最大的优势。然而,这种不需要预先建模的方法缺点是太过自由了,对于较大的图片,较多的 pixel的情形,基于简单 GAN 的方式就不太可控了(超高维)。
自然语言推理(Conneau et al.,2017)和机器翻译(McCann et al.,2017)有很多大型的有监督数据集,在这些数据集上预训练好语言模型,再迁移到别的NLP任务上,效果是非常好的。计算机视觉研究还证明了从大型预训练模型进行迁移学习的重要性,其中有效的方法是对通过ImageNet预训练的模型进行微调。
BERT的模型架构是多层双向Transformer编码器,基于Vaswani等人描述的原始实现。并且我们的Transformers实现几乎与原始实现相同,所以我们将省略模型结构的详细背景介绍,请读者参考诸如The Annotated Transformer之类优秀的指南。 在这项工作中,我们将层(即,Transformer块)的数量表示为L,将隐藏层的大小表示为H,并将自注意力头的数量表示为A。我们主要报告两种模型尺寸的结果:
B
E
R
T
B
A
S
E
(
L
=
12
,
H
=
768
,
A
=
12
,
T
o
t
a
l
P
a
r
a
m
e
t
e
r
s
=
110
M
)
BERT_{BASE} (L=12, H=768, A=12, Total Parameters=110M)
BERTBASE(L=12,H=768,A=12,TotalParameters=110M)和
B
E
R
T
L
A
R
G
E
(
L
=
24
,
H
=
1024
,
A
=
16
,
T
o
t
a
l
P
a
r
a
m
e
t
e
r
s
=
340
M
)
BERT_{LARGE}(L=24, H=1024, A=16, Total Parameters=340M)
BERTLARGE(L=24,H=1024,A=16,TotalParameters=340M)。为了便于比较,
B
E
R
T
B
A
S
E
BERT_{BASE}
BERTBASE 选择了和OpenAI的GPT相同的模型的尺寸。
BERT模型可学习参数来自词嵌入层和Transformer块。
词嵌入层,词表大小3w,词向量维度为H
Transformer块分为两部分:
自注意力子层:Q、K、V分别通过一个 参数矩阵
(
W
Q
,
W
K
,
W
V
)
(W^Q, W^K, W^V)
(WQ,WK,WV)进行投影,参数矩阵维度是H×H(其实是多头,但是合起来还是原始维度大小。投影前后维度不变,所以矩阵大小必须是H×H)。投影之后输出的多头注意力还会经过一个矩阵
W
O
W^O
WO将其映射回H维。所以自注意力层一共四个参数矩阵,可学习的参数量是
4
H
2
4H^2
4H2。
MLP层:有两层,输入输出分别是[H,4H]和[4H,H],所以每一层参数是
4
H
2
4H^2
4H2,两层就是
8
H
2
8H^2
8H2。
总参数应该是
30000
⋅
H
+
L
⋅
12
H
2
30000\cdot H+L\cdot 12H^{2}
30000⋅H+L⋅12H2,带入base的参数大概就是1.1亿。
# 示例
Input =[CLS] the man went to [MASK] store [SEP]
he bought a gallon [MASK] milk [SEP]
Label = IsNext
Input =[CLS] the man [MASK] to the store [SEP]
penguin [MASK] are flight ##less birds [SEP] # 两个## 表示后面这个词less跟在flight后,二者是同一个词被切成两半
Label = NotNext
预训练过程很大程度上遵循现存文献的语言模型预训练,我们使用BooksCorpus(800M个单词)和English Wikipedia(25亿个单词)。为了获取长的连续序列,使用文档级的语料(文章)比使用像Billion Word Benchmark这样无序的句子级语料更为重要。