輕鬆理解 Transformers(2):Attention部分

Baihai_IDP發表於2023-10-30

編者按:隨著人工智慧技術的不斷髮展,Transformers 模型架構已成為自然語言處理領域的重要基石。然而,許多人對其內部工作機制仍然感到困惑。本文透過淺顯易懂的語言和生活中的例子,幫助讀者逐步理解 Transformers 中最核心的 Attention 機制。

本文是Transformers系列的第二篇。作者的核心觀點是:Attention 機制是 Transformers 模型區分關鍵資訊的關鍵所在。本文透過直觀的類比和數學公式,讓讀者對 Attention 的計算過程有更深入的理解。文章詳細介紹了Attention 機制如何辨別不同單詞的重要性;Query、Key、Value 矩陣及其在 Attention 計算過程中的作用;Masking 如何遮蔽無關內容;Dropout、Skip Connection 等機制如何提升模型穩定性;Add & Norm 層的工作原理,以及歸一化對模型學習的重要性。

雖然 Transformers 中各個元件之間相互關聯,難以一口氣理解全貌,但本文透過耐心講解 Attention 這一核心機制,確實讓讀者對整體架構有了更紮實的把握。我們衷心希望這類通俗易懂的文章能幫助更多讀者瞭解 Transformers 技術的執行原理。

以下是譯文,enjoy!

作者 | Chen Margalit

編譯 | 嶽揚

???歡迎小夥伴們加入 AI技術軟體及技術交流群 ,追蹤前沿熱點,共探技術難題~

Transformers 對人工智慧領域,乃至對整個世界都產生了深遠的影響。這種模型架構由多個元件構成,但正如提出該架構那篇論文的題目——Attention is All You Need,顯然注意力機制(Attention)具有特別重要的意義。本系列的第二部分將主要關注注意力(Attention)及其相關功能,這些功能確保了 Transformer 各元件的良好配合。

輕鬆理解 Transformers(2):Attention部分

圖片來自 Vaswani, A. 等人的論文[1]

01 注意力機制(Attention)

在 Transformers 中, attention 指的是一種機制,它能讓模型在處理過程中專注於輸入(input)的相關部分。 可以將其想象成一把手電筒,照亮句子的特定部分,並根據語境(context)判斷其在句子中的重要程度。 我認為舉幾個例子比直接將定義擺出來更有效,透過提供具體的例子,可以激發大腦的思考和理解能力,使大腦有機會自己去理解概念,而不僅僅依賴於定義。

當看到句子“The man took the chair and disappeared”時,我們自然而然地會對句子的不同部分賦予不同程度的重要性(即注意力(attention))。但令我驚訝的是,如果我們去掉一些特定的詞,句子的意思基本保持不變:“man took chair disappeared”。雖然這個版本的英語句子有些不通順,但與原句相比,我們仍然可以理解這句話要表達資訊的本質。有趣的是,三個單詞("The"、"the "和 "and")佔據了句子中詞數的43%,但對句子的整體意思沒有太大影響。在柏林生活期間,我的德語說得非常棒,每一個接觸過我的柏林人可能都這麼認為(要麼學好德語,要麼快樂,這是我必須做出的決定),但對於機器學習模型來說,這一點就不那麼明顯了。

過去,像迴圈神經網路(RNNs)等早期架構面臨著一個重大挑戰: 它們難以“記住”輸入序列(長度通常超過20個單詞)中較遠位置的單詞。眾所周知,這些模型主要依靠數學運算來處理資料。不幸的是,這些早期模型架構中使用的數學運算不夠高效,無法將單詞表徵傳遞到序列的較遠位置。

這種長程依賴(long-term dependency)的限制阻礙了迴圈神經網路(RNN)長時間保持上下文資訊的能力,從而影響了語言翻譯或情感分析等任務,因為在這些任務中,理解整個輸入序列至關重要。然而, Transformer 透過其注意力機制和自注意力機制更有效地解決了這個問題。 它們可以高效地捕捉輸入中的長距離依賴關係,使模型能夠保留語境和關聯資訊,即使是序列中更早出現的單詞也不例外。因此,Transformer 已成為克服以往架構限制的開創性解決方案,並明顯提高了各種自然語言處理任務的效能。

要創造出像我們今天所遇到的聊天機器人這樣的優秀產品,就必須讓模型具備區分高價值和低價值單詞的能力,並在輸入的中長距離保留上下文資訊。Transformer架構為應對這些挑戰而引入的機制被稱為注意力機制。

02 點積 Dot Product

神經網路模型如何在理論上辨別不同單詞的重要性呢? 在分析句子時,我們的目標是找出相互之間關係更緊密的詞語。 由於這些單詞已經被表示為向量(由數字組成),因此我們需要一種測量數字之間相似性的方法。測量向量之間相似性的數學術語是“點積”(Dot Product)。它涉及將兩個向量的元素相乘,併產生一個標量值(例如2、16、-4.43),該值能夠表示這兩個向量的相似性。機器學習建立在各種數學運算的基礎上,其中點積尤為重要。因此,我將花時間詳細解釋這一概念。

個人感覺和直觀理解 Intuition

假設我們將下面這5個單詞轉換為嵌入表徵:“florida”, “california”, “texas”, “politics”和“truth”。由於嵌入(embeddings)只是由數字組成的陣列,我們可以將其繪製在圖表上。但是,由於它們的維度(用於表示單詞的數字數量)很高,可以輕鬆達到 100 到 1000,因此我們無法將它們原封不動地繪製出來。我們無法在2維的計算機/手機螢幕上繪製一個100維的向量。此外,人腦很難理解超過3維的東西。4維向量是什麼樣子的?我不知道。

為了解決這個問題,我們採用了主成分分析(PrincipalComponentAnalysis,PCA[2])這一降維技術。透過應用PCA,我們可以將嵌入投影到二維空間(x、y座標)。 維度的減少有助於我們在圖表上更直觀地展現資料。雖然降維後會丟失一些資訊,但希望這些降維後的向量仍然能夠保持足夠的相似性,從而使我們能夠深入瞭解和理解詞語之間的關係。

這些資料基於 GloVe 嵌入[3]。

florida = [-2.40062016, 0.00478901]
california = [-2.54245794, -0.37579669]
texas = [-2.24764634, -0.12963368]
politics = [3.02004564, 2.88826688]
truth = [4.17067881, -2.38762552]

也許你會發現這些數字有一些規律可循,但為了方便起見,現在來繪製這些數字。

輕鬆理解 Transformers(2):Attention部分

圖中有5個二維向量

在這張圖片中,我們能夠看到五個二維向量(用x,y座標表示),分別代表五個不同的單詞。正如我們所見,該圖示表明了有些單詞與其他單詞的關聯度更高。

數學 math

透過一個簡單的方程,我們可以將向量的數學表示與這張圖片對應起來。如果您對數學不是特別感興趣,並且記得《Attention is All You Need》的論文作者將 Transformer 架構描述為“簡單的網路架構”,有時候機器學習領域的概念和技術可能會讓人感到複雜或難以理解,這可能是真的,但在本文中不會是這樣,本文所討論的內容都是相對簡單的。我來解釋一下:

輕鬆理解 Transformers(2):Attention部分

點積計算公式

符號 ||a|| 表示向量 "a" 的大小,它表示從原點(點 0,0)到向量頂端的距離。計算向量大小的公式如下:

輕鬆理解 Transformers(2):Attention部分

向量大小計算公式

計算結果會是一個數字,如 4 或 12.4。

Theta(θ)指的是向量之間的角度(可以看一下上方的圖片)。角度的餘弦值,表示為cos(θ),是將餘弦函式應用於該角度值的簡單結果。

程式碼 Code

史丹佛大學的研究人員使用 GloVe 演算法[3]為這些單詞生成嵌入,這些我們在前文討論過。雖然他們有建立這些嵌入的自有技術,但其基本概念與我們在本系列前一部分中談到的相同。舉個例子,選取 4 個單詞,將它們的維度降為 2,然後將它們的向量直接繪製成 x 座標和 y 座標。

為了使這個過程順利執行,下載GloVe[3]是必要的先決條件。

*下面是部分程式碼,第一個框中的程式碼,靈感來自於我之前見過的一些程式碼,但我似乎已經找不到原始碼了。

import pandas as pd
path_to_glove_embds = 'glove.6B.100d.txt'
glove = pd.read_csv(path_to_glove_embds, sep=" ", header=None, index_col=0)
glove_embedding = {key: val.values for key, val in glove.T.items()}

words = ['florida', 'california', 'texas', 'politics', 'truth']
word_embeddings = [glove_embedding[word] for word in words]
print(word_embeddings[0]).shape # 100 numbers to represent each word.
---------------------
output:
(100,)

pca = PCA(n_components=2) # reduce dimensionality from 100 to 2.
word_embeddings_pca = pca.fit_transform(word_embeddings)

for i in range(5):
 print(word_embeddings_pca[i])
---------------------
output:
[-2.40062016 0.00478901] # florida
[-2.54245794 -0.37579669] # california
[-2.24764634 -0.12963368] # texas
[3.02004564 2.88826688] # politics
[ 4.17067881 -2.38762552] # truth

現在我們擁有了這5個單詞的真實表徵,下一步是進行點積計算。

計算向量大小:

import numpy as np
florida_vector = [-2.40062016,  0.00478901]
florida_vector_magnitude = np.linalg.norm(florida_vector)
print(florida_vector_magnitude)
---------------------
output:
2.4006249368060817 # The magnitude of the vector "florida" is 2.4.

計算兩個相似向量之間的點積:

import numpy as np
florida_vector = [-2.40062016,  0.00478901]
texas_vector = [-2.24764634 -0.12963368]
print(np.dot(florida_vector, texas_vector))
---------------------
output:
5.395124299364358

計算兩個不同向量之間的點積:

import numpy as np
florida_vector = [-2.40062016, 0.00478901]
truth_vector = [4.17067881, -2.38762552]
print(np.dot(florida_vector, truth_vector))
---------------------
output:
-10.023649994662344

從點積計算中可以明顯看出,它似乎捕捉並反映了不同概念之間的相似性。

03 縮放點積注意力 Scaled Dot-Product attention

個人感覺和直觀理解 Intuition

既然我們已經基本掌握了點積的計算方法,那麼就可以開始深入研究注意力機制(attention)了,特別是自注意力機制(self-attention mechanism)。 使用自注意力機制使模型能夠確定每個單詞的重要性,而不管它與其他單詞的“物理”距離是多少。這使得模型能夠根據每個單詞的上下文相關性(contextual relevance)做出比較明智的決策,從而更好地理解單詞。

為了實現這一宏偉目標,我們建立了由可學習引數(learnable parameters)組成的3個矩陣,稱為查詢矩陣(Query)、鍵矩陣(Key)和值矩陣(Value)(Q、K、V)。查詢矩陣(query matrix)可以看作是一個包含使用者查詢或詢問的矩陣(例如,當您詢問ChatGPT:“上帝今天下午5點有空嗎?(god is available today at 5 p.m.?)”時,這就是查詢矩陣)。鍵矩陣(key matrix)包含序列中的所有其他單詞。透過計算這些矩陣之間的點積,我們可以得到每個單詞與我們當前正在研究的單詞之間的相關程度(例如,翻譯或回答使用者的詢問)。

值矩陣(value matrix)為序列中的每個單詞都提供了一種“乾淨”的表示(“clean” representation)。其他兩個矩陣都是以類似的方式形成的,為什麼我只說值矩陣“乾淨(clean)”?因為值矩陣保持在其原始形式,我們不會在與另一個矩陣相乘後使用它,也不會用某個值對它進行歸一化處理。這種區別使得值矩陣與眾不同,確保它保留了原始的嵌入,無需額外的計算或變換。

這三個矩陣的大小都是 word_embedding (512)。不過,它們都被分成了“heads”。在論文中,作者使用了8個“heads”(譯者注:heads指的是將注意力機制分解為多個子機制的一種方法。模型可以同時關注輸入的不同方面,並從中獲取更豐富的資訊。這種分解可以增加模型的表達能力和效能。),因此每個矩陣的大小為 sequence_length 乘以64。你可能會問,為什麼同樣的操作要對 1/8 的資料執行 8 次,而不是對所有資料執行一次。這種方法的理論基礎是,透過使用8組不同的權重(如前所述,這些權重是可學習的)進行相同的操作8次,我們可以利用資料中固有的多樣性。每個“heads”可以專注於輸入中的一個特定方面,總的來說,這可以帶來更好的效能。

*在大多數實施方案中,我們實際上並沒有將主矩陣分成8份。透過索引,可以實現分割,從而為每個部分實現並行處理。然而,這些只是實現細節。不過,這些只是實現細節。從理論上講,我們可以用 8 個矩陣完成幾乎相同的操作。

我們將查詢矩陣Q和鍵矩陣K進行點積運算,然後將結果除以維度的平方根進行歸一化。然後將歸一化後的結果透過Softmax函式[4]進行處理,然後將結果與值矩陣V相乘。之所以要對結果進行歸一化處理,是因為查詢矩陣Q和鍵矩陣K是以某種隨機方式生成的矩陣。它們的維度可能完全不相關(獨立),而獨立矩陣之間的乘法可能會產生非常大的數值,這可能會對學習效果產生不利影響,我將在本系列的後續部分中解釋。

然後,我們使用一種名為Softmax[4]的非線性變換(non-linear transformation),使所有數字的範圍介於 0 到 1 之間,並且總和為1。結果類似於機率分佈(因為有從0到1的多個結果數字相加得到1)。這些數字體現了序列中每個單詞與其他單詞的相關性。

最後,我們將結果與矩陣V相乘,就得到了自注意力分數(self-attention score)。

*實際上,編碼器由N(在論文中,N=6)個相同的層構成,每個層從上一層獲取輸入並執行相同的操作。最後一層將資料傳遞給解碼器(我們將在本系列的後續部分中討論)和編碼器的上層。

這是自注意力機制的視覺化影像。它就像教室裡的一群朋友,有些人與某些人的聯絡更緊密,有些人與任何人的聯絡都不太緊密。

輕鬆理解 Transformers(2):Attention部分

圖片來自 Vaswani, A. 等人的論文[1]

數學 math

查詢矩陣Q、鍵矩陣K和值矩陣V是透過對嵌入矩陣進行線性變換得到的。線性變換在機器學習中非常重要,如果你對成為一名機器學習從業者感興趣,我建議你進一步探索這個知識點。本文不會進行深入探討,但我要說的是,線性變換是一種將向量(或矩陣)從一個空間移動到另一個空間的數學操作。聽起來似乎比實際要複雜得多。想象一個箭頭指向一個方向,然後移動到右邊30度的位置。這就是線性變換的示例。線性變換需要滿足一些條件才能被認為是線性的,但現在並不重要。關鍵是它保留了許多原始向量的特性。

自注意力層的整個計算是透過應用以下公式來完成的:

輕鬆理解 Transformers(2):Attention部分

縮放點積注意力——圖片來自 Vaswani, A. 等人的論文[1]

計算過程如下所示:

  1. 用Q乘以K的轉置(翻轉)。

  2. 將結果除以矩陣 K 維度數的平方根。

  3. 然後有了描述每個單詞與其他單詞相似程度的“注意力矩陣分數(attention matrix scores)”。將每一行進行 Softmax[4](非線性)變換。Softmax[4] 有三個有趣的相關功能:

  4. a.  縮放所有數字,使其介於 0 和 1 之間。

  5. b.  使所有數字的和為1。

  6. c.  突出差距,使得稍微更重要的部分變得更加重要。因此,我們現在可以輕鬆區分模型對單詞x1與x2、x3、x4等之間聯絡的不同感知程度。

  7. 將計算出來的分數與矩陣V相乘。這是自注意力機制操作的最終結果。

04 Masking

在本系列的前一章中,我已經解釋過我們使用虛擬標記來處理句子中出現的特殊情況,如句子中的第一個單詞、最後一個單詞等。其中一個標記,表示為<PADDING>,表示沒有實際資料,但我們需要在整個過程中保持一致的矩陣大小。為了確保模型理解這些是虛擬標記,並且在自注意力的計算過程中對其不予考慮,我們將這些標記表示為負無窮大(例如一個非常大的負數,例如-153513871339)。掩碼值被新增到Q乘以K的乘積結果中。然後,Softmax將這些數字轉換為0。 這使我們能夠在注意力機制(attention mechanism)中有效地忽略虛擬標記,同時保持計算的完整性。

05 Dropout

在自注意力層之後,應用了一種被稱為 Dropout 的操作。Dropout是機器學習中廣泛使用的一種正則化技術。正則化的目的是在訓練過程中對模型施加約束,使其難以過度依賴特定的輸入細節。這樣,模型就能夠更加穩健地學習,並提高其泛化能力。具體實現包括隨機選擇一些啟用值(activations)(來自不同層的輸出數字),並將它們置零。在同一層的每次傳遞中,都有不同的啟用值將被置零,從而防止模型根據所獲資料找到特定的解決方案。 從本質上講,Dropout有助於增強模型處理不同輸入內容的能力,並使模型難以針對資料中的特定模式進行調整。

06 Skip Connection

Transformer架構中的另一個重要操作稱為Skip Connection。

輕鬆理解 Transformers(2):Attention部分

圖片來自 Vaswani, A. 等人的論文[1]

Skip Connection是一種在不經過任何轉換的情況下傳遞輸入(input)的方法。舉例來說,假設我向我的經理報告,而我的經理又向他的經理報告。即使是出於讓報告更有用的純粹目的,輸入內容在經過另一個人(或 ML 層)處理時,也會進行一些修改。在這個類比中,Skip Connection就像是我直接向我的經理的經理彙報。因此,上級經理既透過我的經理(經過處理的資料)接收輸入,也直接從我這裡(未經處理的資料)接收輸入。然後,上級經理可以更好地做出決策。 採用Skip Connection是為了解決梯度消失等潛在問題,我將在下一節中解釋。

07 Add & Norm 層

"Add & Norm"層主要執行加法和歸一化操作。我先說加法,因為它比較簡單。基本上,我們是將自注意力層的輸出與原始輸入(透過Skip Connection接收)相加。這個加法是逐元素進行的(每個數字與其相同位置的數字相加)。然後對結果進行歸一化。

我們之所以進行歸一化處理,原因是每個層都要進行大量計算。數字多次相乘可能會導致意想不到的情況。例如,如果我取一個小數,比如0.3,然後將其與另一個小數,比如0.9相乘,得到的結果是0.27,會比起開始時更小。如果我多次這樣做,最終可能會得到非常接近於0的結果。這可能會導致深度學習中的一個問題,即梯度消失。

我現在不想說得太深,以免這篇文章讀起來費時費力,但我想說的是,如果數字變得非常接近 0,模型將無法學習。 現代機器學習的基礎是計算梯度,並使用這些梯度(以及其他一些因素)調整權重。如果這些梯度接近於0,模型將很難有效地學習。

相反,當非小數與非小數相乘時,可能會發生相反的現象,即 梯度爆炸(exploding gradients) ,會導致值變得過大。因此, 由於權重和啟用值的巨大變化,模型的學習會面臨困難,從而導致訓練過程中的不穩定性和發散性。

機器學習模型有點像小孩子,它們需要保護。保護這些模型免受數字過大或過小的影響的一種方法是歸一化。

數學 math

層歸一化操作雖然看起來很可怕(一如既往),但實際上相對簡單。

輕鬆理解 Transformers(2):Attention部分

圖片由 Pytorch 提供,摘自此處[5]

在層歸一化操作中,我們需要對每個輸入執行以下簡單步驟:

  • 從輸入中減去其均值。

  • 除以方差的平方根並加上一個epsilon(ε)(一個非常小的數字),用於避免除以零。

  • 將得到的得分乘以一個可學習的引數,稱為gamma(γ)。

  • 新增另一個可學習的引數,稱為beta(β)。

  • 這些步驟可確保均值接近於0,標準差接近於1。歸一化過程增強了訓練的穩定性、速度和整體效能。

程式碼 Code

# x being the input.
(x - mean(x)) / sqrt(variance(x) + epsilon) * gamma + beta

08 總結

至此,我們對編碼器的主要內部工作原理有了紮實的瞭解。此外,我們還探索了Skip Connection,這是機器學習中一種純粹的技術(也是一種重要的技術),可以提高模型的學習能力。

儘管本節內容有點複雜,但讓我們已經對整個 Transformer 架構有了實質性的瞭解。隨著我們在本系列中的進一步深入,理解本部分的內容將有助於你理解本系列中其他部分的內容。

請記住,這是一個前沿領域中的較新技術。學起來並不簡單。即使您現在仍然沒有完全理解所有內容,您也已經取得了很大的進步!

下一部分將介紹機器學習中的另一個基礎(且更簡單)的概念,即前饋神經網路。

輕鬆理解 Transformers(2):Attention部分

圖片來自 Vaswani, A. 等人的論文[1]

END

???歡迎小夥伴們加入 AI技術軟體及技術交流群 ,追蹤前沿熱點,共探技術難題~


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/70018536/viewspace-2991905/,如需轉載,請註明出處,否則將追究法律責任。

相關文章