transformer中的attention为什么scaled?

链接:https://www.zhihu.com/question/339723385

编辑:深度学习与计算机视觉

声明:仅做学术分享,侵删

论文中解释是:向量的点积结果会很大,将softmax函数push到梯度很小的区域,scaled会缓解这种现象。怎么理解将sotfmax函数push到梯度很小区域?还有为什么scaled是维度的根号,不是其他的数?

作者:TniL

https://www.zhihu.com/question/339723385/answer/782509914

1. 为什么比较大的输入会使得softmax的梯度变得很小?

对于一个输入向量 ,softmax函数将其映射/归一化到一个分布 。在这个过程中,softmax先用一个自然底数 将输入中的元素间差距先“拉大”,然后归一化为一个分布。假设某个输入 中最大的的元素下标是 如果输入的数量级变大(每个元素都很大),那么会非常接近1。

我们可以用一个小例子来看看 的数量级对输入最大元素对应的预测概率的影响。假定输入 ),我们来看不同量级的 产生的有什么区别。

  • 时, ;

  • 时, ;

  • 时, (计算机精度限制)。

我们不妨把 在不同取值下,对应的的全部绘制出来。代码如下:

得到的图如下所示:

可以看到,数量级对softmax得到的分布影响非常大。在数量级较大时,softmax将几乎全部的概率分布都分配给了最大值对应的标签

然后我们来看softmax的梯度。不妨简记softmax函数为 ,softmax得到的分布向量 对输入 的梯度为:

把这个矩阵展开:

根据前面的讨论,当输入 的元素均较大时,softmax会把大部分概率分布分配给最大的元素,假设我们的输入数量级很大,最大的元素是 ,那么就将产生一个接近one-hot的向量  ,此时上面的矩阵变为如下形式:

也就是说,在输入的数量级很大时,梯度消失为0,造成参数更新困难

注:softmax的梯度可以自行推导,网络上也有很多推导可以参考。


2. 维度与点积大小的关系是怎么样的,为什么使用维度的根号来放缩?

针对为什么维度会影响点积的大小,在论文的脚注中其实给出了一点解释:

假设向量 的各个分量是互相独立的随机变量,均值是0,方差是1,那么点积 的均值是0,方差是 。这里我给出一点更详细的推导:

都是随机变量,为了方便书写,不妨记 。这样有:

则:

这样 ,  的均值是0,方差是1,又由期望和方差的性质, 对相互独立的分量 ,有

以及

所以有 的均值 ,方差 方差越大也就说明,点积的数量级越大(以越大的概率取大值)。那么一个自然的做法就是把方差稳定到1,做法是将点积除以 ,这样有:

将方差控制为1,也就有效地控制了前面提到的梯度消失的问题

作者:Towser https://www.zhihu.com/question/339723385/answer/812013477

@lintongmao写的很好。用代码做一个数值实验就很清楚了:

from scipy.special import softmax
import numpy as np

def test_gradient(dim, time_steps=50, scale=1.0):
    # Assume components of the query and keys are drawn from N(0, 1) independently
    q = np.random.randn(dim)
    ks = np.random.randn(time_steps, dim)
    x = np.sum(q * ks, axis=1) / scale  # x.shape = (time_steps,) 
    y = softmax(x)
    grad = np.diag(y) - np.outer(y, y)
    return np.max(np.abs(grad))  # the maximum component of gradients

NUMBER_OF_EXPERIMENTS = 5
# results of 5 random runs without scaling
print([test_gradient(100) for _ in range(NUMBER_OF_EXPERIMENTS)])
print([test_gradient(1000) for _ in range(NUMBER_OF_EXPERIMENTS)])

# results of 5 random runs with scaling
print([test_gradient(100, scale=np.sqrt(100)) for _ in range(NUMBER_OF_EXPERIMENTS)])
print([test_gradient(1000, scale=np.sqrt(1000)) for _ in range(NUMBER_OF_EXPERIMENTS)])

程序输出:

不带 scaling 的两组(可以看到 dim=1000 时很容易发生梯度消失):

[0.059398546712975064, 0.2498360169388831, 0.008179271245615127, 0.16985040166173004, 0.00017518204173572194]
[0.037403200843576845, 1.8829382497642655e-11, 6.995490600791854e-06, 1.3460521586239338e-10, 5.498179689311655e-11]

带 scaling 的两组(dim=1000 时梯度流依然稳定):

[0.23435524441068933, 0.10572976561186455, 0.09711877538913292, 0.059005529454577245, 0.15737320167534957]
[0.12238213059896091, 0.09907377893252199, 0.09771834771001327, 0.08899382001739972, 0.1312868174831885]


作者:Temp https://www.zhihu.com/question/339723385/answer/1844269544

感觉可以一句话总结:如果计算softmax的元素方差太大,将会导致softmax结果稀疏,进而导致梯度稀疏

☆ END ☆

如果看到这里,说明你喜欢这篇文章,请转发、点赞。微信搜索「uncle_pn」,欢迎添加小编微信「 mthler」,每日朋友圈更新一篇高质量博文。

扫描二维码添加小编↓

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值