本文为本人初学atttention机制和transform时的学习笔记,学习资料为李宏毅教授2021年的2021年春机器学习课程、黑马程序员2019年课程的部分内容以及datawhale的开源学习资料。如有理解不当之处,还望各位大佬多多指教。
文本张量的表示:将一段文本使用张量进行表示,其中一般将词汇为表示成向量,称作词向量,再由各个词向量按顺序组成矩阵形成文本表示。
又称独热编码,是一种稀疏矩阵。即将每个词表示成具有n个元素的向量(n的大小是整个语料中不同词汇的总数),这个词向量中只有一个元素是1,其他元素都是0,不同词汇元素为0的位置不同。
缺点:完全割裂了词与词之间的联系,而且在大语料集下,每个向量的长度过大,占据大量内存。
word2vec是一种将词汇表示成向量的无监督训练方法, 该过程需要构建神经网络模型, 将网络参数作为词汇的向量表示, 它包含CBOW和skipgram两种训练模式.
CBOW(Continuous bag of words)模式
给定一段用于训练的文本语料, 再选定某段长度(窗口)作为研究对象, 使用上下文词汇预测目标词汇.
分析:图中窗口大小为9, 使用前后4个词汇对目标词汇进行预测
skipgram模式
给定一段用于训练的文本语料, 再选定某段长度(窗口)作为研究对象, 使用目标词汇预测上下文词汇
分析:图中窗口大小为9, 使用目标词汇对前后四个词汇进行预测.
这两种方法都只考虑了一个window(窗口)内的信息,无法考虑整个sequence(句子)之间的相关性。如果使用一个比sequence长度还大的window,虽然可以覆盖整个sequence的信息,但是这需要window的长度比sequence还要长,不仅会导致参数过多,运算量大,还容易造成过拟合。
而Self-Attention,即自注意力机制,可以多个Vector并行输入,能考虑到整个input sequence的信息。
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
attention考虑整个input sequence的资讯,所以必须得计算每个vector之间的关联程度。α就是每一个input vector向量之间的关联的程度。
计算α有两种方法:
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
因为相关性有很多种不同的形式,所以我们应该要有多个 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。
这个方法的分配方式是,将0-1这个范围的,将第一个token分配0,最后一个token分配去1,其余的token按照文章的长度平均分配。具体形式如下:
**问题:**我们可以看到,如果句子长度不同,那么位置编码是不一样,所以无法表示句子之间有什么相似性。
这个方法比较直观,就是按照输入的顺序,一次分配给token所在的索引位置。具体形式如下:
问题:往往句子越长,后面的值越大,数字越大说明这个位置占的权重也越大,这样的方式无法凸显每个位置的真实的权重。
Transformer 的 Position 在 GPT-3 论文中给出的公式如下:
上个公式给出的每一个 Token 的位置信息编码不是一个数字,而是一个不同频率分割出来,和文本一样维度的向量。
得到位置向量 P之后,将和模型的embedding向量相加,得到进入Transformer模型的最终表示
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()