Attention機制
參考連結:
- 【NLP】Attention Model(注意力模型)學習總結(清晰易懂,較全面)
- https://jalammar.github.io/illustrated-transformer/(多圖,非常經典!)
- https://blog.csdn.net/qq_37394634/article/details/102679096(含實作代碼)
- https://nndl.github.io/
- https://github.com/philipperemy/keras-attention-mechanism/tree/0309dbf79da32c0d8d90925660fc4cc7fe53dc8a
- https://blog.csdn.net/uhauha2929/article/details/80733255
核心架構(Key-Value Attention):
将Source中的構成元素想象成是由一系列的<Key,Value>資料對構成,此時給定Target中的某個元素Query,通過計算Query和各個Key的相似性或者相關性,得到每個Key對應Value的權重系數,然後對Value進行權重求和,即得到了最終的Attention數值。是以本質上Attention機制是對Source中元素的Value值進行權重求和,而Query和Key用來計算對應Value的權重系數。
打分函數:
模型 | 公式 |
---|---|
加性模型 | 𝑠(𝒙, 𝒒) = v T t a n h ( W x + U q ) v^Ttanh(Wx + Uq) vTtanh(Wx+Uq) |
點積模型 | 𝑠(𝒙, 𝒒) = x T q x^Tq xTq |
縮放點選模型 | 𝑠(𝒙, 𝒒) = x T q D \frac{x^Tq}{\sqrt{D}} D xTq |
雙線性模型 | 𝑠(𝒙, 𝒒) = x T W q x^TWq xTWq |
理論上,加性模型和點積模型的複雜度差不多,但是點積模型在實作上可以更好地利用矩陣乘積,進而計算效率更高。當輸入向量的次元𝐷 比較高時,點積模型的值通常有比較大的方差,進而導緻Softmax函數的梯度會比較小。是以,縮放點積模型可以較好地解決這個問題。
雙線性模型是一種泛化的點積模型。假設公式中𝑾 = 𝑼T𝑽,雙線性模型可以寫為𝑠(𝒙, 𝒒) = 𝒙T𝑼T𝑽𝒒 = (𝑼𝒙)T(𝑽𝒒),即分别對𝒙 和𝒒 進行線性變換後計算點積。相比點積模型,雙線性模型在計算相似度時引入了非對稱性。
多頭注意力
多頭注意力(Multi-Head Attention)利用多個查詢𝑸 = [𝒒1, ⋯ , 𝒒𝑀 ],來并行地從輸入資訊中選取多組資訊,每個注意力關注輸入資訊的不同部分。
結構化注意力
在之前介紹中,我們假設所有的輸入資訊是同等重要的,是一種扁平(Flat)結構,注意力分布實際上是在所有輸入資訊上的多項分布.但如果輸入資訊本身具有層次(Hierarchical)結構,比如文本可以分為詞、句子、段落、篇章等不同粒度的層次,我們可以使用階層化的注意力來進行更好的資訊選擇[Yang et al.,2016].此外,還可以假設注意力為上下文相關的二項分布,用一種圖模型來建構更複雜的結構化注意力分布[Kim et al., 2017]。
自注意力
如果要建立輸入序列之間的長距離依賴關系,可以使用以下兩種方法:一種方法是增加網絡的層數,通過一個深層網絡來擷取遠距離的資訊互動;另一種方法是使用全連接配接網絡.全連接配接網絡是一種非常直接的模組化遠距離依賴的模型,但是無法處理變長的輸入序列.不同的輸入長度,其連接配接權重的大小也是不同的.這時我們就可以利用注意力機制來“動态”地生成不同連接配接的權重,這就是自注意力模型(Self-Attention Model)。
引入Self Attention後會更容易捕獲句子中長距離的互相依賴的特征,因為如果是RNN或者LSTM,需要依次序序列計算,對于遠距離的互相依賴的特征,要經過若幹時間步步驟的資訊累積才能将兩者聯系起來,而距離越遠,有效捕獲的可能性越小。
為了提高模型能力,自注意力模型經常采用查詢-鍵-值(Query-Key-Value,QKV)模式,其計算過程如圖8.4所示,其中紅色字母表示矩陣的次元。
代碼實作
-
相似度函數采用的是一層全連接配接層。全連接配接層的輸出經過softmax激活函數計算權重。他對隐層向量的每一維在每個時間步上進行了softmax操作,這裡函數的傳回值是三維的,也就是說這裡隻是乘上了權重,但并沒有求和。
見GitHub: Many-to-one attention mechanism for Keras
- 參考https://colinraffel.com/publications/iclr2016feed.pdf
在softmax之前還加了tanh激活函數,而且将輸出進行了求和,是以輸出是二維的。
自定義Attention層:(若上接 LSTM 則需
,即需LSTM輸出三維向量)return_sequences=True
class AttentionLayer(Layer):
def __init__(self, **kwargs):
super(AttentionLayer, self).__init__(** kwargs)
def build(self, input_shape):
assert len(input_shape)==3
# W.shape = (time_steps, time_steps)
self.W = self.add_weight(name='att_weight',
shape=(input_shape[1], input_shape[1]),
initializer='uniform',
trainable=True)
self.b = self.add_weight(name='att_bias',
shape=(input_shape[1],),
initializer='uniform',
trainable=True)
super(AttentionLayer, self).build(input_shape)
def call(self, inputs):
# inputs.shape = (batch_size, time_steps, seq_len)
x = K.permute_dimensions(inputs, (0, 2, 1))
# x.shape = (batch_size, seq_len, time_steps)
a = K.softmax(K.tanh(K.dot(x, self.W) + self.b))
outputs = K.permute_dimensions(a * x, (0, 2, 1))
outputs = K.sum(outputs, axis=1)
return outputs
def compute_output_shape(self, input_shape):
return input_shape[0], input_shape[2]