深入理解 Attention 機制(下)- Scaled Dot-Product Attention 與其例子

FunCry
8 min readMar 1, 2023

--

介紹

上一篇文章中,我們介紹了機器翻譯遇到的難題,並且介紹了 Neural Machine Translation by Jointly Learning to Align and Translate 中提出的 Attention 雛形。

這篇文章將著重介紹 Transformer 背後的 Scaled Dot-Product Attention,並詳細解釋計算邏輯還有其設計理念,文章的最後也會提供一個使用 Attention 的例子,希望能讓讀者看完後對 Attention 有更全面的理解。

Scaled Dot-Product Attention

之前提到的方法雖然解決了 Context Vector 不管用的問題,但如果遇到很長的句子或文章,模型還是無法快速處理輸入 。為了加快運算,運用平行計算的優勢,理想的做法應該是摒棄一個字一個字讀的方法。在 Attention Is All You Need 這篇論文中,便提出了 Scaled Dot-Product Attention 來實現這樣的想法。它的計算方式如下:

公式看起來很複雜,為了說清楚背後的原理,我們一步一步來看究竟發生了什麼。

1. QKᵀ

在這一步中,Q (Query) 和 K (Key) 是兩個矩陣,我們假設 Q 裡面有三筆資料,K 裡面有四筆資料,那這兩個矩陣的維度分別是 3 * dₖ4 * dₖ ,注意兩個矩陣要有一樣數量的 Column,解讀方式是:

  • Q 矩陣裡面有三筆資料,每筆資料用一個長度為 dₖ 的向量表示
  • K 矩陣裡面有四筆資料,每筆資料用一個長度為 dₖ 的向量表示

如果你原本用來表示 Q 和 K 的序列維度不一樣,又或者你想要制定某個特別的 dₖ,那可以分別用 Linear(input_q_dim, dₖ)Linear(input_k_dim, dₖ) 來把原本的 Query 和 Key 做線性轉換成 dₖ 維。這兩個 layer 的作用是把兩個序列轉到同樣的向量空間

現在你已經得到 Q 和 K 兩個矩陣了,他們長下面這樣(下面假設 dₖ = 4)

我們來看看 QKᵀ 在做的到底是什麼:

從上面的動圖可以發現,QKᵀ 會產生一個 3 * 4 (Query 的數量 * Key 的數量)的矩陣,這個矩陣的第 i, j 個元素是由 第 i 個 q 和第 j 個 k 內積 算出來的!

這個步驟其實對應了標題 Dot-Product 的部分,計算出來的矩陣 A 像是一個查詢表,第 i, j 個元素代表的是 第 j 個 key 對第 i 個 query 的重要性

對這一段做個結論。從輸入到做 QKᵀ 運算的這部分,模型在做的事情其實是

  1. 將輸入的 Query 以及 Key 轉換到同一個向量空間,在這個向量空間裡面,越相關的 Query 和 Key 內積的值會越大(模型會自己學會要怎麼做這個轉換)
  2. 用內積算出 Attention 表,我們把這個表取名為 A。

2. softmax(A /√dₖ)

這部分其實對應了 Scaled 的部分,要看懂的話我們必須先了解 softmax 函式

對於 A 裡面每個 row,softmax 會把裡面每個元素轉換成 0 到 1 的之間的數值,而每個 row 的數值加起來會等於 1。我們仔細觀察 row 裡面某個元素,在其他數值不變的情況下,單一數值的座標會長下面這樣:

可以發現在特別大或特別小的地方梯度(斜率)幾乎為 0,導致參數沒辦法更新,而如果你設定的 dₖ 特別大,上面利用內積計算出來的 A 就有比較高的可能性出現落在這些地方的數值(因為總共有 dₖ 個東西要相乘後加總)

除以 dₖ 就是為了讓數值落在這些地方的可能變小,降低訓練時受到的阻礙。

我們把通過 softmax 的矩陣稱作 A’

進階(可略過):

假設你的 q 和 k 向量裡面每個數值都是獨立從 N(0, 1) 這個常態分布抽取出來的,根據內積的算式

q k 的期望值會是 0,但變異數會是 dₖ,除以 dₖ 可以把變異數拉回 1。

3. A’V

在開始這段之前,先複習一下 A’ 是什麼,A’

  1. 有跟 Query 數量一樣多的 row
  2. 有跟 Key 數量一樣多的 column
  3. 每個 row 裡面的數值都介於 0 和 1 之間,第 j 個元素代表第 j 個 Key 對這個 Query 的重要性
  4. 單一 row 裡面所有數值加起來等於 1

假設 A’ 長下面這樣

接下來要討論 V,代表的意義是 Key 背後真正的數值,可以把 Key 想像成學號,Value 想像成姓名、班級、成績等資訊,你用學號來找到這個人,但是他的相關資訊才是你真正需要的東西,對模型來說也是一樣,他真正用來計算的東西是 V 的數值。

V 的維度用 dᵥ 表示,你可以把它設成任何你認為合適的數值。一樣可以用 Linear(input_k_dim, dᵥ) 來將輸入向量轉換到這個維度。

注意上面這行指令中我把第一個參數設成 input_k_dim,這是因為 K 和 V 的源頭應該要是同一個向量,只是一個被轉去 Q 的空間和它比對,另一個被轉譯成真實的數值。換句話說,Key 和 Value 是有一對一的對應關係的,第一個 Value 對應到第一個 Key,第二個 Value 對應到第二個 Key ……

V 的樣子長下面這樣:

最後我們來看看 A’V 代表什麼

從上面的算式可以發現,A’V 會:

  1. 產生一個矩陣,這個矩陣 row 的數量就跟 Query 的數量一樣多
  2. 對於每個 Query 來說,它的最終數值是將 V 裡面的 row 向量做加權平均
  3. 加權平均的權重依據是 Query 和其對應的 Key 做內積

Scale Dot-Product Attention 小結

其實就是在做兩件事

  1. 建立查詢表(Query 和 Key 內積算權重,再把權重轉換成 0 和 1 之前的數值)
  2. 根據查詢表,用 Value 矩陣的加權平均算出 Query 的最後數值

你也可以把 Key-Value 想像成某種資料庫,而 Attention 在做的事情其實就是 根據資料庫裡的內容,找出一組合適的向量來代表每個 Query

Query 和 Key-Value 在上面的介紹是兩種不同的序列,但其實兩者的輸入可以是同一個序列,在這樣的情況下就被稱為 Self-Attention

Self-Attention 在自然語言處理特別常用到,根據上面的邏輯,可以把輸出看做考量前後文後每個字對應的 word-embedding

舉例

文章的最後提供讀者一個使用 Attention 的例子,加深大家的理解。

假設今天我想要將資訊工程系和哲學系(兩個 Query)轉換成模型可以理解的向量,而資料庫裡面有英文、社會、數學、物理四個科目(四個 Key-Value pair),模型算出來的 Attention table 可能會長下面這樣:

解讀方式如下,對於 XX 系,這四個科目的重要性分別為 ……

接下來我們需要 Value 的數值,這裡我設定 dᵥ = 3,Value 的三個數值分別代表記憶力、語言能力、邏輯推理能力。

(注意:真實情況下我們沒辦法知道 Value 的三個 column 分別代表什麼,模型會自己找出它們該表示什麼。)

解讀方式如下,對於 XX 科目,記憶力、語言、邏輯推理分別需要 OO 分才能念好。

(分數純屬虛構)

將上面的兩個矩陣相乘

最後算出的如下,解讀方式是 XX 系的 OO 能力分別需要達到多少分才能念好。

而模型也會分別用 6.9 7.5 10.18.3 8.7 7.3 兩個向量來代表這兩個科系。

希望這個例子能讓你更了解 Attention 在做什麼,以及該如何設定 Attention 的維度。

結論

這篇文章詳細介紹了 Scaled Dot-Product Attention 的計算細節,設計邏輯並且提供了一個使用 Attetion 的例子,若仔細比對前一篇的模型,就會發現兩個架構雖然看起來很不一樣,大致上的邏輯卻是差不多的

實際上的 Transformer 除了 Attention 外還有許多細節,除了 Encoder 和 Decoder 的架構外,還有 MultiHead、Positional Encoding 等,日後若有機會再好好介紹這個主題。

--

--