目前,AIGC(AI-Generated Content,人工智能生產內容)發展迅猛,選代速度呈現指數級增長,全球范圍內經濟價值預計將達到數萬億美元。在中國市場,AIGC的應用規模有望在2025年突破2000億元,這一巨大的潛力吸引著業內領軍企業競相推出千億、萬億級參數量的大模型,底層GPU算力部署規模也達到萬卡級別。以GPT3.5為例,參數規模達1750億,作為訓練數據集的互聯網文本量也超過45TB,其訓練過程依賴于微軟專門建設的AI超算系統,以及由1萬顆V100GPU組成的高性能網絡集群,總計算力消耗約為3640PF-days(即每秒一千萬億次計算,運行3640天)。
分布式并行計算是實現AI大模型訓練的關鍵手段,通常包含數據并行、流水線并行及張量并行等多種并行計算模式。所有并行模式均需要多個計算設備間進行多次集合通信操作。另外,訓練過程中通常采用同步模式,多機多卡間完成集合通信操作后才可進行訓練的下一輪迭代或計算。
Transformer 是 Google 的團隊在 2017 年提出的一種 NLP 經典模型,現在比較火熱的 Bert 也是基于 Transformer。Transformer 模型使用了 Self-Attention 機制,不采用 RNN 的順序結構,使得模型可以并行化訓練,而且能夠擁有全局信息。
Transformer模型實在論文《Attention Is All You Need》里面提出來的,用來生成文本的上下文編碼,傳統的上下問編碼大多數是由RNN來完成的,不過,RNN存在兩個缺點:
a、計算是順序進行的,無法并行化,例如:對于一個有10個單詞的文本序列,如果我們要得到最后一個單詞的處理結果,就必須要先計算前面9個單詞的處理結果。
b、RNN是順序計算,存在信息的衰減,所以很難處理相隔比較遠的兩個單詞之間的信息,因此,RNN通常和attention相結合使用。 ? ?
針對RNN的缺陷,《Attention Is All You Need》提出了Transformer模型解決這個問題。Transformer由多頭注意力、位置編碼、層歸一化和位置前向神經網絡等部分構成。
Transormer和seq2seq模型一樣,由Encoder和Decoder兩大部分組成,其中左側的是Encoder,右側的是Decoder。模型主要由多頭注意力和前饋神經網絡組成。 ? ?
這里有個關鍵的點--位置編碼。使用RNN的進行處理的時候,每個輸入天然存在位置屬性,但這也是RNN的弊端之一。文本單詞的排列與文本的語義有很大的關聯,所以文本的位置是一個很重要的特征,因此,在Transformer模型里面,加入了位置編碼來保留單詞的位置信息。
編碼部分:Encoder
a、多頭注意力
多頭注意力是Transformer模型的重要組成部分,通過下面的圖,我們來看看多頭注意力的結構。
多頭注意力是self-attention(自注意力)的拓展,對與self-attention不熟悉,可以參考self-attention詳解 ,相對于self-attention,多頭注意力再兩個方面有所提高:
擴展了模型在文本序列不同位置的注意力能力。相對于self-attention,self-attention的最終輸出中,包含了其他詞的很少信息,其注意力權重主要由詞語本身即query占主導位置。
賦予attention多種子表達方式。使用多頭注意力機制,我們會有多組的Q、K、V參數矩陣(Transformer使用了8個heads,所以會有8組參數矩陣)。 ? ?
1. Transformer 結構
首先介紹 Transformer 的整體結構,下圖是 Transformer 用于中英文翻譯的整體結構。
Transformer 整體結構
可以看到 Transformer 由 Encoder 和 Decoder 兩個部分組成,Encoder 和 Decoder 都包含 6 個 block。Transformer 的工作流程大體如下:
第一步:獲取輸入句子的每一個單詞的表示向量?X,X由單詞的 Embedding 和單詞位置的 Embedding 相加得到。 ? ?
Transformer 的輸入表示
第二步:將得到的單詞表示向量矩陣 (如上圖所示,每一行是一個單詞的表示?x) 傳入 Encoder 中,經過 6 個 Encoder block 后可以得到句子所有單詞的編碼信息矩陣?C,如下圖。單詞向量矩陣用?X(n×d)表示, n 是句子中單詞個數,d 是表示向量的維度 (論文中 d=512)。每一個 Encoder block 輸出的矩陣維度與輸入完全一致。 ? ?
Transformer Encoder 編碼句子信息
第三步:將 Encoder 輸出的編碼信息矩陣?C傳遞到 Decoder 中,Decoder 依次會根據當前翻譯過的單詞 1~ i 翻譯下一個單詞 i+1,如下圖所示。在使用的過程中,翻譯到單詞 i+1 的時候需要通過?Mask (掩蓋)?操作遮蓋住 i+1 之后的單詞。 ? ?
Transofrmer Decoder 預測
上圖 Decoder 接收了 Encoder 的編碼矩陣?C,然后首先輸入一個翻譯開始符 "",預測第一個單詞 "I";然后輸入翻譯開始符 "" 和單詞 "I",預測單詞 "have",以此類推。這是 Transformer 使用時候的大致流程,接下來是里面各個部分的細節。
2. Transformer 的輸入
Transformer 中單詞的輸入表示?x由單詞 Embedding 和位置 Embedding 相加得到。
Transformer 的輸入表示
2.1 單詞 Embedding
單詞的 Embedding 有很多種方式可以獲取,例如可以采用 Word2Vec、Glove 等算法預訓練得到,也可以在 Transformer 中訓練得到。 ? ?
2.2 位置 Embedding
Transformer 中除了單詞的 Embedding,還需要使用位置 Embedding 表示單詞出現在句子中的位置。因為 Transformer 不采用 RNN 的結構,而是使用全局信息,不能利用單詞的順序信息,而這部分信息對于 NLP 來說非常重要。所以 Transformer 中使用位置 Embedding 保存單詞在序列中的相對或絕對位置。
位置 Embedding 用?PE表示,PE?的維度與單詞 Embedding 是一樣的。PE?可以通過訓練得到,也可以使用某種公式計算得到。在 Transformer 中采用了后者,計算公式如下:
其中,pos 表示單詞在句子中的位置,d 表示?PE的維度 (與詞 Embedding 一樣),2i 表示偶數的維度,2i+1 表示奇數維度 (即 2i≤d, 2i+1≤d)。使用這種公式計算?PE?有以下的好處:
使?PE?能夠適應比訓練集里面所有句子更長的句子,假設訓練集里面最長的句子是有 20 個單詞,突然來了一個長度為 21 的句子,則使用公式計算的方法可以計算出第 21 位的 Embedding。可以讓模型容易地計算出相對位置,對于固定長度的間距 k,PE(pos+k) 可以用?PE(pos) 計算得到。因為 Sin(A+B) = Sin(A)Cos(B) + Cos(A)Sin(B), Cos(A+B) = Cos(A)Cos(B) - Sin(A)Sin(B)。將單詞的詞 Embedding 和位置 Embedding 相加,就可以得到單詞的表示向量?x,x?就是 Transformer 的輸入。
3. Self-Attention ? ?
Transformer Encoder 和 Decoder
上圖是論文中 Transformer 的內部結構圖,左側為 Encoder block,右側為 Decoder block。紅色圈中的部分為?Multi-Head Attention,是由多個?Self-Attention組成的,可以看到 Encoder block 包含一個 Multi-Head Attention,而 Decoder block 包含兩個 Multi-Head Attention (其中有一個用到 Masked)。Multi-Head Attention 上方還包括一個 Add & Norm 層,Add 表示殘差連接 (Residual Connection) 用于防止網絡退化,Norm 表示 Layer Normalization,用于對每一層的激活值進行歸一化。 ? ?
因為?Self-Attention是 Transformer 的重點,所以我們重點關注 Multi-Head Attention 以及 Self-Attention,首先詳細了解一下 Self-Attention 的內部邏輯。
3.1 Self-Attention 結構
Self-Attention 結構
上圖是 Self-Attention 的結構,在計算的時候需要用到矩陣?Q(查詢),?K(鍵值),?V(值)。在實際中,Self-Attention 接收的是輸入(單詞的表示向量?x組成的矩陣?X) 或者上一個 Encoder block 的輸出。而?Q,?K,?V?正是通過 Self-Attention 的輸入進行線性變換得到的。 ? ?
3.2 Q, K, V 的計算
Self-Attention 的輸入用矩陣?X進行表示,則可以使用線性變陣矩陣?WQ,?WK,?WV?計算得到?Q,?K,?V。計算如下圖所示,注意 X, Q, K, V 的每一行都表示一個單詞。
Q, K, V 的計算 ? ?
3.3 Self-Attention 的輸出
得到矩陣?Q,?K,?V之后就可以計算出 Self-Attention 的輸出了,計算的公式如下。
Self-Attention 的輸出
公式中計算矩陣?Q和?K?每一行向量的內積,為了防止內積過大,因此除以 dk 的平方根。Q?乘以?K?的轉置后,得到的矩陣行列數都為 n,n 為句子單詞數,這個矩陣可以表示單詞之間的 attention 強度。下圖為?Q?乘以?K?的轉置,1234 表示的是句子中的單詞。
QKT 的計算
得到?QKT 之后,使用 Softmax 計算每一個單詞對于其他單詞的 attention 系數,公式中的 Softmax 是對矩陣的每一行進行 Softmax,即每一行的和都變為 1。 ? ?
對矩陣的每一行進行 Softmax
得到 Softmax 矩陣之后可以和?V相乘,得到最終的輸出?Z。
Self-Attention 輸出
上圖中 Softmax 矩陣的第 1 行表示單詞 1 與其他所有單詞的 attention 系數,最終單詞 1 的輸出?Z1 等于所有單詞 i 的值?Vi 根據 attention 系數的比例加在一起得到,如下圖所示:
Zi 的計算方法 ? ?
3.4 Multi-Head Attention
在上一步,我們已經知道怎么通過 Self-Attention 計算得到輸出矩陣?Z,而 Multi-Head Attention 是由多個 Self-Attention 組合形成的,下圖是論文中 Multi-Head Attention 的結構圖。
Multi-Head Attention ? ?
從上圖可以看到 Multi-Head Attention 包含多個 Self-Attention 層,首先將輸入?X分別傳遞到 h 個不同的 Self-Attention 中,計算得到 h 個輸出矩陣?Z。下圖是 h=8 時候的情況,此時會得到 8 個輸出矩陣?Z。
多個 Self-Attention ? ?
得到 8 個輸出矩陣?Z1 到?Z8 之后,Multi-Head Attention 將它們拼接在一起 (Concat),然后傳入一個?Linear層,得到 Multi-Head Attention 最終的輸出?Z。
Multi-Head Attention 的輸出
可以看到 Multi-Head Attention 輸出的矩陣?Z與其輸入的矩陣?X?的維度是一樣的。
4. Encoder 結構 ? ?
Transformer Encoder block
上圖紅色部分是 Transformer 的 Encoder block 結構,可以看到是由 Multi-Head Attention, Add & Norm, Feed Forward, Add & Norm 組成的。剛剛已經了解了 Multi-Head Attention 的計算過程,現在了解一下 Add & Norm 和 Feed Forward 部分。 ? ?
4.1 Add & Norm
Add & Norm 層由 Add 和 Norm 兩部分組成,其計算公式如下:
Add & Norm 公式
其中?X表示 Multi-Head Attention 或者 Feed Forward 的輸入,MultiHeadAttention(X) 和 FeedForward(X) 表示輸出 (輸出與輸入?X?維度是一樣的,所以可以相加)。
Add指?X+MultiHeadAttention(X),是一種殘差連接,通常用于解決多層網絡訓練的問題,可以讓網絡只關注當前差異的部分,在 ResNet 中經常用到。
殘差連接
Norm指 Layer Normalization,通常用于 RNN 結構,Layer Normalization 會將每一層神經元的輸入都轉成均值方差都一樣的,這樣可以加快收斂。
4.2 Feed Forward
Feed Forward 層比較簡單,是一個兩層的全連接層,第一層的激活函數為 Relu,第二層不使用激活函數,對應的公式如下。
Feed Forward
X是輸入,Feed Forward 最終得到的輸出矩陣的維度與?X?一致。 ? ?
4.3 組成 Encoder
通過上面描述的 Multi-Head Attention, Feed Forward, Add & Norm 就可以構造出一個 Encoder block,Encoder block 接收輸入矩陣?X(n×d),并輸出一個矩陣?O(n×d)。通過多個 Encoder block 疊加就可以組成 Encoder。
第一個 Encoder block 的輸入為句子單詞的表示向量矩陣,后續 Encoder block 的輸入是前一個 Encoder block 的輸出,最后一個 Encoder block 輸出的矩陣就是?編碼信息矩陣 C,這一矩陣后續會用到 Decoder 中。 ? ?
Encoder 編碼句子信息
5. Decoder 結構 ? ?
Transformer Decoder block
上圖紅色部分為 Transformer 的 Decoder block 結構,與 Encoder block 相似,但是存在一些區別:
包含兩個 Multi-Head Attention 層。第一個 Multi-Head Attention 層采用了 Masked 操作。第二個 Multi-Head Attention 層的?K,?V?矩陣使用 Encoder 的編碼信息矩陣?C?進行計算,而?Q?使用上一個 Decoder block 的輸出計算。最后有一個 Softmax 層計算下一個翻譯單詞的概率。5.1 第一個 Multi-Head Attention ? ?
Decoder block 的第一個 Multi-Head Attention 采用了 Masked 操作,因為在翻譯的過程中是順序翻譯的,即翻譯完第 i 個單詞,才可以翻譯第 i+1 個單詞。通過 Masked 操作可以防止第 i 個單詞知道 i+1 個單詞之后的信息。下面以 "我有一只貓" 翻譯成 "I have a cat" 為例,了解一下 Masked 操作。
下面的描述中使用了類似 Teacher Forcing 的概念,不熟悉 Teacher Forcing 的童鞋可以參考以下上一篇文章Seq2Seq 模型詳解。在 Decoder 的時候,是需要根據之前的翻譯,求解當前最有可能的翻譯,如下圖所示。首先根據輸入 "" 預測出第一個單詞為 "I",然后根據輸入 "I" 預測下一個單詞 "have"。
Decoder 預測
Decoder 可以在訓練的過程中使用 Teacher Forcing 并且并行化訓練,即將正確的單詞序列 (I have a cat) 和對應輸出 (I have a cat) 傳遞到 Decoder。那么在預測第 i 個輸出時,就要將第 i+1 之后的單詞掩蓋住,注意 Mask 操作是在 Self-Attention 的 Softmax 之前使用的,下面用 0 1 2 3 4 5 分別表示 "I have a cat"。
第一步:是 Decoder 的輸入矩陣和?Mask?矩陣,輸入矩陣包含 "I have a cat" (0, 1, 2, 3, 4) 五個單詞的表示向量,Mask?是一個 5×5 的矩陣。在?Mask?可以發現單詞 0 只能使用單詞 0 的信息,而單詞 1 可以使用單詞 0, 1 的信息,即只能使用之前的信息。 ? ?
輸入矩陣與 Mask 矩陣
第二步:接下來的操作和之前的 Self-Attention 一樣,通過輸入矩陣?X計算得到?Q,?K,?V?矩陣。然后計算?Q?和?KT 的乘積?QKT。
QKT
第三步:在得到?QKT 之后需要進行 Softmax,計算 attention score,我們在 Softmax 之前需要使用?Mask矩陣遮擋住每一個單詞之后的信息,遮擋操作如下:
Softmax 之前 Mask ? ?
得到?Mask QKT 之后在?Mask QKT 上進行 Softmax,每一行的和都為 1。但是單詞 0 在單詞 1, 2, 3, 4 上的 attention score 都為 0。
第四步:使用?Mask QKT 與矩陣?V相乘,得到輸出?Z,則單詞 1 的輸出向量?Z1 是只包含單詞 1 信息的。
Mask 之后的輸出
第五步:通過上述步驟就可以得到一個 Mask Self-Attention 的輸出矩陣?Zi,然后和 Encoder 類似,通過 Multi-Head Attention 拼接多個輸出?Zi 然后計算得到第一個 Multi-Head Attention 的輸出?Z,Z與輸入?X?維度一樣。
5.2 第二個 Multi-Head Attention
Decoder block 第二個 Multi-Head Attention 變化不大, 主要的區別在于其中 Self-Attention 的?K,?V矩陣不是使用 上一個 Decoder block 的輸出計算的,而是使用?Encoder 的編碼信息矩陣 C?計算的。
根據 Encoder 的輸出?C計算得到?K,?V,根據上一個 Decoder block 的輸出?Z?計算?Q?(如果是第一個 Decoder block 則使用輸入矩陣?X?進行計算),后續的計算方法與之前描述的一致。
這樣做的好處是在 Decoder 的時候,每一位單詞都可以利用到 Encoder 所有單詞的信息 (這些信息無需 Mask)。 ? ?
5.3 Softmax 預測輸出單詞
Decoder block 最后的部分是利用 Softmax 預測下一個單詞,在之前的網絡層我們可以得到一個最終的輸出?Z,因為 Mask 的存在,使得單詞 0 的輸出?Z0 只包含單詞 0 的信息,如下。
Decoder Softmax 之前的 Z
Softmax 根據輸出矩陣的每一行預測下一個單詞
Decoder Softmax 預測
這就是 Decoder block 的定義,與 Encoder 一樣,Decoder 是由多個 Decoder block 組合而成。 ? ?
6. Transformer 總結
Transformer 與 RNN 不同,可以比較好地并行訓練。
Transformer 本身是不能利用單詞的順序信息的,因此需要在輸入中添加位置 Embedding,否則 Transformer 就是一個詞袋模型了。
Transformer 的重點是 Self-Attention 結構,其中用到的?Q,?K,?V矩陣通過輸出進行線性變換得到。
Transformer 中 Multi-Head Attention 中有多個 Self-Attention,可以捕獲單詞之間多種維度上的相關系數 attention score。
參考文獻
論文:Attention Is All You NeedJay Alammar 博客:The Illustrated Transformerpytorch transformer 代碼:The Annotated Transformer
Attention是如何發揮作用的,其中的參數的含義和作用是什么,反向傳播算法如何更新其中參數,又是如何影響其他參數的更新的?
為什么要用scaled attention?
Multi-head attention相比single head attention為什么更加work,其本質上做了一件什么事?從反向傳播算法的角度分析?
Positional encoding是如何發揮作用的,應用反向傳播算法時是如何影響到其他參數的更新的?同樣的理論可以延伸到其他additional embedding,比如多語言模型中的language embedding
每個encoder/decoder layer中feed-forward部分的作用,并且從反向傳播算法角度分析?
decoder中mask后反向傳播算法過程細節,如何保證training和inference的一致性?
如果不一致(decoder不用mask)會怎么樣? ? ?
1. Attention的背景溯源
想要深度理解Attention機制,就需要了解一下它產生的背景、在哪類問題下產生,以及最初是為了解決什么問題而產生。
首先回顧一下機器翻譯領域的模型演進歷史:
機器翻譯是從RNN開始跨入神經網絡機器翻譯時代的,幾個比較重要的階段分別是: Simple RNN, Contextualize RNN,Contextualized RNN with attention, Transformer(2017),下面來一一介紹。
「Simple RNN」?:這個encoder-decoder模型結構中,encoder將整個源端序列(不論長度)壓縮成一個向量(encoder output),源端信息和decoder之間唯一的聯系只是: encoder output會作為decoder的initial states的輸入。這樣帶來一個顯而易見的問題就是,隨著decoder長度的增加,encoder output的信息會衰減。
Simple RNN(without context)
這種模型有2個主要的問題:
源端序列不論長短,都被統一壓縮成一個固定維度的向量,并且顯而易見的是這個向量中包含的信息中,關于源端序列末尾的token的信息更多,而如果序列很長,最終可能基本上“遺忘”了序列開頭的token的信息。 ? ?
第二個問題同樣由RNN的特性造成: 隨著decoder timestep的信息的增加,initial hidden states中包含的encoder output相關信息也會衰減,decoder會逐漸“遺忘”源端序列的信息,而更多地關注目標序列中在該timestep之前的token的信息。
「Contextualized RNN」?:為了解決上述第二個問題,即encoder output隨著decoder timestep增加而信息衰減的問題,有人提出了一種加了context的RNN sequence to sequence模型:decoder在每個timestep的input上都會加上一個context。為了方便理解,我們可以把這看作是encoded source sentence。這樣就可以在decoder的每一步,都把源端的整個句子的信息和target端當前的token一起輸入到RNN中,防止源端的context信息隨著timestep的增長而衰減。
Contextualized RNN
但是這樣依然有一個問題: context對于每個timestep都是靜態的(encoder端的final hiddenstates,或者是所有timestep的output的平均值)。但是每個decoder端的token在解碼時用到的context真的應該是一樣的嗎?在這樣的背景下,Attention就應運而生了:
「Contextualized RNN with soft align (Attention)」?: Attention在機器翻譯領域的應用最早的提出來自于2014年的一篇論文 ?Neural Machine Translation by Jointly Learning to Align and Translate ? ?
Contextualized RNN with Attention
在每個timestep輸入到decoder RNN結構中之前,會用當前的輸入token的vector與encoderoutput中的每一個position的vector作一個"attention"操作,這個"attention"操作的目的就是計算當前token與每個position之間的"相關度",從而決定每個position的vector在最終該timestep的context中占的比重有多少。最終的context即encoderoutput每個位置vector表達的?「加權平均」?。
context的計算公式
2. Attention的細節
2.1. 點積attention
我們來介紹一下attention的具體計算方式。attention可以有很多種計算方式:加性attention、點積attention,還有帶參數的計算方式。著重介紹一下點積attention的公式: ? ?
Attention中(Q^T)*K矩陣計算,query和key的維度要保持一致
如上圖所示, ???, ?分別是query和key,其中,query可以看作M個維度為d的向量(長度為M的sequence的向量表達)拼接而成,key可以看作N個維度為d的向量(長度為N的sequence的向量表達)拼接而成。
【一個小問題】為什么有縮放因子 ????
先一句話回答這個問題: 縮放因子的作用是?「歸一化」?。
假設 ???, ???里的元素的均值為0,方差為1,那么 ???中元素的均值為0,方差為d. 當d變得很大時, ???中的元素的方差也會變得很大,如果 ???中的元素方差很大,那么 ???的分布會趨于陡峭(分布的方差大,分布集中在絕對值大的區域)。總結一下就是 ???的分布會和d有關。因此 ???中每一個元素乘上 ???后,方差又變為1。這使得 ???的分布“陡峭”程度與d解耦,從而使得訓練過程中梯度值保持穩定。
2.2. Attention機制涉及到的參數
一個完整的attention層涉及到的參數有:
把 ???, ???, ???分別映射到 ???, ???, ???的線性變換矩陣 ???( ???), ???( ???), ???( ???) ? ?
把輸出的表達 ???映射為最終輸出 ???的線性變換矩陣 ???( ???)
2.3. Query, Key, Value
Query和Key作用得到的attention權值作用到Value上。因此它們之間的關系是:
Query ???和Key ???的維度必須一致,Value ???和Query/Key的維度可以不一致。
Key ???和Value ???的長度必須一致。Key和Value本質上對應了同一個Sequence在不同空間的表達。
Attention得到的Output ???的維度和Value的維度一致,長度和Query一致。
Output每個位置 i 是由value的所有位置的vector加權平均之后的向量;而其權值是由位置為i 的query和key的所有位置經過attention計算得到的 ,權值的個數等于key/value的長度。
Attention示意圖
在經典的Transformer結構中,我們記線性映射之前的Query, Key, Value為q, k, v,映射之后為Q, K, V。那么:
self-attention的q, k, v都是同一個輸入, 即當前序列由上一層輸出的高維表達。
cross-attention的q代表當前序列,k,v是同一個輸入,對應的是encoder最后一層的輸出結果(對decoder端的每一層來說,保持不變) ? ?
而每一層線性映射參數矩陣都是獨立的,所以經過映射后的Q, K, V各不相同,模型參數優化的目標在于將q, k, v被映射到新的高維空間,使得每層的Q, K,V在不同抽象層面上捕獲到q, k, v之間的關系。一般來說,底層layer捕獲到的更多是lexical-level的關系,而高層layer捕獲到的更多是semantic-level的關系。
2.4. Attention的作用
下面這段我會以機器翻譯為例,用通俗的語言闡釋一下attention的作用,以及query, key, value的含義。
Transformer模型Encoder, Decoder的細節圖(省去了FFN部分)
query對應的是需要?「被表達」?的序列(稱為序列A),key和value對應的是?「用來表達」A的序列(稱為序列B)。其中key和query是在同一高維空間中的(否則無法用來計算相似程度),value不必在同一高維空間中,最終生成的output和value在同一高維空間中。上面這段巨繞的話用一句更繞的話來描述一下就是:
? ? ?
序列A和序列B在高維空間 ???中的高維表達 ?的每個位置 _「分別」?_ 和 ???計算相似度,產生的權重作用于序列B在高維空間??中的高維表達 ???,獲得序列A在高維空間??中的高維表達 ?
?
Encoder部分中只存在self-attention,而Decoder部分中存在self-attention和cross-attention
【self-attention】encoder中的self-attention的query, key,value都對應了源端序列(即A和B是同一序列),decoder中的self-attention的query, key, value都對應了目標端序列。
【cross-attention】decoder中的cross-attention的query對應了目標端序列,key,value對應了源端序列(每一層中的cross-attention用的都是encoder的最終輸出)
2.5. Decoder端的Mask
Transformer模型屬于自回歸模型(p.s.非自回歸的翻譯模型我會專門寫一篇文章來介紹),也就是說后面的token的推斷是基于前面的token的。Decoder端的Mask的功能是為了保證訓練階段和推理階段的一致性。
論文原文中關于這一點的段落如下:
?
We also modify the self-attention sub-layer in the decoder stack to preventfrom attending to subsequent positions. This masking, combined with the factthat the output embeddings are offset by one position, ensures that thepredictions for position i can depend only on the known outputs at positionsless than i.
? ? ?
在推理階段,token是按照從左往右的順序推理的。也就是說,在推理timestep=T的token時,decoder只能“看到”timestep < T的T-1 個Token,不能和timestep大于它自身的token做attention(因為根本還不知道后面的token是什么)。為了保證訓練時和推理時的一致性,所以,訓練時要同樣防止token與它之后的token去做attention。
2.6. 多頭Attention (Multi-head Attention)
Attention是將query和key映射到同一高維空間中去計算相似度,而對應的multi-head attention把query和key映射到高維空間??的不同子空間 ?
中去計算相似度。
為什么要做multi-head attention?論文原文里是這么說的:
?
Multi-head attention allows the model to jointly attend to information fromdifferent representation subspaces at different positions. With a singleattention head, averaging inhibits this.
?
也就是說,這樣可以在不改變參數量的情況下增強每一層attention的表現力。?
? ? ? ? ? ? ? ? ? ? ? ? ??Multi-headAttention示意圖 ? ?
Multi-head Attention的本質是,在?「參數總量保持不變」?的情況下,將同樣的query, key, value映射到原來的高維空間的「不同子空間」中進行attention的計算,在最后一步再合并不同子空間中的attention信息。這樣降低了計算每個head的attention時每個向量的維度,在某種意義上防止了過擬合;由于Attention在不同子空間中有不同的分布,Multi-head Attention實際上是尋找了序列之間不同角度的關聯關系,并在最后concat這一步驟中,將不同子空間中捕獲到的關聯關系再綜合起來。
從上圖可以看出, ???和 ???之間的attentionscore從1個變成了h個,這就對應了h個子空間中它們的關聯度。
3. Transformer模型架構中的其他部分
3.1. Feed Forward Network ? ?
每一層經過attention之后,還會有一個FFN,這個FFN的作用就是空間變換。FFN包含了2層lineartransformation層,中間的激活函數是ReLu。
曾經我在這里有一個百思不得其解的問題:attention層的output最后會和 ?相乘,為什么這里又要增加一個2層的FFN網絡?
其實,FFN的加入引入了非線性(ReLu激活函數),變換了attention output的空間,從而增加了模型的表現能力。把FFN去掉模型也是可以用的,但是效果差了很多。
3.2. Positional Encoding
位置編碼層只在encoder端和decoder端的embedding之后,第一個block之前出現,它非常重要,沒有這部分,Transformer模型就無法用。位置編碼是Transformer框架中特有的組成部分,補充了Attention機制本身不能捕捉位置信息的缺陷。
?positionencoding
PositionalEmbedding的成分直接疊加于Embedding之上,使得每個token的位置信息和它的語義信息(embedding)充分融合,并被傳遞到后續所有經過復雜變換的序列表達中去。
論文中使用的PositionalEncoding(PE)是正余弦函數,位置(pos)越小,波長越長,每一個位置對應的PE都是唯一的。同時作者也提到,之所以選用正余弦函數作為PE,是因為這可以使得模型學習到token之間的相對位置關系:因為對于任意的偏移量k,??可以由 ???的線性表示:
上面兩個公式可以由 ???和 ?
的線性組合得到。也就是 ?乘上某個線性變換矩陣就得到了 ?
p.s. 后續有一個工作在attention中使用了“相對位置表示” ( ?Self-Attention with Relative PositionRepresentations) ,有興趣可以看看。 ? ?
3.3. Layer Normalization
在每個block中,最后出現的是Layer Normalization。LayerNormalization是一個通用的技術,其本質是規范優化空間,加速收斂。
當我們使用梯度下降法做優化時,隨著網絡深度的增加,數據的分布會不斷發生變化,假設feature只有二維,那么用示意圖來表示一下就是:
數據的分布發生變化,左圖比較規范,右圖變得不規范
為了保證數據特征分布的穩定性(如左圖),我們加入Layer Normalization,這樣可以加速模型的優化速度。
機器學習——圖解Transformer(完整版) ? ?
Transformer是一種基于注意力機制的序列模型,最初由Google的研究團隊提出并應用于機器翻譯任務。與傳統的循環神經網絡(RNN)和卷積神經網絡(CNN)不同,Transformer僅使用自注意力機制(self-attention)來處理輸入序列和輸出序列,因此可以并行計算,極大地提高了計算效率。下面是Transformer的詳細解釋。 ? ?
1. 自注意力機制
自注意力機制是Transformer的核心部分,它允許模型在處理序列時,將輸入序列中的每個元素與其他元素進行比較,以便在不同上下文中正確地處理每個元素。 ? ?
自注意力機制中有三個重要的輸入矩陣:查詢矩陣Q(query)、鍵矩陣K(key)和值矩陣V(value)。這三個矩陣都是由輸入序列經過不同的線性變換得到的。然后,查詢矩陣Q與鍵矩陣K的乘積經過一個softmax函數,得到一個與輸入序列長度相同的概率分布,該分布表示每個元素對于查詢矩陣Q的重要性。最后,將這個概率分布乘以值矩陣V得到自注意力向量,表示將每個元素的值加權平均后的結果。 ? ?
2. 多頭注意力機制
為了進一步提高模型的性能,Transformer引入了多頭注意力機制(multi-head attention)。多頭注意力機制通過將自注意力機制應用于多組不同的查詢矩陣Q、鍵矩陣K和值矩陣V,從而學習到不同的上下文表示。具體來說,將輸入序列分別通過不同的線性變換得到多組不同的查詢矩陣Q、鍵矩陣K和值矩陣V,然后將它們輸入到多個并行的自注意力機制中進行處理。
Transformer在自然語言處理中廣泛應用,例如機器翻譯、文本摘要、語言生成等領域。相比于傳統的遞歸神經網絡(RNN)和卷積神經網絡(CNN),Transformer的并行計算能力更強,處理長序列的能力更強,且可以直接對整個序列進行處理。 ? ?
Transformer模型由編碼器(Encoder)和解碼器(Decoder)兩部分組成,下面將詳細介紹每個部分的構成和作用。
1. 編碼器(Encoder)
編碼器將輸入序列(例如一句話)轉化為一系列上下文表示向量(Contextualized Embedding),它由多個相同的層組成。每一層都由兩個子層組成,分別是自注意力層(Self-Attention Layer)和前饋全連接層(Feedforward Layer)。具體地,自注意力層將輸入序列中的每個位置與所有其他位置進行交互,以計算出每個位置的上下文表示向量。前饋全連接層則將每個位置的上下文表示向量映射到另一個向量空間,以捕捉更高級別的特征。 ? ?
2. 解碼器(Decoder)
解碼器將編碼器的輸出和目標序列(例如翻譯后的句子)作為輸入,生成目標序列中每個位置的概率分布。解碼器由多個相同的層組成,每個層由三個子層組成,分別是自注意力層、編碼器-解碼器注意力層(Encoder-Decoder Attention Layer)和前饋全連接層。其中自注意力層和前饋全連接層的作用與編碼器相同,而編碼器-解碼器注意力層則將解碼器當前位置的輸入與編碼器的所有位置進行交互,以獲得與目標序列有關的信息。 ? ?
在Transformer中,自注意力機制是關鍵的組成部分。它可以將輸入序列中的任何兩個位置之間的關系建模,并且可以根據序列的內容自動學習不同位置之間的相互依賴關系。自注意力機制的計算包括三個步驟:計算查詢向量(Query Vector)、鍵向量(Key Vector)和值向量(Value Vector),并將它們組合起來計算注意力分數,最后將注意力分數與值向量相乘得到自注意力向量。 ? ?
總體來說,Transformer通過引入自注意力機制和多頭注意力機制,使得神經網絡能夠更好地捕捉序列中的長程依賴關系,從而在自然語言處理等領域獲得了巨大的成功。
? ?
Mask
mask表示掩碼。即對某些值進行掩蓋,不參與計算,不會對參數更新產生效果。Decoder計算注意力的時候,為了讓decoder不能看到未來的信息,需要把未來的信息隱藏。例如在 time_step 為 t 的時刻,解碼計算attention的時候應該只能依賴于 t 時刻之前的輸出,而不能依賴 t 之后的輸出。因此需要想一個辦法,把 t 之后的信息給隱藏起來。這就是mask的作用。
具體的辦法是在計算attention步驟中,在計算softmax之前,在這些位置加上一個非常打的負數(-INF),這樣,經過softmax這些位置的概率會接近0。
Linear和softmax
Decoder最終輸出的結果是一個浮點型數據的向量,我們要如何把這個向量轉為一個單詞呢?這個就是Linear和softmax要做的事情了。
Linear層是一個全連接的神經網絡,輸出神經元個數一般等于我們的詞匯表大小。Decoder輸出的結果會輸入到Linear層,然后再用softmax進行轉換,得到的是詞匯表大小的向量,向量的每個值對應的是當前Decoder是對應的這個詞的概率,我們只要取概率最大的詞,就是當前詞語Decoder的結果了。 ? ?
transformer模型詳解
一、transformer模型原理
Transformer模型是由谷歌公司提出的一種基于自注意力機制的神經網絡模型,用于處理序列數據。相比于傳統的循環神經網絡模型,Transformer模型具有更好的并行性能和更短的訓練時間,因此在自然語言處理領域中得到了廣泛應用。
在自然語言處理中,序列數據的輸入包括一系列文本、語音信號、圖像或視頻等。傳統的循環神經網絡(RNN)模型已經在這些任務中取得了很好的效果,但是該模型存在著兩個主要問題:一是難以并行計算,二是難以捕捉長距離依賴關系。為了解決這些問題,Transformer模型應運而生。
作為一種基于自注意力機制的神經網絡模型,Transformer模型能夠對序列中的每個元素進行全局建模,并在各個元素之間建立聯系。與循環神經網絡模型相比,Transformer模型具有更好的并行性能和更短的訓練時間。
Transformer模型中包含了多層encoder和decoder,每一層都由多個注意力機制模塊和前饋神經網絡模塊組成。encoder用于將輸入序列編碼成一個高維特征向量表示,decoder則用于將該向量表示解碼成目標序列。在Transformer模型中,還使用了殘差連接和層歸一化等技術來加速模型收斂和提高模型性能。
Transformer模型的核心是自注意力機制(Self-Attention Mechanism),其作用是為每個輸入序列中的每個位置分配一個權重,然后將這些加權的位置向量作為輸出。
自注意力機制的計算過程包括三個步驟:
計算注意力權重:計算每個位置與其他位置之間的注意力權重,即每個位置對其他位置的重要性。 ? ?
計算加權和:將每個位置向量與注意力權重相乘,然后將它們相加,得到加權和向量。
線性變換:對加權和向量進行線性變換,得到最終的輸出向量。
通過不斷堆疊多個自注意力層和前饋神經網絡層,可以構建出Transformer模型。
對于Transformer模型的訓練,通常采用無監督的方式進行預訓練,然后再進行有監督的微調。在預訓練過程中,通常采用自編碼器或者掩碼語言模型等方式進行訓練,目標是學習輸入序列的表示。在微調過程中,通常采用有監督的方式進行訓練,例如在機器翻譯任務中,使用平行語料進行訓練,目標是學習將輸入序列映射到目標序列的映射關系。
二、Transformer模型的優缺點
Transformer模型的優缺點
更好的并行性能:Transformer模型能夠在所有位置同時計算,從而充分利用GPU并行計算的優勢,加速了模型的訓練和推理過程。
能夠處理長序列:傳統的循環神經網絡模型在處理長序列時容易出現梯度消失和梯度爆炸的問題,而Transformer模型使用了自注意力機制,能夠同時考慮所有位置的信息,從而更好地處理長序列。
更好的性能表現:Transformer模型在自然語言處理領域中已經取得了很多重要的研究成果,比如在機器翻譯、文本生成、語言模型等任務中都取得了很好的效果。
Transformer模型的缺點
對于小數據集,Transformer模型的表現可能會不如傳統的循環神經網絡模型,因為它需要更大的數據集來訓練。
Transformer模型的計算復雜度較高,需要更多的計算資源,比如GPU等。
Transformer模型的可解釋性不如傳統的循環神經網絡模型,因為它使用了自注意力機制,難以解釋每個位置的重要性。 ? ?
三、Transformer模型的代碼示例
以下是使用PyTorch實現Transformer模型的代碼示例:
import torch
import torch.nn as nn
import torch.nn.functional as F
class MultiHeadAttention(nn.Module):
def?__init__(self, d_model, n_heads):
super(MultiHeadAttention,?self).__init__()
self.d_model?= d_model
self.n_heads?= n_heads
self.d_k?= d_model // n_heads
self.d_v?= d_model // n_heads
self.W_Q?= nn.Linear(d_model, d_model)
self.W_K?= nn.Linear(d_model, d_model)
self.W_V?= nn.Linear(d_model, d_model)
self.W_O?= nn.Linear(d_model, d_model)
def?forward(self, Q, K, V, mask=None):
Q?= self.W_Q(Q)
K?= self.W_K(K)
V?= self.W_V(V)
Q?= self.split_heads(Q)
K?= self.split_heads(K) ? ?
V?= self.split_heads(V)
scores?= torch.matmul(Q, K.transpose(-1, -2)) / torch.sqrt(torch.tensor(self.d_k, dtype=torch.float32))
if?mask is not None:
scores?= scores.masked_fill(mask == 0, -1e9)
attn_weights?= F.softmax(scores, dim=-1)
attn_output?= torch.matmul(attn_weights, V)
attn_output?= self.combine_heads(attn_output)
attn_output?= self.W_O(attn_output)
return?attn_output
def?split_heads(self, x):
batch_size,?seq_len, d_model = x.size()
x?= x.view(batch_size, seq_len, self.n_heads, self.d_k)
return?x.transpose(1, 2)
def?combine_heads(self, x):
batch_size,?n_heads, seq_len, d_v = x.size()
x?= x.transpose(1, 2).contiguous()
x?= x.view(batch_size, seq_len, n_heads * d_v)
return?x
class PositionalEncoding(nn.Module):
def?__init__(self, d_model, max_len=5000):
super(PositionalEncoding,?self).__init__() ? ?
self.d_model?= d_model
self.dropout?= nn.Dropout(p=0.1)
pe?= torch.zeros(max_len, d_model)
position?= torch.arange(0, max_len, dtype=torch.float32).unsqueeze(1)
div_term?= torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
pe[:,?0::2] = torch.sin(position * div_term)
pe[:,?1::2] = torch.cos(position * div_term)
pe?= pe.unsqueeze(0)
self.register_buffer('pe',?pe)
def?forward(self, x):
x?= x * math.sqrt(self.d_model)
x?= x + self.pe[:, :x.size(1)]
x?= self.dropout(x)
return?x
class FeedForward(nn.Module):
def?__init__(self, d_model, d_ff):
super(FeedForward,?self).__init__()
self.linear1?= nn.Linear(d_model, d_ff)
self.linear2?= nn.Linear(d_ff, d_model)
def?forward(self, x):
x?= self.linear1(x) ? ?
x?= F.relu(x)
x?= self.linear2(x)
return?x
class EncoderLayer(nn.Module):
def?__init__(self, d_model, n_heads, d_ff):
super(EncoderLayer,?self).__init__()
self.multi_head_attn?= MultiHeadAttention(d_model, n_heads)
self.feed_forward?= FeedForward(d_model, d_ff)
self.layer_norm1?= nn.LayerNorm(d_model)
self.layer_norm2?= nn.LayerNorm(d_model)
self.dropout1?= nn.Dropout(p=0.1)
self.dropout2?= nn.Dropout(p=0.1)
def?forward(self, x, mask=None):
attn_output?= self.multi_head_attn(x, x, x, mask=mask)
x?= x + self.dropout1(attn_output)
x?= self.layer_norm1(x)
ff_output?= self.feed_forward(x)
x?= x + self.dropout2(ff_output)
x?= self.layer_norm2(x)
return?x
class Encoder(nn.Module):
def?__init__(self, input_size, d_model, n_heads, d_ff, n_layers): ? ?
super(Encoder,?self).__init__()
self.embedding?= nn.Embedding(input_size, d_model)
self.pos_encoding?= PositionalEncoding(d_model)
self.layers?= nn.ModuleList([EncoderLayer(d_model, n_heads, d_ff) for _ in range(n_layers)])
self.layer_norm?= nn.LayerNorm(d_model)
def?forward(self, x, mask=None):
x?= self.embedding(x)
x?= self.pos_encoding(x)
for?layer in self.layers:
x?= layer(x, mask=mask)
x?= self.layer_norm(x)
return?x
class Transformer(nn.Module):
def?__init__(self, input_size, output_size, d_model, n_heads, d_ff, n_layers):
super(Transformer,?self).__init__()
self.encoder?= Encoder(input_size, d_model, n_heads, d_ff, n_layers)
self.output_layer?= nn.Linear(d_model, output_size)
def?forward(self, x, mask=None):
x?= self.encoder(x, mask)
x?= x[:, 0, :]
x?= self.output_layer(x) ? ?
return?x
這段代碼實現了一個基于Transformer模型的文本分類器。
四、Transformer模型應用領域
Transformer模型是一種基于注意力機制的神經網絡架構,最初被提出用于自然語言處理任務中的序列到序列學習。隨著時間的推移,Transformer模型被應用于各種不同的領域,如下所示:
(一)?自然語言處理
自然語言處理是指將人類語言轉換為計算機可以理解的形式,以便計算機能夠處理和理解語言。Transformer模型在自然語言處理領域有許多應用案例。以下是一些例子:
文本分類:Transformer模型可以對文本進行分類,例如將電子郵件分類為垃圾郵件或非垃圾郵件。在這種情況下,Transformer模型可以將文本作為輸入,然后輸出類別標簽。
機器翻譯:Transformer模型可以將一種語言的文本翻譯成另一種語言的文本。在這種情況下,Transformer模型可以將源語言的文本作為輸入,然后輸出目標語言的文本。
命名實體識別:Transformer模型可以識別文本中的命名實體,例如人名、地名、組織名稱等。在這種情況下,Transformer模型可以將文本作為輸入,然后輸出命名實體的類型和位置。
情感分析:Transformer模型可以對文本進行情感分析,例如判斷一篇文章是積極的還是消極的。在這種情況下,Transformer模型可以將文本作為輸入,然后輸出情感極性。
(二)?語音識別
語音識別是指將人類語音轉換為計算機可以理解的形式,以便計算機能夠處理和理解語音。一些最新的研究表明,基于Transformer的語音識別系統已經取得了與傳統的循環神經網絡(RNN)和卷積神經網絡(CNN)相媲美的性能。下面是一些Transformer模型在語音識別領域的應用案例: ? ?
語音識別:Transformer模型可以對語音信號進行識別,例如將語音轉換為文本。在這種情況下,Transformer模型可以將語音信號作為輸入,然后輸出文本結果。
語音合成:Transformer模型可以將文本轉換為語音信號。在這種情況下,Transformer模型可以將文本作為輸入,然后輸出語音信號。
說話人識別:Transformer模型可以識別不同說話者的語音信號。在這種情況下,Transformer模型可以將語音信號作為輸入,然后輸出說話者的身份。
聲紋識別:Transformer模型可以對聲音信號進行識別,例如將聲音轉換為特征向量。在這種情況下,Transformer模型可以將聲音信號作為輸入,然后輸出特征向量。
這些應用案例只是Transformer模型在語音識別領域中的一部分應用。由于Transformer模型具有處理變長序列數據的能力和更好的性能,因此在語音識別領域中得到了廣泛的應用。
(三) 計算機視覺
計算機視覺是指讓計算機理解和分析圖像和視頻。Transformer模型在計算機視覺領域也有廣泛應用。以下是一些例子:
圖像分類:Transformer模型可以對圖像進行分類,例如將圖像分類為不同的物體或場景。在這種情況下,Transformer模型可以將圖像作為輸入,然后輸出類別標簽。
目標檢測:Transformer模型可以檢測圖像中的物體,并將它們分割出來。在這種情況下,Transformer模型可以將圖像作為輸入,然后輸出物體的位置和大小。
圖像生成:Transformer模型可以生成新的圖像,例如生成一張藝術作品或者修改一張圖像。在這種情況下,Transformer模型可以將圖像作為輸入,然后輸出新的圖像。
這些應用案例只是Transformer模型在計算機視覺領域中的一部分應用。由于Transformer模型具有處理變長序列數據的能力和更好的性能,因此在計算機視覺領域中得到了廣泛的應用。 ? ?
(四) 強化學習
Transformer模型在強化學習領域的應用主要是應用于策略學習和值函數近似。強化學習是指讓機器在與環境互動的過程中,通過試錯來學習最優的行為策略。在強化學習中,模型需要通過學習狀態轉移概率,來預測下一個狀態和獎勵,從而實現增強學習。
1、Transformer模型可以通過多頭注意力機制來處理多個輸入序列,并將它們融合成一個輸出序列。在強化學習中,Transformer模型可以將當前狀態作為輸入,然后輸出一個行動策略。具體而言,Transformer模型可以學習到狀態轉移概率函數,使得在當前狀態下,選擇行動后可以獲得最大的獎勵。
2、Transformer模型還可以用于值函數近似。值函數是指在給定狀態下,執行一個特定行動所能獲得的期望獎勵。在強化學習中,值函數通常是通過蒙特卡羅方法來估計的。而Transformer模型可以通過學習值函數來近似這些值,從而提高強化學習的效率和精度。
3、Transformer模型已經被廣泛應用于自然語言處理、語音識別、計算機視覺和強化學習等領域,并且在這些領域中都取得了顯著的成果。它的廣泛應用前景表明,Transformer模型在未來的人工智能領域中將扮演著越來越重要的角色。
總體來說,Transformer模型是一種高效、靈活、易于實現的神經網絡模型,其在自然語言處理領域中發揮著越來越重要的作用。隨著深度學習技術的不斷發展,Transformer模型必將在未來的自然語言處理領域中發揮越來越重要的作用。
系統版本:macos 12.2.1
軟件版本:PaddlePaddle2.3.0
硬件型號:MacBook Pro
審核編輯:黃飛
?
評論
查看更多