文章目录
前言
本文为本人初学atttention机制和transform时的学习笔记,学习资料为李宏毅教授2021年的2021年春机器学习课程、黑马程序员2019年课程的部分内容以及datawhale的开源学习资料。如有理解不当之处,还望各位大佬多多指教。
一、 文本张量的表示方法
文本张量的表示:将一段文本使用张量进行表示,其中一般将词汇为表示成向量,称作词向量,再由各个词向量按顺序组成矩阵形成文本表示。
1 One-hot Encoding
又称独热编码,是一种稀疏矩阵。即将每个词表示成具有n个元素的向量(n的大小是整个语料中不同词汇的总数),这个词向量中只有一个元素是1,其他元素都是0,不同词汇元素为0的位置不同。
缺点:完全割裂了词与词之间的联系,而且在大语料集下,每个向量的长度过大,占据大量内存。
2 word2vec
word2vec是一种将词汇表示成向量的无监督训练方法, 该过程需要构建神经网络模型, 将网络参数作为词汇的向量表示, 它包含CBOW和skipgram两种训练模式.
-
CBOW(Continuous bag of words)模式
给定一段用于训练的文本语料, 再选定某段长度(窗口)作为研究对象, 使用上下文词汇预测目标词汇.
分析:图中窗口大小为9, 使用前后4个词汇对目标词汇进行预测 -
skipgram模式
给定一段用于训练的文本语料, 再选定某段长度(窗口)作为研究对象, 使用目标词汇预测上下文词汇
分析:图中窗口大小为9, 使用目标词汇对前后四个词汇进行预测.
这两种方法都只考虑了一个window(窗口)内的信息,无法考虑整个sequence(句子)之间的相关性。如果使用一个比sequence长度还大的window,虽然可以覆盖整个sequence的信息,但是这需要window的长度比sequence还要长,不仅会导致参数过多,运算量大,还容易造成过拟合。
而Self-Attention,即自注意力机制,可以多个Vector并行输入,能考虑到整个input sequence的信息。
二、注意力机制
1 Self-Attention
Self-Attention的输入序列长度不固定,其对应的输出向量考虑了整个输入序列的信息,然后将输出向量输入到Fully-Connected网络中,做后续处理。
Self-Attention可以和Fully-Connected交替使用多次以提高网络的性能
1. Self-Attention处理整个Sequence的资讯
2. Fully-Connected的Network,专注于处理某一个位置的资讯
3. 再用Self-Attention,再把整个Sequence资讯再处理一次
4. 然后交替使用Self-Attention跟Fully-Connected
2 Self-Attention运算机制
2.1 向量间关联度α的计算方法
attention考虑整个input sequence的资讯,所以必须得计算每个vector之间的关联程度。α就是每一个input vector向量之间的关联的程度。
计算α有两种方法:
- Dot-product
输入的这两个向量分别乘上两个不同的矩阵Wq和Wk得到j矩阵q和矩阵k,再将q和k做点乘得到α,即两个矩阵之间的关联性。 - Additive
输入的这两个向量分别乘上两个不同的矩阵 Wq 和W k 得到j矩阵 q 和矩阵 k ,将 q 和 k 合并后经过一个激活函数,再通过一个Transform, 然后得到 α。
transform 中所用的方法为 Dot-product,所以我们以下所有的讨论只针对第一种方法
2.2 输出向量的计算方法
-
Step 1
a1, a2, a3, a4 分别与 Wq 相乘,得到 q1,q2,q3,q4。其中 q1,q2,q3,q4 统称为Query。
a1, a2, a3, a4 分别与 Wk 相乘,得到k1,k2,k3,k4。其中 k1,k2,k3,k4 统称为Key。
a1, a2, a3, a4 分别与 Wv 相乘,得到v1,v2,v3,v4。其中 v1,v2,v3,v4 统称为Value。 -
Step 2
q2 分别和k1,k3,k4 做Dot-product运算,得到 a1 与 a2, a3, a4 之间的关联性 α2,1 ,α2,3 ,α2,4 。
这个关联性 α 叫做 Attention 的 Score。
当然,a2也需要和自己计算关联度。将 q2 与 k2 做Dot-product运算即得到 a2 与自己的关联度 α2,2。
刚才计算得到的关联性 α 也可以接入一个激活函数(例:softmax激活函数),得到 α’2,1 ,α’2,2,α’2,3 ,α’2,4。 -
Step 3
得到 α’ 以后,将 α’ 与v1,v2,v3,v4 分别相乘,最后把相乘后的结果全部相加得到 b2。b2 即根据 α’ 抽取出的Sequence里面重要的资讯。 -
Note
若 a2 与 a1 关联性很强,则他们的Attention Score 的值 α’2,1 就会很高,在做完Weighted Sum以后,得到的 b2 的值,就可能会比较接近 v1。整个运算过程中,共涉及到三个不同的参数,分别是 Wq,Wk,Wv。
同理可以计算出其他输出向量 b1, b3, b4
2.3 常见的注意力计算规则
- 将Q,K进行纵轴拼接, 做一次线性变化, 再使用softmax处理获得结果最后与V做张量乘法.
- 将Q,K进行纵轴拼接, 做一次线性变化后再使用tanh函数激活, 然后再进行内部求和, 最后使用softmax处理获得结果再与V做张量乘法.
- 将Q与K的转置做点积运算, 然后除以一个缩放系数, 再使用softmax处理获得结果最后与V做张量乘法.
通过计算公式得到注意力的结果, 这个结果代表query在key和value作用下的注意力表示.
当输入的Q=K=V时, 称作自注意力计算规则.
2.4 多头注意力机制
因为相关性有很多种不同的形式,所以我们应该要有多个 q,不同的 q 负责不同形式的相关性,这就是多头注意力机制。
以 2 head 注意力机制为例,得到矩阵 q 后,将 q 分别乘以两个不同的权重 Wq,1, Wq,2 得到 qi,1, qi,2。i 代表词汇的位置,1 和 2 分别代表第几个位置的 q。k 和 v 同理。qi,1 和 ki,1 做 Dot-product 运算得到 ai 与自身的 attention score,qi,1 和 kj,1 做 Dot-product 运算得到 ai 与 aj 之间的attention score,将两个 α 分别乘以 vi,1 和 vj,1后相加得到 bi,1。
同理可以得到 bi,2。将b i,1 与 b i,2 拼接起来,乘以一个矩阵 W0,得到最后的输出 bi。
三 Positional Encoding
3.1 以前的方法——表格型
3.1.1 使用[0,1]范围分配
这个方法的分配方式是,将0-1这个范围的,将第一个token分配0,最后一个token分配去1,其余的token按照文章的长度平均分配。具体形式如下:
- 我喜欢吃洋葱 【0 0.16 0.32…1】
- 我真的不喜欢吃洋葱【0 0.125 0.25…1】
**问题:**我们可以看到,如果句子长度不同,那么位置编码是不一样,所以无法表示句子之间有什么相似性。
3.1.2 1-n正整数范围分配
这个方法比较直观,就是按照输入的顺序,一次分配给token所在的索引位置。具体形式如下:
- 我喜欢吃洋葱 【1,2,3,4,5,6】
- 我真的不喜欢吃洋葱【1,2,3,4,5,6,7】
问题:往往句子越长,后面的值越大,数字越大说明这个位置占的权重也越大,这样的方式无法凸显每个位置的真实的权重。
3.2 相对位置的关系-函数型
3.2.1 运算机制
Transformer 的 Position 在 GPT-3 论文中给出的公式如下:
上个公式给出的每一个 Token 的位置信息编码不是一个数字,而是一个不同频率分割出来,和文本一样维度的向量。
得到位置向量 P之后,将和模型的embedding向量相加,得到进入Transformer模型的最终表示
3.2.2 绘制特征的分布曲线:
import matplotlib.pyplot as plt
plt.figure(figsize=(15, 5))
pe = PositionalEncoding(20, 0)
y = pe(Variable(torch.zeros(1, 100, 20)))
plt.plot(np.arange(100), y[0, :, 4:8].data.numpy())
plt.legend(["dim %d"%p for p in [4,5,6,7]])
plt.show()
输出曲线:
效果分析:
- 每条颜色的曲线代表某一个词汇中的特征在不同位置的含义.
- 保证同一词汇随着所在位置不同它对应位置嵌入向量会发生变化.
- 正弦波和余弦波的值域范围都是1到-1这又很好的控制了嵌入数值的大小, 有助于梯度的快速计算.