weights = softmax( Q K T d k \frac{QK ^T}{\sqrt{d_k}} dk QKT) ( d k d_k dk 是Q和K的维度)
3、使用概率分布权重乘以V矩阵,我们就得到了注意力公式,也叫缩放点积自注意力
output = weights · V = softmax( Q K T d k \frac{QK ^T}{\sqrt{d_k}} dk QKT)·V
在上面计算苹果梨的例子中,Q、K、V都是来源于同一个句子序列,对于这种句子中某个token对同一个句子序列中的所有token求注意力权重的,我们称之为自注意力机制;而传统注意力机制(交叉注意力机制):如翻译场景,Q来自同一个序列(梨和苹果都是水果)、K、V来自另外的序列,如:Pears and apples are both fruits(早期的交叉注意力并没有QKV一说,而是序列到序列(Seq2Seq)的注意力机制,有兴趣可以了解下)。
这里就有两个疑问:为何要用除以一个数?为何是 d k \sqrt{d_k} dk ?当然过程可能涉及数学推导,这里简要说下(不是本文重点):
当Q和K的维度特别大的时候,内积也会变得很大,由于softmax通过指数计算,容易导致数值爆炸增长,同时元素间的差值和方差也变大失真,使softmax后的概率分布变得更加尖锐(即某些位置的概率接近1,而其他位置的概率接近0,大的大小的小),导致模型损失对概率小的位置的关注,通过损失函数求导过程中对softmax求导,对于接近0的元素的梯度变得极小(梯度消失),影响权重收敛。除以 d k \sqrt{d_k} dk ,可以是softmax后的概率分布更加平滑。
同时 d k \sqrt{d_k} dk 是一个经验取值,通过推导可以得到更优的值。 竟然这么麻烦,为何不直接用余弦相似函数计算向量间夹角再通过softmax计算权重? 其实在后面我们将要学习的位置编码中,有类似的原理。 注意: 细心的小伙伴可能发现,我们将句子从"苹果梨",改成"梨苹果",最终的到的新苹果和新梨,竟然是一样的,因为苹果和梨两个向量调换顺序后,对应计算的权重也换了顺序,因此最终计算出来的结果一样,有兴趣的小伙伴可以试着算一算。
4、实际上,自注意力机制中Q、K、V,是通过对输入做不同的线性变换得到,同一个输入,分别与 W Q 、 W K 、 W V {W^Q}、W^K、W^V WQ、WK、WV相乘,其中 W Q 、 W K {W^Q}、W^K WQ、WK维度 d k {d_k} dk(列数)相同,行数与输入token维度相同 ;W V W^V WV 维度 d v {d_v} dv任意,行数与输入的token维度相同。
然后将得到的Q、K、V代入softmax( Q K T d k \frac{QK ^T}{\sqrt{d_k}} dk QKT)·V
最终输出的维度与V的维度相同。
为何要 W Q 、 W K 、 W V {W^Q}、W^K、W^V WQ、WK、WV三个矩阵: 主要是为了通过线性变化,使模型更容易关注到某些特征:
图中红色表示不同的水果、蓝色表示不同的手机,通过变换1,可以将水果和手机的点区分开更容易提取特征完成分类。而变换2,所有的点聚集一起,难以区分。 W Q 、 W K 、 W V {W^Q}、W^K、W^V WQ、WK、WV就是这样的变换矩阵。
对于二维三维的空间,可能通过人工设计一个变换矩阵,但对于高维向量空间,这几乎不可能,因此 W Q 、 W K 、 W V {W^Q}、W^K、W^V WQ、WK、WV 也是通过大量的语料训练得到, W V W^V WV的将输入投射到更高维或者更低维空间,实现特征的扩展或者压缩,也直接影响output的维度,也就影响关注到的特征数目。
1、每个输入token经过 Q K T QK ^T QKT得到的内积,都会得到一个维度与key的行数相等的的单行矩阵s = [ s 1 , s 2 , . . . , s n ] [s_1,s_2,...,s_n] [s1,s2,...,sn],s中的每个si元素就是单个输入token的Q与key的每行记录的相似度,我们可以直接通过 s i s 1 + s 2 + . . . + s n \frac{s_i}{s_1+s_2+...+s_n} s1+s2+...+snsi得到每个s的权重。 注意: s元素个数是K的行数相等,也就是 K T K ^T KT的列数,不是 K T K ^T KT的行数,
2、由于内积计算结果可能是负数,也可能是0,会导致 s i s 1 + s 2 + . . . + s n \frac{s_i}{s_1+s_2+...+s_n} s1+s2+...+snsi无法计算
3、因此引入softmax函数,将权重归一化到[0,1]:
p i = e s i ∑ j = 1 n e s j ( i = 1 , 2 , . . . n ) p_i = \frac{e^{s_i}}{∑_{j=1}^{n}e^{s_j}} ( i = 1,2,... n) pi=∑j=1nesjesi(i=1,2,...n)
s i s_i si表示经过 Softmax 函数转换后的第 i 个元素,e 是自然对数的底,分母是对所有输入元素 e s j e^{s_j} esj的求和,最终得到
P = [ p 1 , p 2 , . . . , p n ] [p_1,p_2,...,p_n] [p1,p2,...,pn],每个p元素就是K矩阵每个token与输入token的相似度权重。
注意: 当Q和K的维度特别大的时候,内积也会变得很大,因此 e s i e^{s_i} esi的值可以出现指数爆炸的情况,导致元素间差距变大(方差变大),导致某些元素概率接近1,某些接近0,这也是上面说到为何需要除以 d k \sqrt{d_k} dk 的原因。
在大模型中,有个超参叫temperature,也是跟softmax函数有关系,带temperature的softmax函数表示如下:
p i = e s i / T ∑ j = 1 n e s j / T ( i = 1 , 2 , . . . n ) p_i = \frac{e^{s_i/T}}{∑_{j=1}^{n}e^{s_j/T}} ( i = 1,2,... n) pi=∑j=1nesj/Tesi/T(i=1,2,...n)
他的作用跟 d k \sqrt{d_k} dk 差不多,也是为了控制概率分布的平滑性,由于大模型通过概率选择下一个需要出现的词token,T越小,某些元素的概率越大,越有可能被选中为下一个词,生成内容越保守,T越大,概率分布越平均,下一个词出现的概率越随机,生成的内容更有创造性,或者,胡说八道。
多头注意力:
多头注意力(multi-heads)就是将同一个输入序列,经过多组不同的 W Q 、 W K 、 W V {W^Q}、W^K、W^V WQ、WK、WV处理,最后将结果拼接。
每组不同的 W Q 、 W K 、 W V {W^Q}、W^K、W^V WQ、WK、WV,,每组不同的 W Q 、 W K 、 W V {W^Q}、W^K、W^V WQ、WK、WV相当于一个head,每个头关注不同方面的数据特征,并且可并行计算,提高模型的表达能力,表现更丰富的依赖关系。
输入序列的多个token,经过 Q K T QK ^T QKT的处理一定是个n*n的矩阵(上图省略了k的生成过程,因 W Q 、 W K {W^Q}、W^K WQ、WK形状相同,生成的Q和K形状也相同),n为token个数,即为输入Q的行数。
以 n * n矩阵的第一行为例,第一行的四个格子分别代表的是"我" 分别与 "我","喜欢","学习","Python"四个词token计算的内积得分,与三角矩阵逐乘后,只有第一格有得分,经过softmax计算得到权重矩阵[1,0,0,0];
n * n矩阵的第二行:是"喜欢",分别和"我","喜欢","学习","Python"四个词token计算的内积得分与三角矩阵逐乘后,只有前两个格有得分,经过softmax计算得到权重矩阵[0.4,0.6,0,0](数值随便写的);
模型的参数量:
我们经常听到说大模型参数量多少B,这个参数量主要由以下部分组成: 嵌入矩阵: n* m个参数;(n为词库token数,m为嵌入矩阵维度(列数)) W Q {W^Q} WQ: m* k个参数;(m为词嵌入的维度,k为 W Q {W^Q} WQ的维度) W K {W^K} WK: m* k个参数;(m为词嵌入的维度,k为 W K {W^K} WK的维度) W V {W^V} WV: m* v个参数:(m为词嵌入的维度,为 W V {W^V} WV的维度) 多头注意力层数: M,那么 W Q 、 W K 、 W V {W^Q}、W^K、W^V WQ、WK、WV的个数还需要分别再乘以M 解嵌入矩阵: v* n个参数;( v为嵌入矩阵维度(也是 W V {W^V} WV的维度),n为词库token数) 其他隐藏层权重W和偏置b: 若干
假设词库token个数:50000,维度16384, W Q 、 W K 、 W V {W^Q}、W^K、W^V WQ、WK、WV的维度8192,注意力头96个,暂不计算隐藏层,得到总参数量:50000 * 16384 + 96*16384 * 8192 * 3 + 8192 * 16384 ≈ 4B(四十亿)。