文章来源:初识 CV - Transformer 模型详解(图解最完整版)


# Transformer 是什么

TransformerTransformer 是一种由谷歌团队在 20172017 年提出的深度学习模型架构,最初用于处理自然语言(翻译、文本生成等),现已广泛应用于图像、音频等领域,设计灵感是人类处理信息的方式 关注重点、忽略无关内容


  • 核心特点
    • 注意力机制
    • 无记忆性
    • 通用架构

# Transformer 结构与工作流程

# 结构


由图可知,TransformerTransformerEncoderEncoderDecoderDecoder 两部分组成

# 工作流程

  1. 获取输入句子的每一个表示向量 xx,这个向量由 单词的意思Embedding单词的位置Embedding 相加得到
  2. 将得到的 表示向量矩阵(每一行是一个 表示向量),传入 EncoderEncoder 中,经过 66EncoderEncoder 块后就可以得到该句子的编码信息矩阵 CC
  3. 将编码矩阵 CC 传递到 DecoderDecoder 中,DecoderDecoder 会根据当前翻译的 1i11 \to i - 1 个单词翻译下一个单词 ii,在翻译过程中,需要通过 Mask(掩盖) 操作遮盖住 i+1i + 1 及之后的单词

# Transformer 各步骤详解

# Transformer 的输入

# 单词的词意 Embedding

可以通过 Word2VecWord2VecGloveGlove 等算法预训练得到,也可以在 TransformerTransformer 中训练得到

# 单词的位置 Embedding

TransformerTransformer 的核心是 自注意力机制,把句子中的所有词当成一个集合,但有个问题是 我 爱 你你 爱 我 ,他们会是一样的集合,丢失顺序信息,而此时,我们就提出了位置 EmbeddingEmbedding


假设一句话有 LL 个词,每个词的向量维度是 dmd_{m},我们给每个位置 pospos 分配一个向量,PositionalEncoding(PE)Positional~Encoding~(PE),大小也是 dmd_m。词意 EmbeddingEmbedding 和 词位 EmbeddingEmbedding 相加,这样模型就能感知到 “位置” 信息

# 公式

PE(pos,2i)=sin(pos100002i/dm)PE(pos, 2i) = sin(\frac{pos}{10000^{2i / d_{m}}})

PE(pos,2i+1)=cos(pos100002i/dm)PE(pos, 2i+1)=cos(\frac{pos}{10000^{2i/d_m}})


我 爱 你 为例

  • 位置 pos=0,1,2pos = 0, 1, 2
  • dmd_{m} 取一个小一些的,假设是 44,那 i=0,1,2,3i = 0, 1, 2, 3

每一个词都可以代入,得到一个唯一的位置 EmbeddingEmbedding

# Self-Attention(自注意机制)


被额外框起来的部分是 MultiHeadAttentionMulti-Head~Attention,是由多个 SelfAttentionSelf-Attention 组成的,EncoderEncoder 包括一个 MultiHeadAttentionMulti-Head~Attention,而 DecoderDecoder 包含两个 MultiHeadAttentionMulti-Head~Attention

每个 MultiHeadAttentionMulti-Head~Attention 上都有一个 Add&NormAdd ~ \& ~ Norm

  • AddAdd 层表示残差连接(ResidualConnectionResidual~Connection),用于防止网络退化
  • NormNorm 层表示 LayerNormalizationLayer~Normalization,用于对每一层的激活值进行归一化

# Self-Attention 结构


SelfAttentionSelf-Attention 接受的是输入(单词的表示向量 xx 组成的矩阵 xx 或者 上一个 EncoderEncoder 块的输出)


Q,K,VQ,K,V 三个矩阵都是通过矩阵乘法线性变换得来的

  • Q(Query)Q~(Query):我是谁?我想找谁?
  • K(Key)K~(Key):我有什么特征?我可以被谁找?
  • V(Value)V~(Value):我的内容是什么?被找到的时候我要传递什么信息?

在数学形式上,就是三个线性变换

Q=XWQ,K=XWK,V=XWVQ = X·W_Q, K = X·W_K,V=X·W_V

  • WQ,K,VRdm×dkW_{Q,K,V} \in \mathbb{R}^{d_{m} \times d_k}:是可训练的矩阵
  • dkd_k 通常比 dmd_m

QQKK 做点积,可以得到相关性

Scores=QKTRn×nScores = Q·K^{T} \in \mathbb{R}^{n \times n}

这样一个 n×nn \times n 矩阵,表示第 ii 个词对第 jj 个词的注意力打分。为了避免数值太大,通常除以 dk\sqrt{d_k} 进行缩放

Scorescaled=QKTdkScore_{scaled}=\frac{Q·K^T}{\sqrt{d_k}}

再对每一行做 SoftMaxSoftMax,变成权重形式

AttentionWeights=SoftMax(QKTdk)Attention~Weights = SoftMax(\frac{Q·K^T}{\sqrt{d_k}})

用这样的权重去加和 VV,就能得到输入的新的表示

Output=VAttentionWeightsRn×dvOutput = V·Attention~Weights \in \mathbb{R}^{n \times d_v}

通过这样的形式,就能更新每个词的表示,同时还能融合其他词的信息

# Multi-Head Attention(多头注意力机制)


MultiHeadAttentionMulti-Head~Attention 中包含多个 SelfAttentionSelf-Attention 层,分别将输入 xx 传入 hh 个不同的 SelfAttentionSelf-Attention 中,得到 hh 个输出矩阵 ZZ

hh 个输出矩阵 ZZ 拼接(ConcatConcat)到一起,然后传入一个 LinearLinear 层,从而得到 MultiHeadAttentionMulti-Head~Attention 层的最终输出

# Encoder 结构


EncoderEncoder 部分还有 Add & NormFeed Forward 部分,这里进行一个补充介绍

# Add & Norm

Output=LayerNorm(x+SubLayer(x))Output = LayerNorm(x+SubLayer(x))

顾名思义,这个部分分为

  • AddAdd:残差连接
  • NormNorm:层归一化

# Add

计算完上一层的输入 SubLayer(x)SubLayer(x) 后,与原始输入相加

y=x+SubLayer(x)y = x + SubLayer(x)

通过相加,既能保留原始信息,又能叠加上新信息,缓解梯度消失的问题

# Norm

AddAddyy 进行 LayerNormalizationLayer~Normalization,在特征维度上做归一化

LayerNorm(y)=γyμσ2+ϵ+βLayerNorm(y) = \gamma· \frac{y - \mu}{\sqrt{\sigma^2+\epsilon}} + \beta

  • μ=1di=1dyi\mu = \frac{1}{d} \sum\limits_{i=1}^{d} y_i:样本均值
  • σ2\sigma^2:方差
  • dd:特征维度
  • γ,β\gamma,\beta:学习的参数,用来缩放和平移,恢复网络的表达能力
  • ϵ\epsilon:防除 00 的小常数

# Feed Forward(前馈全连接网络 FFN)

FFNFFN 用来进一步对特征进行加工,核心是 两层全连接 + 激活函数

FFN(x)=W2σ(W1x+b1)+b2FFN(x) = W_2 · \sigma(W_1·x+b_1)+b_2

  • W1Rdf×dmW_1 \in \mathbb{R}^{d_f \times d_m}:第一层权重,把 dmd_m 升维至 d_
  • b1Rdfb_1 \in \mathbb{R}^{d_f}:第一层偏置
  • σ()\sigma(·):激活函数(通常是 ReLUReLUGELUGELU
  • W2dm×dfW_2 \in \mathbb{d_m \times d_f}:第二层权重,降维回到 dmd_m
  • b2Rdmb_2 \in \mathbb{R}^{d_m}:第二层偏置

通俗易懂的解释就是,一句话的表达 xx 先展开思路(升维),再把展开的思路精简一下(降维)
而激活函数的作用就是增加非线性的表达,如果没有激活函数的话,那就相当于一个线性变换了,什么都没做

# Decoder 结构

# 第一个 MHA

DecoderDecoder 部分的第一个 MHAMHA 使用了 MaskedMasked 操作,之前我们提过,在翻译过程中,是顺序翻译的(翻完 ii 个单词才能翻 i+1i+1 个)
注意MaskedMasked 操作是在 SelfAttentionSelf-AttentionSoftmaxSoftmax 之前使用的
MaskedMasked 矩阵参考图如下:


  1. 第一步仍是 QKTQ · K^T,得到注意力矩阵 QKTQK^T(此处为了方便,不提及缩放)
  2. 区别就是,要在 SoftmaxSoftmax 钱,利用 MaskedMasked 矩阵做掩码
  3. Mask(QKT)Mask(Q·K^T)

# 第二个 MHA

第二个 MultiHeadAttentionMulti-Head~Attention 之前的 MHAMHA 变化不大,主要的区别是其中的 SelfAttentionSelf-AttentionK,VK, V 矩阵是使用 Encoder 的编码信息矩阵 C 计算的,而不是使用上一个 DecoderDecoder 的输出

  • K,VK, V 是从 EncoderEncoder 的编码信息矩阵 CC 来的
  • QQ 是由上一个 DecoderDecoder 来的

这样的好处是,在 DecoderDecoder 时,每一位单词都可以利用到 EncoderEncoder 的所有信息(这些信息无需 MaskedMasked

# Softmax

其实是得到一堆 SoftmaxSoftmax,表示每个位置每词的概率