一般输入是一个向量,但是有时问题比较复杂,比如遇到文字处理、语音识别、图像识别等问题时,输入变得比较复杂,需要输入一组向量,且输入的个数不是稳定的,每次输入的序列长度不一样。
FC V.S. Self-Attention
做词性标注(Part-Of-Speech tagging, POS tagging) 时需要标注句子中每个单词的词性,但是遇到句子比如 “I saw a saw” 时如果使用全连接网络 (Full Connected network) 就不能很好的识别各个单词的词性,因为作为输入的两个 “Saw” 是完全一样的,实现词性标注需要网络考虑更多的信息,如图
这样就是给全连接网络一整个窗口的信息,让他考虑上下文。但是有局限,比如语音识别中如果一个任务不是只考虑这一个窗口就可以解决,而是要考虑一个序列,这样就不合适了。
如果只是简单的将窗口开大,这个全连接网络就需要非常多的参数,运算量可能很大,还容易发生过拟合,此时可以考虑自注意力模型。
Self-Attention 运作原理
自注意力模型会考虑整个序列的参数,输入几个向量就输出几个。输出的向量再放进全连接网络得出结果。
计算过程
输入一组向量 a a a ,输出一组向量 b b b ,每个 b b b 都是考虑了所有 a a a 得到的。接下来介绍 b 1 b^1 b1 产生的过程:
1. 根据 a 1 a^1 a1 找出与之相关的其他向量
用 α \alpha α 表示每两个向量之间的关系。把左边的向量乘上矩阵 W q W^q Wq ,右边的向量乘上矩阵 W k W^k Wk ,得到两个向量 q q q 和 k k k ,再做逐元素(element-wise)相乘,得到标量 α \alpha α 。当然还有其他方法,但是这是最常用的方法
2. 套用到Self-Attention中
自注意力模型采用 QKV (查询-键-值) 模式,分别计算 a 1 , a 2 , a 3 , a 4 a^1, a^2, a^3, a^4 a1,a2,a3,a4 之间的关联性 α \alpha α
-
首先计算查询 q i q^i qi 和键 k i k^i ki
q 1 = W q × a 1 , k 1 = W k × a 1 q^1=W^q\times a^1, \space k^1=W^k \times a^1 q1=Wq×a1, k1=Wk×a1
k 2 = W k × a 2 , k 3 = W k × a 3 , k 4 = W k × a 4 k^2=W^k \times a^2, \space k^3=W^k \times a^3, \space k^4=W^k \times a^4 k2=Wk×a2, k3=Wk×a3, k4=Wk×a4
-
然后通过计算查询 q 1 q^1 q1 与键 k i k^i ki 之间的内积(Inner-product)计算注意力分数 α 1 , i \alpha_{1, i} α1,i
-
得到注意力分数之后在进行 softmax 操作得到 α ′ \alpha' α′
α 1 , j ′ = exp ( α 1 , j ) ∑ j exp ( α 1 , j ) \alpha'_{1,j} = \frac{\exp(\alpha_{1,j})}{\sum_j \exp(\alpha_{1,j})} α1,j′=∑jexp(α1,j)exp(α1,j) -
得到 α ′ \alpha' α′ 之后,根据关联性抽取重要信息
由 a 1 a^1 a1 到 a 4 a^4 a4 累积 W v W^v Wv 权重的向量: v 1 , v 2 , v 3 v^1, v^2, v^3 v1,v2,v3 和 v 4 v^4 v4,按下述规律每一个向量都被赋予上注意力加权的数值 α ′ \alpha' α′,再把它们加起来
v i = W v × a i b 1 = ∑ i α 1 , i ′ v i v^i = W^v \times a^i \\ b^1 = \sum_i \alpha'_{1,i} v^i \\ vi=Wv×aib1=i∑α1,i′vi
此时,关联性越强, a 1 , i ′ a_{1, i}' a1,i′ 的值越大,加权之后得到的值就越接近 v i v^i vi 。
Vectorization
multi-head self-attention 多头注意力
翻译、语音识别中会用到多头注意力,多了一个超参数就是头的个数
简单理解
就是分多个组,不同组的矩阵相乘得到不同的组,工作时只考虑这一个组,不考虑其他组了,其他与单头相同
应用
Positional Encoding 位置编码
做POS tagging时,知道单词的位置很重要。比如一个动词一般不会出现在句首,一般是名词。
所以说自注意力层还需要位置信息,决定每一个输入在序列中的位置。此时要使用位置编码(Postional Encoding)
位置编码为每个位置设定一个位置向量 e i e^i ei ,直接在 a i a^i ai 上面加上 e i e^i ei 作为输入,就可以得到位置的信息。
位置编码是 hand-crafted
truncated self-attention 截断自注意力
truncated self-attention 可以解决向量序列长度过大的问题。有时在 NLP中,不需要看一整句话,只要看一个小的范围即可