天天看點

Attention概述及代碼實作Attention機制

Attention機制

參考連結:

  1. 【NLP】Attention Model(注意力模型)學習總結(清晰易懂,較全面)
  2. https://jalammar.github.io/illustrated-transformer/(多圖,非常經典!)
  3. https://blog.csdn.net/qq_37394634/article/details/102679096(含實作代碼)
  4. https://nndl.github.io/
  5. https://github.com/philipperemy/keras-attention-mechanism/tree/0309dbf79da32c0d8d90925660fc4cc7fe53dc8a
  6. https://blog.csdn.net/uhauha2929/article/details/80733255

核心架構(Key-Value Attention):

Attention概述及代碼實作Attention機制

将Source中的構成元素想象成是由一系列的<Key,Value>資料對構成,此時給定Target中的某個元素Query,通過計算Query和各個Key的相似性或者相關性,得到每個Key對應Value的權重系數,然後對Value進行權重求和,即得到了最終的Attention數值。是以本質上Attention機制是對Source中元素的Value值進行權重求和,而Query和Key用來計算對應Value的權重系數。

Attention概述及代碼實作Attention機制
Attention概述及代碼實作Attention機制

打分函數:

模型 公式
加性模型 𝑠(𝒙, 𝒒) = 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, ⋯ , 𝒒𝑀 ],來并行地從輸入資訊中選取多組資訊,每個注意力關注輸入資訊的不同部分。

Attention概述及代碼實作Attention機制

結構化注意力

在之前介紹中,我們假設所有的輸入資訊是同等重要的,是一種扁平(Flat)結構,注意力分布實際上是在所有輸入資訊上的多項分布.但如果輸入資訊本身具有層次(Hierarchical)結構,比如文本可以分為詞、句子、段落、篇章等不同粒度的層次,我們可以使用階層化的注意力來進行更好的資訊選擇[Yang et al.,2016].此外,還可以假設注意力為上下文相關的二項分布,用一種圖模型來建構更複雜的結構化注意力分布[Kim et al., 2017]。

自注意力

如果要建立輸入序列之間的長距離依賴關系,可以使用以下兩種方法:一種方法是增加網絡的層數,通過一個深層網絡來擷取遠距離的資訊互動;另一種方法是使用全連接配接網絡.全連接配接網絡是一種非常直接的模組化遠距離依賴的模型,但是無法處理變長的輸入序列.不同的輸入長度,其連接配接權重的大小也是不同的.這時我們就可以利用注意力機制來“動态”地生成不同連接配接的權重,這就是自注意力模型(Self-Attention Model)。

引入Self Attention後會更容易捕獲句子中長距離的互相依賴的特征,因為如果是RNN或者LSTM,需要依次序序列計算,對于遠距離的互相依賴的特征,要經過若幹時間步步驟的資訊累積才能将兩者聯系起來,而距離越遠,有效捕獲的可能性越小。

為了提高模型能力,自注意力模型經常采用查詢-鍵-值(Query-Key-Value,QKV)模式,其計算過程如圖8.4所示,其中紅色字母表示矩陣的次元。

Attention概述及代碼實作Attention機制

代碼實作

  1. 相似度函數采用的是一層全連接配接層。全連接配接層的輸出經過softmax激活函數計算權重。他對隐層向量的每一維在每個時間步上進行了softmax操作,這裡函數的傳回值是三維的,也就是說這裡隻是乘上了權重,但并沒有求和。

    見GitHub: Many-to-one attention mechanism for Keras

  2. 參考https://colinraffel.com/publications/iclr2016feed.pdf
    Attention概述及代碼實作Attention機制

    在softmax之前還加了tanh激活函數,而且将輸出進行了求和,是以輸出是二維的。

    自定義Attention層:(若上接 LSTM 則需

    return_sequences=True

    ,即需LSTM輸出三維向量)
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]
           

繼續閱讀