【基礎整理】attention:淺談注意力機制與自注意力模型(附鍵值對注意力 + 多頭注意力)
划水休息兩天不看論文了 ~ 來重新複習一下基礎qaq
以下講解參考大名鼎鼎的 nndl
邱錫鵬 《神經網路與深度學習》
部分內容(詳見第八章,注意力與外部記憶)是對於不太行的初學者也比較友好的一本,當然不能要求一本書既全面又深入,閱讀過程還是建議自己去更多地從別的渠道瞭解細節內容,但個人覺得即使是順著通讀亦對關於深度學習的整體框架搭建蠻有幫助的qaq
同時參考了這篇綜述:
An Attentive Survey of Attention Models
,具體這篇論文的閱讀筆記也蠻多的就不找時間再寫了(
https://www.cnblogs.com/ydcode/p/11040811.html
這篇就寫的很好~)
1 background
2 整體架構
2。1 計算注意力分佈
2。2 計算加權分佈
2。3 在 encode-decode 中的應用舉例
3 常用注意力機制的變體
3。1 鍵值對注意力 key-value pair
3。2 多頭注意力 Multi-Head Attention
4 自注意力 Self-Attention
4。1 查詢 - 鍵值對注意力模型 Query-Key-Value,QKV
4。2 多頭自注意力 Multi-Head Self-Attention
5 summary
1 background
注意力機制本身想要解決的問題很簡單,就是算不動了
在整體模型越來越龐大的情況下,大家明顯地覺得運算開始吃力了,這樣的問題下直觀的思想就是考慮如何
按重要性更好地將手頭有限的計算資源進行分配
,以保證更多的計算資源可以分配到確實重要的內容上,而儘量不要太浪費在所謂不重要的內容上。人腦面對海量資訊往往利用
注意力
將部分不重要的資訊略去而只關注於重要的資訊,這裡將注意力分為兩種:
自上而下的有意識的注意力,也就是
聚焦式注意力(Focus Attention)
:此時的注意力是確定地有一個目的的,也就是會主動地去關注某一個特定的物件,本身依賴目的,存在預定的任務(舉例閱讀理解問題,此時給定問題以後,關注的只是和問題相似的文字段落物件,對其他物件可以少輸入或不輸入模型以節約計算資源)
自下而上的無意識的注意力,也就是
基於顯著性的注意力(Saliency Based Attention)
:也就是說此時並沒有預先根據某種目的或任務關注某一個特定的物件,而是單純地當某一個物件表現出某種特徵的時候,比如某一個物件值很大時則轉而主動關注這樣的物件(舉例 max 池化,門控機制)
這裡來一個 nndl 中的例子:
一個和注意力有關的例子是雞尾酒會效應。當一個人在吵鬧的雞尾酒會上和朋友聊天時,儘管周圍噪音干擾很多,他還是可以聽到朋友的談話內容,而忽略其他人的聲音(聚焦式注意力)。同時,如果背景聲中有重要的詞(比如他的名字),他會馬上注意到(顯著性注意力)
從這個思路出發,當前已經進行了較多的嘗試,比如最簡單的
池化層
:最大池化本身也就是選擇一個範圍內的最大值儲存下來,直觀理解可以認為就是隻關注了值最大的部分而將其他部分內容捨去,以更好地將更寶貴的計算資源放在可能重要的部分
進一步地從當前主流的 encode - decode (編碼器 - 解碼器)模型來討論一下
注意力機制
的優勢。傳統的編碼器解碼器模型存在以下兩個很大的問題:
編碼器需要把輸入的資訊
轉化為一個定長的序列
才能給到解碼器進行處理,也就意味著此時容易造成資訊的損失(非要塞到一個定長的序列裡)
此時輸入的序列和最後解碼器的輸出本身
難以作對齊
,以翻譯問題來說,我輸入 Tom chase Jerry,此時由於編碼器 RNN 是平等地對每一個詞來進行編碼操作的,也就是說我最後翻譯出的 湯姆 本身是依賴了相同權重的 Tom 、chase、 Jerry 這三個詞。但明顯 湯姆 的翻譯應該更多地依賴 Tom 才對,這就造成了本身輸入序列和輸出序列的不對齊。這同樣也影響了本身神經網路的解釋性問題,將所有輸入的東西都以相同的權重看待將導致難以解釋我最後的結果到底是依賴什麼得出的。
而
注意力機制
,也就是嘗試
在輸入的資訊上計算注意力分佈
→ 從而得到
不同輸入資訊對應當前任務的重要性分佈 = 不同的權重
→ 再根據不同的重要性,也就是不同的權重
計算當前輸入資訊的加權平均
,以實現(對重要的,和任務相關的資訊賦予更高的權重,而將不重要的資訊基本忽略或賦予較低的權重)以更有效率地利用計算資源
2 整體架構
注意力機制
本身只是一種思想,並不依賴某一個特定的模型(雖然總是依賴編碼器 - 解碼器的模型來解釋它),可以簡單地總結為兩個步驟:
在給定的資訊上計算注意力分佈
(也就是判斷什麼資訊重要,什麼資訊不重要,分別賦予不同的權重)
根據注意力分佈來計算所有輸入資訊的加權平均
2.1 計算注意力分佈
簡化問題,考慮此時輸入 N 個向量 :
,我想要從中選出對於我的目標而言比較重要的資訊,需要引入我的目標任務的表示,稱為
查詢向量(query vector)
,則此時問題可以轉換為考察
輸入的不同內容和查詢向量之間的相關度
,一個簡單的思路就是透過一個
注意力打分函式
對不同內容進行打分,賦予與我當前任務比較相關的部分更大的權重,再直接地透過一個 softmax 層得到分佈,也就是輸入資訊的不同部分的權重。
這裡的注意力打分函式主要有以下幾種:
加性模型:
點積模型:
縮放點積模型:
雙線性模型:
上面的 W U 都是可以學習的引數,D是輸入向量的維度
比較常用的就是
點積模型
,簡單 + 有效
透過每一個輸入 x 和 q 計算得分函式 → 再透過 softmax 層,則第 i 個輸入 xi 對應的權重也就是
2.2 計算加權分佈
這裡分為兩種方式:
軟性注意力機制
:也就是每一個輸入的按各自權重的加權平均
硬性注意力機制
:也就是隻關注某一個向量,此時用某一個向量來直接代替所有輸入的資訊,而將其他的資訊都一概忽略
主要有以下兩種形式:
選擇權重最大的向量
在注意力分佈上進行隨機取樣(也就是權重越大的向量越容易被採到)
但是注意到,這裡硬性注意力機制的最大的問題就是它本身是不可導的(比如選擇權重最大實際上就是通過了一個 max 函式),也就是說這一步會導致無法使用反向傳播演算法,一般只能依賴強化學習進行訓練
2.3 在 encode-decode 中的應用舉例
在這裡舉個例子,考慮 seq2seq 框架下的 編碼器 - 解碼器模型中注意力機制最簡單的應用方式
整體如下,此時左邊是正常的編碼器-解碼器模型,右邊是加入了注意力模組的
經過 encode,此時輸入 x1 x2 x3 對應的得到三個隱藏狀態 h1 h2 h3,考察上一步中解碼器已經得到的隱藏狀態 s2,可以將 s2 作為查詢向量,計算所有的隱藏狀態 h1 h2 h3 和 s2 的相關度(這裡的得分是透過一個前饋神經網路來學習的) → 得到注意力分佈 → 得到 h1 h2 h3 的聚合內容,也就是圖中的 c2,再進一步依據模型設計將 c2 用於解碼器
3 常用注意力機制的變體
實際使用的時候直接利用最原本的模式的情況是不多的,這裡講幾個應用比較廣泛的變體:
3.1 鍵值對注意力 key-value pair
也就是利用
鍵值對
的方式來輸入資訊,此時不再是隻輸入一個 x,而以:
的方式輸入 N 組資訊。這裡滿足:
鍵 = k 用來計算注意力分佈
值 = v 用來基於注意力分佈最後計算聚合後的資訊
其他內容和基本形式是一樣的,也就是說此時的聚合資訊可以表示為(如果利用軟性的資訊聚合,打分函式為 s):
工作實質如圖所示:
階段1 → 透過打分函式,利用查詢向量 q,對此時輸入的 (鍵 key)的部分進行打分 階段2 → 透過 softmax 將不同的打分作歸一化處理,得到各個部分的注意力權重,也就是注意力分佈 階段3 → 透過輸入的 (值 value)結合注意力分佈進行資訊聚合
K=V 的時候也就是普通的模型
3.2 多頭注意力 Multi-Head Attention
也就是此時存在多個查詢 Q:
來透過一種
並行
的方式從輸入中搜索需要的資訊。直觀理解就是解決問題需要很多不同的方面的資訊,每一個不同的 qi 考察的都是不同的方面,此時利用不同的 qi 從不同的角度給輸入資訊的重要性進行打分,再進行某種程度的聚合。
一般不同查詢對應得到的聚合資訊直接用向量拼接的方式:
4 自注意力 Self-Attention
考慮當前針對輸入序列的編碼方式,如果我們需要將輸入序列轉化為一個定長的序列,此時卷積和迴圈神經網路均是較好的選擇,但是注意到以上兩種均只是一種區域性編碼的方式(迴圈神經網路本身由於長程依賴問題 / 梯度消失,實際上也只能建模區域性的資訊)
換一個思路,如果我想要捕捉整個輸入序列中的某種長程依賴關係,此時常用的方法包括:
構建深層網路來捕捉關係 → 也就是增加神經網路的層數,但是大家這麼幹過都知道直接粗暴增加層數是很消耗計算資源的
構造全連線網路 → 但是無法處理變長的序列,也就是說此時輸入的序列必須要是等長的 = 輸入層的神經元個數
想要模擬全連線神經網路的思路來構建一種更好的,可以處理變長輸入序列 + 捕捉長距離關係的模型,可以考慮利用注意力機制來
動態地
生成權重,這也就是
自注意力模型
的主要思路
4.1 查詢 - 鍵值對注意力模型 Query-Key-Value,QKV
考慮到往常的使用頻率,這裡先介紹一下最常用的
查詢 - 鍵值對注意力模型(Query-Key-Value,QKV)
,實際上為了增強模型效果,基本不會使用上面廣義形式對應的自注意力模型
假設此時的輸入序列為 x,則自注意力模型可以分為以下幾個步驟:
將輸入的 x
線性投影到三個不同的空間
,以分別得到查詢向量 qi,鍵向量 ki,值向量 vi
注意這裡線性投影的含義就是學習到三個不同的矩陣 Wq Wk Wv:
也可以看作是一個簡單的前饋神經網路。注意這裡因為自注意力模型的打分函式常常使用點積形式,所以這裡得到的 qi ,ki,vi 三個結果往往是相同維度的
利用上述得到的查詢向量,鍵向量和值向量,透過上述的
鍵值對注意力機制得到輸出
。也就是說如果這裡得到的查詢向量,鍵向量和值向量分別為:
,則此時直接透過鍵值對注意力機制的方式來計算最後的輸出:
整體圖解如下:
也就是說,輸入三個(這裡設 N=3)X 序列,每一個長度為 Dx,則此時得到三個查詢向量,每一個查詢向量得到一個對應的 (這三個 x 序列的線性組合),則此時得到三個結果,對應拼在一起,不改變輸入的 X 的對應 N 這部分的維度,但是將長度 Dx 改變為了 Dv(這裡的 Dv 是可以任意設定的,只要透過操作此時從 X 到值 V 的投影操作對應的矩陣 Wv 就可以了)
也就是說透過上述操作,此時可以將不定長的序列 Dx 動態地生成適合的權重並轉化為某一個定長 Dv
4.2 多頭自注意力 Multi-Head Self-Attention
其實也就是上述的自注意力操作加上了自注意力的思路
比如說此時對應的 x 是 Dx 維度,共 N 個,我每一次透過一個矩陣 Wq 將其投影為一個查詢矩陣的時候都可以一次性得到 N 個查詢向量,這 N 個查詢向量可以保證後續輸出的結果還是共 N 個(只是另一個維度由值向量的維度 Dv 決定),這是我們上一節的思路
考慮多頭注意力,也就是說此時我們考慮能不能得到多個查詢矩陣,以從不同的角度來捕捉 X 的重要情況,則此時我採用多個矩陣 Wqi 將它投影到 m 個不同的空間分別得到 m 個查詢矩陣,共 m*N 個向量,再分別計算輸出,最後採用向量拼接的方式把它拼起來得到最後的結果,這裡思路是十分接近的,就不多說了。
5 summary
簡單總結一下注意力機制的幾個優點:
直觀上了解,它可以同時捕捉全域性和區域性的聯絡,也就是說每一個 xi 的對應的權重都是和全域性比較後得出的(也就是 softmax 部分)
大大減少了計算時間,直觀理解也就是更多地將算力用在了確實需要注意的,與任務更加相關的重要的部分
支援並行處理 ,注意力機制的計算都不依賴一層一層的結果輸出,所以可以並行進行操作計算
本身模型很簡單(可能只是簡單的點積 / 前饋神經網路,最後再加入一層 softmax),也就是說並不會為當前的模型帶來太大的負擔,本身引數也不多,訓練容易
某種程度上或許可以幫助提高神經網路模型的解釋性,也就是說透過計算注意力分佈,我可以知道我當前的答案或許是更多地來自哪一個輸入,從而更好地為未來的結果提供一定的解釋
但是可以注意到此時缺點也是很明顯的:
將所有的輸入(對比到 encode - decode 模型也就是 encoder 部分的 隱藏層 h1 h2 h3)均平行對待,也就是說並沒有考慮輸入可能存在位置關係(比如 h2 就是在 h1 和 h3 之間輸入的),而是並行地計算它們和查詢向量 q 的關係,對於 nlp 任務來說本質上是損失了資訊的
當然後續的模型大多加入位置資訊 embedding 來幫助緩解這個問題(比如 BERT 就是這麼幹的),所以並不認為這就是 attention 用在 nlp 上的致命傷
理解深度有限,存在錯誤 / 不足歡迎指出!期待進一步討論~
轉載請註明出處。知識見解與想法理應自由共享交流,禁止任何商用行為!