Transformer的前世今生

目录

引言

Attention

Transformer

Transformer在CV中的应用


引言

Transformer在今天已经非常火了, 不管是NLP, 还是CV, 效果表现均很好. 那么这是Transformer到底是什么呢?

要把Transformer的来龙去脉讲清楚, 首先得从attention开始, attention刚出来时, 直接把Google翻译送上了人生巅峰.

在Transformer的出现之前的NLP相比CV来说并不那么活跃, 同时难度相对也比较大, 用得最多的也就是LSTM那一套, 不可能像CV那样模型可迁移性很强.

而Transformer的出现后, 简直把NLP推进几十年的节奏. 改变了上述情况, 不仅可迁移性强, 计算效率也比LSTM高了多少倍.

现在Transformer更是在CV领域如火如荼, 下面就先从attention开始慢慢讲一下整个来弄去脉, 以及算法思想, 内部逻辑.

Attention

Attention是什么呢?

举个例子: 把眼前的实物看成一副图像的话, 我们通常只会关注到里面的某个部分, 例如某个美女帅哥等, 很多别的信息就被过滤掉了.

其最早应该是用于图像里面的(Recurrent Models of Visual Attention), 参考Attention:Recurrent Models of Visual Attention阅读笔记

Neural Machine Translation by Jointly Learning to Align and Translate中,将attention机制首次应用在nlp领域,其采用Seq2Seq+Attention模型来进行机器翻译,并且得到了效果的提升, 参考Seq2Seq With Attention. 与早期的注意力比较, 又有了很多改进.

其实我最开始看到Attention这个次是在Google’s Neural Machine Translation System, 不过这里面关于注意力的部分几乎与14年那篇相同.

为什么需要Attention?

例如在翻译任务中, 当句子太长时, 很难让编码器记住所有的信息用于翻译每个部分.

Attention的具体原理是怎么回事呢?

举个例子: 在翻译任务中, 在翻译某个词时, 可能只需要部分临近的词语, 别的部分对该词语的翻译并不具有太大的作用, 那么此时, 应该对临近的词语关注度更大, 其余部分关注度降低.

说到这里, 有没有觉得跟CV里面的2017年的SENet很像?

其实2017年的另外一篇CV论文NetSlimming也基本上如出一辙.

估计这两篇的作者, 也是受到Attention的启发.

通过这个例子, 现在我们应该对Attention有一个大概的认知了:

> 输出不同的权重\alpha_i即可, 且需要保证\sum{\alpha_i} = 1

> 输入应该是哪些呢? 以最开始眼前实物为例, 从人的视角出发, 输入的信息首先得包含所有原始信息, 其次需要兴趣点, 不同的兴趣点, 关注到的内容也不同.

翻译任务编解码模型Neural Machine Translation by Jointly Learning to Align and Translate翻译任务编解码模型中, 原始信息也就是Encode的全部输出, 兴趣点则是每个Decode的隐层.

上图中的Attention输出并不是权重, 而直接是结果. 也就是对一段原始信息进行兴趣点提问, 直接得出最终结果.

用数学语言来描述上图中的Attention模块输出的context就是, 公式(1.1):


\begin{aligned} & context^{<i>} = \sum{a_i \times \alpha_i} \\ & s.t.: \\ & \alpha_i = softmax(Dense(concate(s_{i-1}, A)))\\ & concate(s_{i-1}, A) = \begin{bmatrix} [s_{i-1}, a_1] \\ ... \\ [s_{i-1}, a_n] \end{bmatrix} \\ & A = [a_1, ..., a_n]^T \\ \end{aligned}

经过上面一堆的描述, Attention的本质基本上就是要呼之欲出了: 计算原始信息与兴趣点的相关性. 相关性越强的, 权重越大, 相关性越小的, 权重越小.

Attention进化版本

先给出Q(query), K(key), V(value)的公式(1.2):

Attention(Q, K, V) = f(Q, K) \times V

如果将公式(1.1)写成公式(1.2)的形式, 则是公式(1.3):

\begin{aligned} Attention(Q, K, V) &= f(Q, K) \times V \\ &= f(Q, V) \times V \\ &= softmax(Dense(Q, V)) \times V \end{aligned}

为什么感觉Q,K,V的更流行, 没有怎么直接看到Q, V呢?

        > An attention function can be described as mapping a query and a set of key-value pairs to an output, where the query, keys, values, and output are all vectors.

        > The output is computed as a weighted sum of the values, where the weight assigned to each value is computed by a compatibility function of the query with the corresponding key.

我的理解是

        > 在神经网络中, 说提出的问题比较复杂, 不便于直接从原始信息中得到结论

        > 假设原始数据为X_q, X_k, X_v

        > 将其变为K=W_1X_k, 对其进行提问Q=W_2X_q, 所得到的答案需要从V=W_3X_v中提取

上面这么来说可能比较晦涩, 举个例子

        > 原文: 13+7=20

        > 提问: 如果是8进制, 上式还能成立吗?

        > 解题过程中

        > - 需要将13, 7, 20转成10进制 => 也就是 K=W_1X_k

        > - 再计算看是否相等 => V=W_3X_v

讲到了这里, 再多说几句, CNN之前, 大家会手工设计卷积核, 例如SURF算法. 有了CNN后, 需要什么卷积核, 交给模型自己去学习.

那么在Attention的时代, 需要提什么问题? 需要对什么提问? 需要什么来回答? 全部都交给模型自己去学习. 很美妙是吧, 已经是成熟的模型了, 可以自己去解决问题.

那计算相关性嘛, 方法就很多了, 总结如下:

Neural Machine Translation by Jointly Learning to Align and Translate中的加法, 公式(1.4):

f(Q, K) = softmax(Dense(Q, K))

Attention Is All You Need中的乘法(Scaled Dot-Product Attention), 公式(1.5):

f(Q, K) = softmax(\frac{QK^T}{\sqrt{d_k}})

更加直观的描述公式(1.5), 也就是:

Effective Approaches to Attention-based Neural Machine Translation中的各种, 公式(1.6):

f(Q, K) = \left\{\begin{matrix} QK^T & dot \\ QWK^T & general \\ tanh(W[Q, K_i]) & concat, e.g. plus \\ \end{matrix}\right.

公式(1.6)中的最后一个, 称呼为感知机(perceptron)可能更好一些.

可否采用类似余弦相似性的方式来计算呢? 我觉得理论上应该是可以的, 就连感知机都能用, 别的还有啥不能用呢? 需要什么样的相似性, 理论上都完全可以交给模型自己学习.

另外还有一种Attention值得注意: Self-Attention.

        > In a self-attention layer all of the keys, values and queries come from the same place.

那么到这里之后, Attention变成了什么样子? 公式(1.7)

\begin{aligned} & input: X \\ & Q = W_qX \\ & K = W_kX \\ & V = W_vX \\ & output = Attention(Q,K,V) = Attention(W_qX, W_kX, W_vX) \end{aligned}

这不就是输入X, 输出特征吗? 那跟卷积核有啥差别? 直接用来"随意"堆叠, 不就搞定了? 避免了RNN的串联计算量, 还能提取到更好的特征? 事实上也差不多大概接近这个意思了, 下面来看一个Multi-Head Attention的东西. 原文中是这样计算的, 公式(1.8):

MultiHead(Q,K,V) = Concat(head_1, ..., head_h)W^O \\ \begin{aligned} s.t.: & \\ & head_i = Attention(QW_i^Q, KW_i^K, VW_i^V) \\ & W_i^Q, W_i^K \in R^{d_{model} \times d_k} \\ & W_i^V \in R^{d_{model} \times d_v} \\ & W^O \in R^{hd_v \times d_{model}} \end{aligned}

其中的Attention使用Scaled Dot-Product Attention时, 直观的描述如下:

有没有感觉上述的muti-head attention就类似CNN里面的一层卷积, 包含了多个卷积核?

那么self-attention加上muti-head attention会是什么样子? 将会在后面的Transormer中有直观的介绍.

现在回过头来观察公式(1.5)中为什么需要除以\sqrt{q_k}呢?

- 对模型的精度有提升?

- 对模型的训练有提升?

- Next we apply the “scaled” factor to have more stable gradients

- 也就是说对模型的训练有帮助, 为什么呢?

import numpy as np

def softmax(data):
    data_exp = np.exp(data)
    total = sum(data_exp)
return data_exp/total

# 假设矩阵维度为8
softmax([114, 96]) # array([1.00000000e+00, 2.78946809e-10])
softmax([114/8, 96/8]) # array([0.90465054, 0.09534946])

- 从上述实验结果可以看出, 当数组中数值差异稍微大一点时, 要么趋近于1, 要么趋近于0

- 这将增加模型的训练难度

- 假设输入Muti-Head的Attention中的QKV相同, 也即是均为X, 即

\begin{aligned} head_i &= Attention(QW_i^Q, KW_i^K, VW_i^V) \\ &= Attention(XW_i^Q, XW_i^K, XW_i^V) \end{aligned}

- 且, 误差传递到Attention时为\delta

- 则有(不考虑V, 重点分析QK)

\begin{aligned} \Delta W_i^Q &= \frac{\partial \delta}{\partial head_i} \frac{\partial head_i}{\partial Q} \frac{\partial Q}{\partial X} \\ \Delta W_i^K &= \frac{\partial \delta}{\partial head_i} \frac{\partial head_i}{\partial K} \frac{\partial K}{\partial X} \end{aligned}

- 其中(设g = \frac{QK^T}{\sqrt{d_k}})

\begin{aligned} \frac{\partial head_i}{\partial Q} &= \frac{\partial softmax}{\partial Q} V = \frac{\partial softmax}{\partial g} \frac{K}{\sqrt{d_k}}V \\ \frac{\partial head_i}{\partial K} &= \frac{\partial softmax}{\partial K} V = \frac{\partial softmax}{\partial g} \frac{Q}{\sqrt{d_k}}V \end{aligned}

- 当softmax \rightarrow 1/0时, \frac{\partial softmax}{\partial g} \rightarrow 0

- 因此容易产生梯度消失

- 因此为了更加稳定的训练, 除了这个系数, 那么可否换成别的系数呢? 我认为是可以的!

- 具体论文为什么得到这个系数, 除了公式的美观外[偷笑]

- 假设输入的Q, K的各个分量均相互独立, 且均值为0, 方差为1

- 设G=QK^T, 则G_{ij}的均值方差分别为:

\begin{aligned} E(G_{ij}) &= E(\sum_k Q_{ik}K_{jk}) = \sum_k E(Q_{ik}K_{jk}) = \sum_k E(Q_{ik})E(K_{jk}) = 0 \\ D(G_{ij}) &= D(\sum_k Q_{ik}K_{jk}) = \sum_k D(Q_{ik}K_{jk}) = \sum_k D(Q_ik)D(K_{jk}) = d_k \end{aligned}

Transformer

先直接上论文原图:

上图中左边部分为Encoder, 右边部分为Decoder. Encoder中的muti-head attention, 注意到了吧, 输入的Q, K, V都是同一个, 也就是self-attention.

再来分析Transformer的组成:

- 加入了ResNet机制, 每个Multi-Head Attention & Feed Forward后面都接了残差层

- 如果把Multi-Head Attention & Feed Forward看做一个整体, 那么也就是很多CV论文里面提到的一个Block

- Feed Forward由两个线性全链接层组成, 其中第一个线性全链接激活函数为Relu, 第二个没有激活函数, 直接接残差层. 原文公式如下, 公式(2.1):

FFN(x) = max(0, xW_1 + b_1) W_2+b_2

- Encoder中全都是self-attention

- Decoder中也包含self-attention, 与Encoder不同的地方是增加了Mask操作.

- Decoder中除了self-attention外, 包含额外的encoder-decoder attention, 其输入的KV来自Encoder的输出, Q则来自Decoder自身

讲到这里, 其实基本上已经清楚整个Transformer的工作逻辑了.

但是有没有注意到一个问题: 整体框架图中还有一个Positonal Encoding, 如果没有会怎么样?

- Transformer与RNN系相比, 是并行计算的, 没有RNN提取序列特征的能力

- 换句话说, 如果没有序列特征, 那么在翻译任务中很可能会出现: 不管输入我喜欢深度学习, 还是输入深度学习喜欢我, 都可能翻译为I like deep learning

- 显然是不合理的

那么Positonal Encoding是如何解决上述问题的呢?

作者自己设计位置编码特征, 并与输入词向量相加, 得到新的特征向量. 并没有采用传统的类似one-hot编码, 与词向量拼接; 或自动化训练位置编码. 公式(2.2)

\begin{aligned} PE(pos, 2i) &= sin(\frac{pos}{1000^{\frac{2i}{d_{model}}}}) \\ PE(pos, 2i+1) &= cos(\frac{pos}{1000^{\frac{2i}{d_{model}}}}) \end{aligned}

pos表示位置, i表示维度. d_{model}可以理解为词向量的维度.

根据公式(2.2)则可以将每个位置上的词/字符都编码成一个维度与d_{model}相同的向量. 而且可以看到, 这个编码向量的同一维度上, 不同的位置其实就是一个三角函数曲线.

选择三角函数, 原文也提到了是因为位置偏移后向量便于线性表示, 也就是公式(2.3):

\begin{aligned} sin(pos+k) &= sin(pos)cos(k) + cos(pos)sin(k) \\ cos(pos+k) &= cos(pos)cos(k) - sin(pos)sin(k) \end{aligned}

原文也提到, 对比了自动训练位置向量和三角函数编码位置向量, 结果相近, 则跟愿意选择三角函数编码. 因为可以少训练很多参数.

假设句子长度为100, 词向量为512, 则得到的位置向量PE为: (100, 512), 且PE(:, i)为同一周期, 同一相位的三角函数曲线上的点.

按照公式(2.2)的理解: 应该是表达奇数维度使用sin, 偶数维度使用cos, 但源码中似乎直接把sincos拼接, 并没有按照奇偶维度进行操作. 应该是为了简化吧, 只要向量中包含了位置信息即可. 最终进入模型的向量其实是PositonalEncoding + WordEmbedding.

到这里, Transformer中还剩下最后一个问题, Decoder中的Mask是如何使用的? 其目的是什么?

训练的过程中, 我们知道预测结果, 所以可以随便怎么编码传入到Decoder中.

但真正使用做预测时, 就不能这么玩了. 为了能够让训练跟预测一样, Mask的作用就有了, 训练时会把当前时刻之后的均屏蔽掉, 只保留当前时刻之间的.

有没有觉得上面的描述哪里怪怪的? 不是并行计算的吗? 怎么还分时间先后啊? 那相比LSTM之类的有什么差别?

训练时, 是可以完全并行计算的, 则训练速度相比LSTM系列快很多.

预测时, 编码器部分是完全可以并行计算的, 解码器部分确实只能挨个进行, 当时相比LSTM已经好了很多.

Transformer在CV中的应用

- A Survey on Vision Transformer

- Transformers in Vision: A Survey

- Vit-Vision Transformer

- 源码: https://github.com/x1489/vision_transformer

- 思想还是很简单的

- Transformer的输入是很多个1维向量(位置向量+词向量)

- 因此将图像切成很多个小块

- 再把每个小块转成1维向量

- 要么直接拉直成1维向量

- 要么通过卷积转成1维向量

- 再加上每个小块的位置向量

- 直接送入到了Transformer中

- 文中只用到了Encoder部分

- 最后再加一个MLP或Liner进行分类

- 更多的细节参考原文

- 虽然是成功将Transformer应用在了CV, 但似乎并没有很NB的样子

- 其实可以想想到, CV任务中, 输入的图像可能很多部分其实没有用, 只需要关注其中部分即可, 因此切成小块(小块越小效果越好), 或者别的注意力机制应该就能够直接达到不错的效果

- 论文ConvMixer提到这个事情, 可能ViT中的很大功劳来自于Patch

- 源码: https://github.com/locuslab/convmixer
 

[1]: https://zhuanlan.zhihu.com/p/46990010

[2]: https://jalammar.github.io/illustrated-transformer/

[3]: https://www.zhihu.com/question/437495132

  • 5
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值