transformaer原理
文章目錄
- transformaer原理
- 1. Transformer的興起
- 2. 圖解Attention
- 2.1 seq2seq
- 2.2 回圈神經網路的不足:
- 2.3 attention的引出(重點內容)
- 2.4 從機器翻譯推廣到attention的一般模式
- 2.5 Attention模型的改進形式
- 2.6 Self-Attention
- 2.6.1 Self-Attention結構
- 2.6.2 Self-Attention在機器翻譯中的優勢
- 2.6.3 Self Attention和回圈神經網路對比
- 2.6.4計算 Self Attention :
- 2.6.5使用矩陣計算 Self-Attention
- 3.多頭注意力機制(multi-head attention)
- 3.1 從attention引出multi-head attention
- 3.2 從Attention到Multi-Head Attention的公式變換:
- 3.3 多頭注意力模型的可視化表示
- 3.4 代碼實作矩陣計算 Attention
- 3.4.1 定義MultiheadAttention
- 3.4.2 forward的輸入(引出mask機制)
- 3.4.3 forward的輸出
- 3.5 手動實作attention
- 4. 圖解transformer
- 4.1 自注意力模型的缺點及transformer的提出
- 4.2 transformer的改進
- 4.2.1 融入位置資訊
- 4.2.2 輸入向量角色資訊
- 4.2.3多層自注意力(多層編碼解碼結構)
- 4.2.4多頭自注意力( Multi - head Self - attention )
- 4.3 Encoder
- 4.3.1 Encoder層結構
- 4.3.2殘差連接和標準化
- 4.3.3 Transformer-encoder結構梳理——數學表示.
- 4.4 Decoder(解碼器)
- 4.5 最后的線性層和 Softmax 層
- 4.6 Transformer 的輸入
- 5. Transformer 的訓練程序
- 5.1 損失函式
- 5.2 貪婪解碼和集束搜索
說明:
??本文主要來自datawhale的開源教程 《基于transformers的自然語言處理(NLP)入門》,此專案也發布在 github,部分內容(章節2.1-2.5,3.1-3.2,4.1-4.2)來自北大博士后盧菁老師的《速通機器學習》一書,這只是我的一個讀書筆記,進行一般性總結,所以有些地方進行了簡寫(比如代碼部分,不要噴我,有誤請反饋),想要了解更詳細內容可以參考datawhale教程(有更多的圖片描述、部分動圖和詳細的代碼)和《速通》一書,
?? 另外篇幅有限(可也能是水平有限),關于多頭注意力的encoder-decoder attention模塊進行運算的更詳細內容可以參考 《Transformer概覽總結》,從attention到transformer的API實作和自編程代碼實作,可以查閱 《Task02 學習Attention和Transformer》(這篇文章排版很好,干凈簡潔,看著非常舒服,非常推薦)
1. Transformer的興起
?? 2017年,《Attention Is All You Need》論文首次提出了Transformer模型結構并在機器翻譯任務上取得了The State of the Art(SOTA, 最好)的效果,2018年,《BERT: Pre-training of Deep Bidirectional Transformers for Language Understanding》使用Transformer模型結構進行大規模語言模型(language model)預訓練(Pre-train),再在多個NLP下游(downstream)任務中進行微調(Finetune),一舉重繪了各大NLP任務的榜單最高分,轟動一時,2019年-2021年,研究人員將Transformer這種模型結構和預訓練+微調這種訓練方式相結合,提出了一系列Transformer模型結構、訓練方式的改進(比如transformer-xl,XLnet,Roberta等等),如下圖所示,各類Transformer的改進不斷涌現,

??圖片來自復旦大學邱錫鵬教授:NLP預訓練模型綜述《A Survey of Transformers》,中文翻譯可以參考:https://blog.csdn.net/Raina_qing/article/details/106374584
https://blog.csdn.net/weixin_42691585/article/details/105950385
??另外,由于Transformer優異的模型結構,使得其引數量可以非常龐大從而容納更多的資訊,因此Transformer模型的能力隨著預訓練不斷提升,隨著近幾年計算能力的提升,越來越大的預訓練模型以及效果越來越好的Transformers不斷涌現,
??本教程也將基于HuggingFace/Transformers, 48.9k Star進行具體編程和解決方案實作,
??NLP中的預訓練+微調的訓練方式推薦閱讀知乎的兩篇文章 《2021年如何科學的“微調”預訓練模型?》 和《從Word Embedding到Bert模型—自然語言處理中的預訓練技術發展史》,
2. 圖解Attention
2.1 seq2seq
??seq2seq模型是由編碼器(Encoder)和解碼器(Decoder)組成的,其中,編碼器會處理輸入序列中的每個元素,把這些資訊轉換為一個向量(稱為背景關系context),當我們處理完整個輸入序列后,編碼器把背景關系(context)發送給解碼器,解碼器開始逐項生成輸出序列中的元素,背景關系向量的長度,基于編碼器 RNN 的隱藏層神經元的數量
??如何把每個單詞都轉化為一個向量呢?我們使用一類稱為 “word embedding” 的方法,這類方法把單詞轉換到一個向量空間,這種表示能夠捕捉大量單詞之間的語意資訊,(word2vec)通常embedding 向量大小是 200 或者 300,
??在機器翻譯任務中,背景關系(context)是一個向量(基本上是一個數字陣列),編碼器和解碼器在Transformer出現之前一般采用的是回圈神經網路,背景關系context向量是這類模型的瓶頸,以兩個具有不同引數的LSTM分別作為encoder和decoder處理機器翻譯為例,結構如下:

??LSTM1為編碼器,在最后時刻的背景關系資訊 C 包含中文“我愛你”的完整資訊,傳給給解碼器LSTM2,作為翻譯階段,LSTM2的起始狀態start,之后每時刻的預測結果作為下一時刻的輸入,翻譯順序進行直到終止符停止翻譯,
2.2 回圈神經網路的不足:
回圈神經網路的處理此類任務存在一些不足:
?? 1.機器翻譯中,使用LSTM的encoder只輸出最后時刻的背景關系資訊C,而這兩個模型都存在長距離衰減問題,使得C的描述能力有限,當編碼句子較長時,句子靠前部分對C的影響會降低;
?? 2.解碼階段,隨著序列的推移,編碼資訊C對翻譯的影響越來越弱,因此,越靠后的內容,翻譯效果越差,(其實也是因為長距離衰減問題)
?? 3.解碼階段缺乏對編碼階段各個詞的直接利用,簡單說就是:機器翻譯領域,解碼階段的詞和編碼階段的詞有很強的映射關系,比如“愛”和“love”,但是seq2seq模型無法再譯“love”時直接使用“愛”這個詞的資訊,因為在編碼階段只能使用全域資訊C,(attention在這點做得很好)
??在 2014——2015年提出并改進了一種叫做注意力attetion的技術,它極大地提高了機器翻譯的質量,注意力使得模型可以根據需要,關注到輸入序列的相關部分,
2.3 attention的引出(重點內容)
基于上面第3點,需要對模型進行改造,(圖不是很好,將就看看)

??編碼階段和前面的模型沒有區別,保留了各時刻LSTM1的輸出向量v,解碼階段,模型預測的方法有了變化,比如在t=1時刻,預測方式為:
?? 1.計算LSTM2在t=1時刻的輸出q1,以及v1、v2、v3的相似度,即對q1和v1、v2、v3求內積:
s1=<q1,v1>
s2=<q1,v2>
s3=<q1,v3>
?? 2.s1、s2、s3可以理解為未歸一化的相似度,通過softmax函式對其歸一化,得到a1、a2、a3,滿足a1+a2+a3=1,a1、a2、a3就是相似度得分attention score,用于表示解碼階段t=1時刻和編碼階段各個詞之間的關系,
?? 例如解碼器在第一個時刻,翻譯的詞是“I”,它和編碼階段的“我”這個詞關系最近,
a
我
a_我
a我?的分數最高(比如0.95),由此達到讓輸出對輸入進行聚焦的能力,找到此時刻解碼時最該注意的詞,這就是注意力機制,比起回圈神經網路有更好的效果,
?? (attention score只表示注意力強度,是一個標量,一個系數,不是向量,不含有背景關系資訊,所以還不是最終輸出結果,在此回答一些小伙伴的疑問)
?? 3.根據相似度得分對v1、v2、v3進行加權求和,即
h
1
=
a
1
v
1
+
a
2
v
2
+
a
3
v
3
h_{1}=a_{1}v_{1}+a_{2}v_{2}+a_{3}v_{3}
h1?=a1?v1?+a2?v2?+a3?v3?,
?? 4.向量h1經過softmax函式來預測單詞“I”,可以看出,此時的h1由最受關注的向量
v
我
v_我
v我?主導,因為
a
我
a_我
a我?最高,
??上述模型就是注意力(Attention)模型)(這里沒有用Self-Attention代替LSTM,主要還是講attention機制是基于什么原因引出的,好的建議可以反饋給我),(此處的模型沒有key向量,是做了簡化,即向量 K = V K=V K=V)
??注意力模型和人類翻譯的行為更為相似,人類進行翻譯時,會先通讀“我愛你”這句話,從而獲得整體語意(LSTM1的輸出C),而在翻譯階段,除了考慮整體語意,還會考慮各個輸入詞(“我”、“愛”、“你”)和當前待翻譯詞之間的映射關系(權重a1、a2、a3來聚焦注意力)
??一個注意力模型不同于經典的(seq2seq)模型,主要體現在 2 個方面:
??1.編碼器會把更多的資料傳遞給解碼器,編碼器把所有時間步的 hidden state(隱藏層狀態)傳遞給解碼器,而非只傳遞最后一個 hidden state,
??2.解碼器在產生輸出之前,做了一個額外的處理,把注意力集中在與該時間步相關的輸入部分:
a. 查看所有接收到的編碼器的 hidden state(隱藏層狀態),其中,編碼器中每個 hidden state(隱藏層狀態)都對應到輸入句子中一個單詞,
b. 給每個 hidden state(隱藏層狀態)一個分數(attention score),
c. 將每個 hidden state(隱藏層狀態)乘以經過 softmax 的對應的分數,分數的高低代表了注意力的強度,分數更大的hidden state更會被關注,
Tips:上面計算相似度s=<q,k>時,s要除以
(
d
k
e
y
)
\sqrt(d_{key})
(
?dkey?)(Key 向量的長度),原因是:
??求相似度時,如果特征維度過高(如詞向量embedding維度),就會導致計算出來的相似度s過大,s值的過大會導致歸一化函式softmax飽和(softmax在s值很大的區域輸出幾乎不變化)使得歸一化后計算出來的結果a要么趨近于1要么趨近于0,即加權求和退化成勝者全拿,則解碼時只關注注意力最高的(attention模型還是希望別的詞也有權重)而且softmax函式的飽和區導數趨近于0,梯度消失,所以對公式s=<q,k>進行優化:
s
=
<
q
,
k
>
d
k
e
y
s=\frac{<q,k>}{\sqrt{d_{key}}}
s=dkey?
?<q,k>?
??q和k求內積,所以其實key和q的向量長度一樣,
2.4 從機器翻譯推廣到attention的一般模式
(本來不想寫的,想到一個問題,還是把這節補了)
??Attention不止是用來做機器翻譯,甚至是不止用在NLP領域,換一個更一般點的例子,來說明Attention的一般模式,
??比如有一個場景是家長帶小孩取玩具店買玩具,用模型預測最后玩具是否會被購買,每個玩具有兩類特征,1-形狀顏色功能等,用來吸引孩子;第二類特征是加個、安全、益智性等,用來決定家長是否購買,
??假設孩子喜好用特征向量q表示,玩具第一類特征用向量k表示,第二類特征用向量v表示,模型結果如下:

??首先計算q和k的相似度
s
1
?
s
n
s_{1}-s_{n}
s1??sn?,并歸一化到
a
1
?
a
n
a_{1}-a_{n}
a1??an?,a反映了孩子對玩具的喜好程度(權重),接下來a對特征v進行加權求和(家長角度考慮),得到向量h,最后家長是否購買玩具是由向量h決定的,
??上述程序就是Attention的標準操作流程,Attention模型三要素是
q
、
K
、
V
q、K、 V
q、K、V,
K
、
V
K、 V
K、V矩陣分別對應向量序列
k
1
k_1
k1?到
k
n
k_n
kn?和
v
1
v_1
v1?到
v
n
v_n
vn?,由于中間涉及到加權求和,所以這兩個序列長度一致,而且元素都是對應的,即
k
j
k_j
kj?對應
v
j
v_j
vj?,但是k和v分別表示兩類特征,所以向量長度可以不一致,
??為了運算方便,可以將Attention操作計算為:
h
=
A
t
t
e
n
t
i
o
n
(
q
、
K
、
V
)
h=Attention(q、K、 V)
h=Attention(q、K、V),q也可以是一個向量序列Q(對應機器翻譯中輸入多個單詞),此時輸出也是一個向量序列H,Attention通用標準公式為:
H
=
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
=
[
A
t
t
e
n
t
i
o
n
(
q
1
,
K
,
V
)
.
.
.
A
t
t
e
n
t
i
o
n
(
q
m
,
K
,
V
)
]
H=Attention(Q,K,V)=\begin{bmatrix} Attention(q_{1},K,V)\\ ...\\ Attention(q_{m},K,V)\end{bmatrix}
H=Attention(Q,K,V)=???Attention(q1?,K,V)...Attention(qm?,K,V)????
??這里,
Q
、
K
、
V
、
H
Q、K、 V、H
Q、K、V、H均為矩陣(向量序列),其中,
H
H
H和
Q
Q
Q序列長度一致,各行一一對應(一個輸入對應一個輸出),
K
K
K和
V
V
V序列長度一致,各行一一對應,
2.5 Attention模型的改進形式
Attention模型計算相似度,除了直接求內積<q,k>,還有很多其它形式,
s
=
A
T
T
a
n
h
(
q
W
+
k
U
)
s=A^{T}Tanh(qW+kU)
s=ATTanh(qW+kU)
??多層感知機,
A
、
W
、
U
A 、 W 、 U
A、W、U都是待學習引數,這種方法不僅避開了求內積時 q 和 k 的向量長度必須一致的限制,還可以進行不同空間的向量匹配,例如,在進行圖文匹配時, q 和 k 分別來自文字空間和影像空間,可以先分別通過
W
、
U
W 、 U
W、U將它們轉換至同一空間,再求相似度,
??上面式子中,
W
、
U
W 、U
W、U是矩陣引數,相乘后可以使q和k的維度一致,比如機器翻譯中,中文一詞多義情況比較多,中文向量q維度可以設定長一點,英文中一詞多義少,k的維度可以設定短一點,
q
W
+
k
U
qW+kU
qW+kU是同長度向量相加,結果還是一個向量,再經過列向量
A
T
A^{T}
AT相乘,得到一個標量,即attention score數值,
??第二個改進式子:
s
=
<
q
W
k
T
>
d
k
e
y
s=\frac{<qWk^{T}>}{\sqrt{d_{key}}}
s=dkey?
?<qWkT>?
 ?其中,W是待學習引數,q和k維度可以不同,
??第三個改進式子:
s
=
<
q
W
,
k
U
>
d
k
e
y
s=\frac{<qW,kU>}{\sqrt{d_{key}}}
s=dkey?
?<qW,kU>?
2.6 Self-Attention
2.6.1 Self-Attention結構
??
H
=
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
H=Attention(Q,K,V)
H=Attention(Q,K,V)有一種特殊情況,就是
Q
=
K
=
V
Q=K=V
Q=K=V,也就是自注意力模型self-attention,(一個輸入向量同時承擔了三種角色)

??如上圖所示,self-attention中query、key、value的這三樣東西其實是一樣的,它們的形狀都是:(L,N,E)
L:輸入序列的長度(例如一個句子的長度)
N:batch size(例如一個批的句子個數)
E:詞向量長度
??Self-Attention只有一個序列(即只有一種輸入特征),比如機器翻譯中,輸入只有詞向量,這應該就是Self-Attention和Attention的區別,
2.6.2 Self-Attention在機器翻譯中的優勢
The animal didn't cross the street because it was too tired
??這個句子中的 it 是一個指代詞,那么 it 指的是什么呢?它是指 animal 還是street?這個問題對人來說,是很簡單的,但是對演算法來說并不是那么容易,當模型在處理(翻譯)it 的時候,Self Attention機制能夠讓模型把it和animal關聯起來,
?? Transformer 使用Self Attention機制,會把其他單詞的理解融入處理當前的單詞,即當模型處理句子中的每個詞時,Self Attention機制使得模型不僅能夠關注這個位置的詞,而且能夠關注句子中其他位置的詞,作為輔助線索,進而可以更好地編碼當前位置的詞,

??如上圖可視化圖所示,當我們在第五層編碼器中(編碼部分中的最后一層編碼器)編碼“it”時,有一部分注意力集中在“The animal”上,并且把這兩個詞的資訊融合到了"it"這個單詞中,
2.6.3 Self Attention和回圈神經網路對比
??Self Attention是一個詞袋模型,對詞序不敏感,因為每時刻輸出
h
i
=
a
1
v
1
+
a
2
v
2
+
a
3
v
3
.
.
.
=
∑
a
i
,
j
v
i
h_{i}=a_{1}v_{1}+a_{2}v_{2}+a_{3}v_{3}...=\sum a_{i,j}v_{i}
hi?=a1?v1?+a2?v2?+a3?v3?...=∑ai,j?vi?,這是一個加權求和,調換詞序對結果不影響,所以對比回圈神經網路可以發現:
??1.LSTM、RNN、ELMo等回圈神經網路模型考慮了詞序,但是正因為如此,每個時刻的輸出依賴上一時刻的輸入,所以只能串行計算,無法并行,無利用更龐大的算力來加快模型訓練,這也是回圈神經網路漸漸被attention替代的原因之一,Self Attention模型不考慮詞序,所有字是全部同時訓練的, 各時刻可以獨立計算,可以并行,反而成了它的優點,
??2.回圈神經網路的存在長距離衰減問題,也沒有注意力機制(前面講過,不再重復)attention可以無視詞的距離,因為每時刻都是加權求和,考慮了每一個詞,不存在資訊衰減,
??LSTM:非詞袋模型,含有順序資訊,無法解決長距離依賴,無法并行,沒有注意力機制
??Self Attention:詞袋模型,不含位置資訊,沒有長距離依賴,可以并行,有注意力機制,
但是這里有個問題,語意和詞序是有一定的關聯的,為了解決這個問題,有兩個辦法:
??1.位置嵌入(Position Embeddings)
??2.位置編碼(Position Encodings)
??在transformer部分會進一步介紹
2.6.4計算 Self Attention :
??第 1 步:將輸入詞向量,映射為三個新的向量:Query 向量,Key 向量,Value 向量,這 3 個向量是詞向量分別和 3 個矩陣相乘得到的,而這個矩陣是我們要學習的引數(這應該是改進版的Self Attention)
??第 2 步:計算 Attention Score(注意力分數),有幾種計算方式,常用的是求點積,注意力分數決定了我們在編碼時,需要對句子中其他位置的每個詞放置多少的注意力,
??第 3 步:把每個分數除以
(
d
k
e
y
)
\sqrt(d_{key})
(
?dkey?)(Key 向量的長度,也可以是其它數),再進行softmax歸一化,得到系數a;
??第 4步:a和向量V加權求和得z,這種做法背后的直覺理解就是:對于分數高的位置,相乘后的值就越大,我們把更多的注意力放到了它們身上
??第 5 步是把上一步得到的向量相加,就得到了 Self Attention 層在這個位置的輸出,
??輸出向量會輸入到前饋神經網路,在實際的代碼實作中,Self Attention 的計算程序是使用矩陣來實作的,這樣可以加速計算,一次就得到所有位置的輸出向量,
2.6.5使用矩陣計算 Self-Attention
?? 1.把所有詞向量放到一個矩陣 X 中(輸入),然后分別和3 個權重矩陣
W
Q
W^Q
WQ,
W
K
W^K
WK
W
V
W^V
WV相乘,得到 Q,K,V 矩陣, X 中的每一行,表示句子中的每個詞的詞向量,長度是 512,Q,K,V 矩陣中的每一行表示 Query 向量,Key 向量,Value 向量,向量長度是 64,
?? 2.由于我們使用了矩陣來計算,我們可以把上面的第 2 步到第 5 步壓縮為一步,直接得到 Self Attention 的輸出,

3.多頭注意力機制(multi-head attention)
3.1 從attention引出multi-head attention
?? 在標準的 Attention 模型 Attention ( Q,K , V )中,對 Q 和 K 進行相似度匹配,相當于在特定的角度上計算相似度, Q 和 K 所在的向量空間即為觀察角度,并且有且僅有一個觀察角度,然而,實際情況要復雜得多,
?? 例如,“小明養了一只貓,它特別調皮可愛,他非常喜歡它”,將這句話作為Self - Attention 的輸入序列,其中每個詞都和其他詞有一個對應的相似度得分,“貓”從指代的角度看,與“它”的匹配度最高,但從屬性的角度看,與“調皮”“可愛”的匹配度最高,由于標準的 Attention 模型無法處理這種多語意的情況,所以,需要將向量序列 Q 、 K 、 V 多次轉換至不同的語意空間,對標準的 Attention 模型進行多語意匹配改進,(Self - Attention是Attention的特例,所以此種改進方法也適用)
3.2 從Attention到Multi-Head Attention的公式變換:
??1.用矩陣系數
W
1
Q
、
W
1
K
、
W
1
V
W_{1}^{Q}、W_{1}^{K}、W_{1}^{V}
W1Q?、W1K?、W1V?將Q,K , V 轉至語意空間1,公式為:
Q
1
=
Q
W
1
Q
=
[
q
1
W
1
Q
.
.
.
q
m
W
1
Q
]
Q_{1}=QW_{1}^{Q}=\begin{bmatrix} q_{1}W_{1}^{Q}\\ ...\\ q_{m}W_{1}^{Q}\end{bmatrix}
Q1?=QW1Q?=???q1?W1Q?...qm?W1Q?????
K
1
=
K
W
1
K
=
[
q
1
W
1
K
.
.
.
q
m
W
1
K
]
K_{1}=KW_{1}^{K}=\begin{bmatrix} q_{1}W_{1}^{K}\\ ...\\ q_{m}W_{1}^{K}\end{bmatrix}
K1?=KW1K?=???q1?W1K?...qm?W1K?????
V
1
=
V
W
1
V
=
[
q
1
W
1
V
.
.
.
q
m
W
1
V
]
V_{1}=VW_{1}^{V}=\begin{bmatrix} q_{1}W_{1}^{V}\\ ...\\ q_{m}W_{1}^{V}\end{bmatrix}
V1?=VW1V?=???q1?W1V?...qm?W1V?????
??Q,K , V都是向量序列,因此特征變換就是各時序上的向量變換,
W
1
Q
、
W
1
K
、
W
1
V
W_{1}^{Q}、W_{1}^{K}、W_{1}^{V}
W1Q?、W1K?、W1V?是待學習引數,
??2.在轉換后的語意空間進行attention計算,即
h
e
a
d
1
=
A
t
t
e
n
t
i
o
n
(
Q
1
,
K
1
,
V
1
)
head_1= Attention(Q_1,K_1 , V_1)
head1?=Attention(Q1?,K1?,V1?),
h
e
a
d
1
head_1
head1?也是向量序列,長度和Q一致(一個輸入對應一個輸出),
??3.用矩陣系數
W
2
Q
、
W
2
K
、
W
2
V
W_{2}^{Q}、W_{2}^{K}、W_{2}^{V}
W2Q?、W2K?、W2V?將Q 、 K 、 V 轉換至語意空間2,同樣進行Attention計算,得到
h
e
a
d
2
head_2
head2?,同理計算出
h
e
a
d
3
.
.
.
.
h
e
a
d
c
head_3....head_c
head3?....headc?,
??4.
h
e
a
d
c
head_c
headc?是多個不同語意空間注意力計算的結果,將它們串聯起來,
h
e
a
d
1
.
.
.
.
h
e
a
d
c
head_1....head_c
head1?....headc?均為向量序列,串聯之后還是向量序列,
總結起來,多頭注意力模型公式可以寫成:
M
u
l
t
i
?
H
e
a
d
(
Q
,
K
,
V
)
=
c
o
n
c
a
t
(
h
e
a
d
1
.
.
.
.
h
e
a
d
c
)
W
O
=
[
c
o
n
c
a
t
(
h
1
,
1
.
.
.
h
n
,
1
)
W
O
.
.
.
c
o
n
c
a
t
(
h
1
,
m
.
.
.
h
n
,
m
W
O
]
Multi-Head(Q ,K , V )=concat(head_1....head_c)W^{O}=\begin{bmatrix} concat(h_{1,1}...h_{n,1})W^{O}\\ ...\\ concat(h_{1,m}...h_{n,m}W^{O}\end{bmatrix}
Multi?Head(Q,K,V)=concat(head1?....headc?)WO=???concat(h1,1?...hn,1?)WO...concat(h1,m?...hn,m?WO????
??多頭注意力結果串聯在一起維度可能比較高,所以通過
W
O
W^{O}
WO進行一次線性變換,實作降維和各頭資訊融合的目的,得到最終結果,
??多頭注意力模型中,head數是一個超引數,語料大,電腦性能好就可以設定的高一點,寧可冗余也不遺漏,
??多頭注意力從如下兩個方面增強了 attention 層的能力:
?? 1.它擴展了模型關注不同位置的能力,例如當我們翻譯句子:The animal didn’t cross the street because it was too tired時,我們想讓機器知道其中的it指代的是什么,這時,多頭注意力機制會有幫助,
?? 2.多頭注意力機制賦予 attention 層多個“子表示空間”,可以表示不同角度下的語意資訊,
??在前面的講解中,我們的 K、Q、V 矩陣的序列長度都是一樣的,但是在實際中,K、V 矩陣的序列長度是一樣的(加權求和),而 Q 矩陣的序列長度可以不一樣,
??這種情況發生在:在解碼器部分的Encoder-Decoder Attention層中,Q 矩陣是來自解碼器下層,而 K、V 矩陣則是來自編碼器的輸出,
3.3 多頭注意力模型的可視化表示
?? 下面我們會看到,多頭注意力機制會有多組
W
Q
W^Q
WQ,
W
K
W^K
WK
W
V
W^V
WV的權重矩陣(在 Transformer 的論文中,使用了 8 組注意力(attention heads),因此,接下來我也是用 8 組注意力頭 (attention heads)),多抽頭的每一組注意力的 的權重矩陣都是隨機初始化的,都是不一樣的,經過訓練之后,每一組注意力
W
Q
W^Q
WQ,
W
K
W^K
WK
W
V
W^V
WV 可以看作是把輸入的向量映射到一個”子表示空間“,

?? 將輸入 X 和每組注意力的
W
Q
W^Q
WQ,
W
K
W^K
WK
W
V
W^V
WV相乘,得到 8 組 Q, K, V 矩陣,接著,我們把每組 K, Q, V 進行計算,得到每組的 Z 矩陣,一共就得到 8 個 Z 矩陣,(就是上一節的h,這個圖寫的是Z)
??把8個矩陣拼接起來,然后和另一個權重矩陣
W
O
W^O
WO相乘,(前饋神經網路層接收的也是 1 個矩陣,而不是8個,其中每行的向量表示一個詞)
??總結一下:把 8 個矩陣
Z
0
,
Z
1
.
.
.
Z
7
Z_{0},Z_{1}...Z_{7}
Z0?,Z1?...Z7?拼接起來,拼接后的矩陣和
W
O
W^O
WO 權重矩陣相乘,得到最終的矩陣 Z,這個矩陣包含了所有 attention heads(注意力頭) 的資訊,這個矩陣會輸入到 FFNN (Feed orward Neural Network)層,
??這就是多頭注意力的全部內容,下面我把所有的內容都放到一張圖中,這樣你可以總攬全域,在這張圖中看到所有的內容,

3.4 代碼實作矩陣計算 Attention
??下面我們是用代碼來演示,如何使用矩陣計算 attention,首先使用 PyTorch 庫提供的函式實作,然后自己再實作,
??PyTorch 提供了 MultiheadAttention 來實作 attention 的計算,(其實應該理解為多頭自注意力模型)
3.4.1 定義MultiheadAttention
torch.nn.MultiheadAttention(embed_dim, num_heads, dropout=0.0, bias=True, add_bias_kv=False, add_zero_attn=False, kdim=None, vdim=None)
??1.embed_dim最終輸出的 K、Q、V 矩陣的維度,這個維度需要和詞向量的維度一樣
??2.num_heads:設定多頭注意力的數量,要求embed_dim%num_heads==0,即要能被embed_dim整除,這是為了把詞的隱向量長度平分到每一組,這樣多組注意力也能夠放到一個矩陣里,從而并行計算多頭注意力,
??3.dropout:這個 dropout 加在 attention score 后面
??例如,我們前面說到,8 組注意力可以得到 8 組 Z 矩陣,然后把這些矩陣拼接起來,得到最終的輸出,
??如果最終輸出的每個詞的向量維度是 512,那么每組注意力的向量維度應該是512/8=64 如果不能夠整除,那么這些向量的長度就無法平均分配,
3.4.2 forward的輸入(引出mask機制)
??定義 MultiheadAttention 的物件后,呼叫forward時傳入的引數如下,
forward(query, key, value, key_padding_mask=None, need_weights=True, attn_mask=None)
??1.query:對應于 Query矩陣,形狀是 (L,N,E) ,其中 L 是輸出序列長度,N 是 batch size,E 是詞向量的維度
??2.key:對應于 Key 矩陣,形狀是 (S,N,E) ,其中 S 是輸入序列長度,N 是 batch size,E 是詞向量的維度
??3.value:對應于 Value 矩陣,形狀是 (S,N,E) ,其中 S 是輸入序列長度,N 是 batch size,E 是詞向量的維度
下面重點介紹.key_padding_mask和attn_mask:
??4.key_padding_mask:
??在
s
e
l
f
a
t
t
e
n
t
i
o
n
self \ attention
self attention的計算程序中, 我們通常使用
m
i
n
i
b
a
t
c
h
mini \ batch
mini batch來計算, 也就是一次計算多句話, , 而一個
m
i
n
i
b
a
t
c
h
mini \ batch
mini batch是由多個不等長的句子組成的, 我們就需要按照這個
m
i
n
i
b
a
t
c
h
mini \ batch
mini batch中最大的句長對剩余的句子進行補齊長度, 我們一般用
0
0
0來進行填充, 這個程序叫做
p
a
d
d
i
n
g
padding
padding.
??但這時在進行
s
o
f
t
m
a
x
softmax
softmax的時候就會產生問題, 回顧
s
o
f
t
m
a
x
softmax
softmax函式
σ
(
z
)
i
=
e
z
i
∑
j
=
1
K
e
z
j
\sigma (\mathbf {z} )_{i}={\frac {e^{z_{i}}}{\sum _{j=1}^{K}e^{z_{j}}}}
σ(z)i?=∑j=1K?ezj?ezi??
??
e
0
e^0
e0=1, 這樣的話
s
o
f
t
m
a
x
softmax
softmax中被
p
a
d
d
i
n
g
padding
padding的部分就參與了運算, 就等于是讓無效的部分參與了運算, 會產生很大隱患, 這時就需要做一個
m
a
s
k
mask
mask讓這些無效區域不參與運算, 我們一般給無效區域加一個很大的負數的偏置, 也就是:
z
i
l
l
e
g
a
l
=
z
i
l
l
e
g
a
l
+
b
i
a
s
i
l
l
e
g
a
l
z_{illegal} = z_{illegal} + bias_{illegal}
zillegal?=zillegal?+biasillegal?
b
i
a
s
i
l
l
e
g
a
l
→
?
∞
bias_{illegal} \to -\infty
biasillegal?→?∞
e
z
i
l
l
e
g
a
l
→
0
e^{z_{illegal}} \to 0
ezillegal?→0
??經過上式的
m
a
s
k
i
n
g
masking
masking我們使無效區域經過
s
o
f
t
m
a
x
softmax
softmax計算之后還幾乎為
0
0
0, 這樣就避免了無效區域參與計算.,
key_padding_mask = ByteTensor,非 0 元素對應的位置會被忽略
key_padding_mask =BoolTensor, True 對應的位置會被忽略
(如果 key_padding_mask對應是0、1張量,那么1表示mask,如果是布爾張量,則true表示mask)
??key_padding_mask形狀是 (N,S),其中 N 是 batch size,S 是輸入序列長度,里面的值是1或0,我們先取得key中有padding的位置,然后把mask里相應位置的數字設定為1,這樣attention就會把key相應的部分變為"-inf". (為什么變為-inf參考https://blog.csdn.net/weixin_41811314/article/details/106804906)
??5.attn_mask:表示不計算未來時序的資訊,以機器翻譯為例,Decoder的Self-Attention層只允許關注到輸出序列中早于當前位置之前的單詞,在Self-Attention分數經過Softmax層之前,屏蔽當前位置之后的位置,
??attn_mask形狀可以是 2D (L,S),或者 3D (N?numheads,L,S),其中 L 是輸出序列長度,S 是輸入序列長度,N 是 batch size,
attn_mask =ByteTensor,非 0 元素對應的位置會被忽略(不計算attention,不看這個詞)
attn_mask =BoolTensor, True 對應的位置會被忽略
??mask機制更具體內容可以參考Transformer相關——(7)Mask機制
3.4.3 forward的輸出
??解碼(decoding )階段的每一個時間步都輸出一個翻譯后的單詞(以英語翻譯為例),
#實體化一個nn.MultiheadAttention
multihead_attn = nn.MultiheadAttention(embed_dim, num_heads)
attn_output, attn_output_weights = multihead_attn(query, key, value)
即輸出是:
??attn_output:即最終輸出的的注意力Z,形狀是為(L,N,E), L 是輸出序列長度,N 是 batch size,E 是詞向量的維度
??attn_output_weights:注意力系數a,形狀是 (N,L,S)
代碼示例如下:
# nn.MultiheadAttention 輸入第0維為length
# batch_size 為 64,有 12 個詞,每個詞的 Query 向量是 300 維
query = torch.rand(12,64,300)
# batch_size 為 64,有 10 個詞,每個詞的 Key 向量是 300 維
key = torch.rand(10,64,300)
# batch_size 為 64,有 10 個詞,每個詞的 Value 向量是 300 維
value= torch.rand(10,64,300)
embed_dim = 299
num_heads = 1
# 輸出是 (attn_output, attn_output_weights)
multihead_attn = nn.MultiheadAttention(embed_dim, num_heads)
attn_output = multihead_attn(query, key, value)[0]
# output: torch.Size([12, 64, 300])
# batch_size 為 64,有 12 個詞,每個詞的向量是 300 維
print(attn_output.shape)
3.5 手動實作attention
def forward(self, query, key, value, mask=None):
bsz = query.shape[0]
Q = self.w_q(query)
K = self.w_k(key)
V = self.w_v(value)
1.#計算attention score
attention = torch.matmul(Q, K.permute(0, 1, 3, 2)) / self.scale
if mask isnotNone:
attention = attention.masked_fill(mask == 0, -1e10)# mask 不為空,那么就把 mask 為 0 的位置的 attention 分數設定為 -1e10
2.#計算上一步結果的最后一維做 softmax,再經過 dropout,得attention,
attention = self.do(torch.softmax(attention, dim=-1))
3.attention結果與V相乘,得到多頭注意力的結果
# [64,6,12,10] * [64,6,10,50] = [64,6,12,50]
x = torch.matmul(attention, V)
4.轉置x并拼接多頭結果
x = x.permute(0, 2, 1, 3).contiguous()#轉置
x = x.view(bsz, -1, self.n_heads * (self.hid_dim // self.n_heads))#拼接
x = self.fc(x)
return x
# batch_size 為 64,有 12 個詞,每個詞的 Query 向量是 300 維
query = torch.rand(64, 12, 300)
# batch_size 為 64,有 12 個詞,每個詞的 Key 向量是 300 維
key = torch.rand(64, 10, 300)
# batch_size 為 64,有 10 個詞,每個詞的 Value 向量是 300 維
value = torch.rand(64, 10, 300)
attention = MultiheadAttention(hid_dim=300, n_heads=6, dropout=0.1)
output = attention(query, key, value)
## output: torch.Size([64, 12, 300])
print(output.shape)
4. 圖解transformer
4.1 自注意力模型的缺點及transformer的提出
??雖然自注意力模型有很多優勢,但是,要想真正取代回圈神經網路,自注意力模型還需要解決如下問題:.
1.在計算自注意力時,沒有考慮輸入的位置資訊,因此無法對序列進行建模;.
2.輸入向量 T ,同時承擔了Q、K、V三種角色,導致其不容易學習;
3.只考慮了兩個輸人序列單元之間的關系,無法建模多個輸人序列單元之間更復雜的關系;
4.自注意力計算結果互斥,無法同時關注多個輸人
??2017 年,Google 提出了 Transformer 模型,綜合解決了以上問題,Transformer也使用了用 Encoder-Decoder框架,為了提高模型能力,每個編碼解碼塊不再是由RNN網路組成,而是由Self Attention+FFNN 的結構組成(前饋神經網路), 從本質上講,transformer是將序列轉換為序列,所以叫這個名字,可以翻譯為轉換器,也有人叫變壓器,
??概括起來就是transformer使用了位置嵌入
(
p
o
s
i
t
i
o
n
a
l
e
n
c
o
d
i
n
g
)
(positional \ encoding)
(positional encoding)來理解語言的順序, 使用自注意力機制和全連接層來進行計算,

?? Transformer 可以拆分為 2 部分:左邊是編碼部分(encoding component),右邊是解碼部分(decoding component),
4.2 transformer的改進
4.2.1 融入位置資訊
??為了解決Self-Attention詞袋模型問題,除了詞向量,還應該給輸入向量引入不同的位置資訊,有兩種引人位置資訊的方式:
??1.位置嵌入( Position Embeddings ):與詞嵌入類似,即為序列中每個絕對位置賦予一個連續、低維、稠密的向量表示,
??2.位置編碼( Position Encodings ):使用函式
f
:
N
→
R
d
f:\mathbb{N}\rightarrow \mathbb{R}^{d}
f:N→Rd ,直接將一個整數(位置索引值)映射到一個 d 維向量上,映射公式為:
P
o
s
E
n
c
(
p
,
i
)
=
{
s
i
n
(
p
1000
0
i
d
)
c
o
s
(
p
1000
0
i
?
1
d
)
}
PosEnc(p,i)= \begin{Bmatrix} sin(\frac{p}{10000^{\frac{i}{d}}})\\ cos(\frac{p}{10000^{\frac{i-1}{d}}})\end{Bmatrix}
PosEnc(p,i)={sin(10000di?p?)cos(10000di?1?p?)?}
??其中,p為序列中位置索引值,
0
?
i
<
d
0\leqslant i< d
0?i<d是位置編碼向量中的索引值,
4.2.2 輸入向量角色資訊
??原始的自注意力模型在計算注意力時,直接使用兩個輸入向量計算注意力系數a,然后使用得到的注意力對同一個輸入向量加權,這樣導致一個輸入向量同時承擔了三種角色:査詢( Query )鍵( Key )和值( Value ),(見上面2.6節)
??更好的做法是,對不同的角色使用不同的向量,即使用不同的引數矩陣對原始的輸人向量做線性變換,從而讓不同的變換結果承擔不同的角色,具體地,分別使用三個不同的引數矩陣
W
Q
W^Q
WQ,
W
K
W^K
WK,
W
V
W^V
WV,將輸入向量
x
i
x_{i}
xi?映射為三個新的向量
q
i
q_{i}
qi?、
k
i
k_{i}
ki?、
v
i
v_{i}
vi?,分別表示查詢、鍵和值對應的向量,
4.2.3多層自注意力(多層編碼解碼結構)
??原始的自注意力模型僅考慮了序列中任意兩個輸人序列單元之間的關系,而在實際應用中,往往需要同時考慮更多輸入序列單元之間的關系,即更高階的關系,如果直接建模高階關系,會導致模型的復雜度過高,而類似于圖模型中的訊息傳播機制( Message Propogation ),這種高階關系可以通過堆疊多層自注意力模型實作,
??另一方面,直接堆疊多層注意力模型,由于每層的變換都是線性的(注意力計算一般使用線性函式,只是簡單的加權求和),最終模型依然是線性的,因此,為了增強模型的表示能力,往往在每層自注意力計算之后,增加一個非線性的前饋神經網路FFNN,如果將自注意力模型看作特征抽取器,那么FFNN就是最終的分類器,
??同時,為了使模型更容易學習,還可以使用層歸一化( Layer Normalization )殘差連接( Residual Connections )等深度學習的訓練技巧,這些都加在一起,叫Transformer塊(Block)
4.2.4多頭自注意力( Multi - head Self - attention )
??由于自注意力結果需要經過歸一化,導致即使一個輸人和多個其他的輸人相關,也無法同時為這些輸入賦予較大的注意力值,即自注意力結果之間是互斥的,無法同時關注多個輸人,
??因此,如果能使用多組自注意力模型產生多組不同的注意力結果,則不同組注意力模型可能關注到不同的輸人上,從而增強模型的表達能力,具體來說,只需要設定多組映射矩陣即可,然后將產生的多個輸出向量拼接,為了將輸出結果作為下一組的輸人,還需要將拼接后的輸出向量再經過一個線性映射,映射回 d 維向量,該模型又叫作多頭自注意力( Multi - head Self - attention )模型,
??從另一方面理解、多頭自注意力機制相當于多個不同的自注意力模型的集成( Ensemble ),也會增強模型的效果,類似卷積神經網路中的多個卷積核,也可以將不同的注意力頭理解為抽取不同型別的特征,
4.3 Encoder
4.3.1 Encoder層結構
??Encoder由多層編碼器組成,每層編碼器在結構上都是一樣的,但不同層編碼器的權重引數是不同的,每層編碼器里面,主要由以下兩部分組成:
1.Self-Attention Layer
2.Feed Forward Neural Network(前饋神經網路,縮寫為 FFNN)
??輸入編碼器的文本資料,首先會經過一個 Self Attention 層,這個層處理一個詞的時候,不僅會使用這個詞本身的資訊,也會使用句子中其他詞的資訊(你可以類比為:當我們翻譯一個詞的時候,不僅會只關注當前的詞,也會關注這個詞的背景關系的其他詞的資訊),
??接下來,Self Attention 層的輸出會經過前饋神經網路FFNN,
??Self-Attention模型的作用是提取語意級別的資訊(不存在長距離依賴),而FFNN是在各個時序上對特征進行非線性變換,提高網路表達能力,
4.3.2殘差連接和標準化
??編碼器的每個子層(Self Attention 層和FFNN)都有一個Add&normalization層,如下如所示:

?? Add&normalization的意思是LayerNorm(X+Z),即殘差連接和標準化,
?? Add殘差連接是 用到Shortcut 技術,解決深層網路訓練時退化問題,具體解釋可以看文章《Transformer相關——(5)殘差模塊》
?? LayerNorm 用于提高網路的訓練速度,防止過擬合,具體可以參考《Transformer相關——(6)Normalization方式》
(再寫下去感覺這篇文章繃不住了,太長抓不住主線)
4.3.3 Transformer-encoder結構梳理——數學表示.
?? 經過前面部分的講解,我們已經知道了很多知識點,下面用公式把一個
t
r
a
n
s
f
o
r
m
e
r
b
l
o
c
k
transformer \ block
transformer block的計算程序整理一下:
1). 字向量與位置編碼:
X
=
E
m
b
e
d
d
i
n
g
L
o
o
k
u
p
(
X
)
+
P
o
s
i
t
i
o
n
a
l
E
n
c
o
d
i
n
g
(eq.2)
X = EmbeddingLookup(X) + PositionalEncoding \tag{eq.2}
X=EmbeddingLookup(X)+PositionalEncoding(eq.2)
X
∈
R
b
a
t
c
h
s
i
z
e
?
s
e
q
.
l
e
n
.
?
e
m
b
e
d
.
d
i
m
.
X \in \mathbb{R}^{batch \ size \ * \ seq. \ len. \ * \ embed. \ dim.}
X∈Rbatch size ? seq. len. ? embed. dim.2). 自注意力機制:
Q
=
L
i
n
e
a
r
(
X
)
=
X
W
Q
Q = Linear(X) = XW_{Q}
Q=Linear(X)=XWQ?
K
=
L
i
n
e
a
r
(
X
)
=
X
W
K
(eq.3)
K = Linear(X) = XW_{K} \tag{eq.3}
K=Linear(X)=XWK?(eq.3)
V
=
L
i
n
e
a
r
(
X
)
=
X
W
V
V = Linear(X) = XW_{V}
V=Linear(X)=XWV?
X
a
t
t
e
n
t
i
o
n
=
S
e
l
f
A
t
t
e
n
t
i
o
n
(
Q
,
K
,
V
)
(eq.4)
X_{attention} = SelfAttention(Q, \ K, \ V) \tag{eq.4}
Xattention?=SelfAttention(Q, K, V)(eq.4)3). 殘差連接與
L
a
y
e
r
N
o
r
m
a
l
i
z
a
t
i
o
n
Layer \ Normalization
Layer Normalization
X
a
t
t
e
n
t
i
o
n
=
X
+
X
a
t
t
e
n
t
i
o
n
(eq. 5)
X_{attention} = X + X_{attention} \tag{eq. 5}
Xattention?=X+Xattention?(eq. 5)
X
a
t
t
e
n
t
i
o
n
=
L
a
y
e
r
N
o
r
m
(
X
a
t
t
e
n
t
i
o
n
)
(eq. 6)
X_{attention} = LayerNorm(X_{attention}) \tag{eq. 6}
Xattention?=LayerNorm(Xattention?)(eq. 6)4). 下面進行
t
r
a
n
s
f
o
r
m
e
r
b
l
o
c
k
transformer \ block
transformer block結構圖中的第4部分, 也就是
F
e
e
d
F
o
r
w
a
r
d
FeedForward
FeedForward, 其實就是兩層線性映射并用激活函式激活, 比如說
R
e
L
U
ReLU
ReLU:
X
h
i
d
d
e
n
=
A
c
t
i
v
a
t
e
(
L
i
n
e
a
r
(
L
i
n
e
a
r
(
X
a
t
t
e
n
t
i
o
n
)
)
)
(eq. 7)
X_{hidden} = Activate(Linear(Linear(X_{attention}))) \tag{eq. 7}
Xhidden?=Activate(Linear(Linear(Xattention?)))(eq. 7)5). 重復3).:
X
h
i
d
d
e
n
=
X
a
t
t
e
n
t
i
o
n
+
X
h
i
d
d
e
n
X_{hidden} = X_{attention} + X_{hidden}
Xhidden?=Xattention?+Xhidden?
X
h
i
d
d
e
n
=
L
a
y
e
r
N
o
r
m
(
X
h
i
d
d
e
n
)
X_{hidden} = LayerNorm(X_{hidden})
Xhidden?=LayerNorm(Xhidden?)
X
h
i
d
d
e
n
∈
R
b
a
t
c
h
s
i
z
e
?
s
e
q
.
l
e
n
.
?
e
m
b
e
d
.
d
i
m
.
X_{hidden} \in \mathbb{R}^{batch \ size \ * \ seq. \ len. \ * \ embed. \ dim.}
Xhidden?∈Rbatch size ? seq. len. ? embed. dim.
4.4 Decoder(解碼器)
??同理,解碼器也具有這兩層,但是這兩層中間還插入了一個 Encoder-Decoder Attention 層,編碼器輸出最終向量,將會輸入到每個解碼器的Encoder-Decoder Attention層,用來幫解碼器把注意力集中中輸入序列的合適位置,(類似于 seq2seq 模型 中的 Attention),
??在解碼器的子層里面也有層標準化(layer-normalization),假設一個 Transformer 是由 2 層編碼器和兩層解碼器組成的,如下圖所示,

??在完成了編碼(encoding)階段之后,我們開始解碼(decoding)階段,解碼(decoding )階段的每一個時間步都輸出一個翻譯后的單詞(這里的例子是英語翻譯),接下來會重復這個程序,直到輸出一個結束符,Transformer 就完成了所有的輸出,Decoder 就像 Encoder 那樣,從下往上一層一層地輸出結果,每一步的輸出都會輸入到下面的第一個解碼器,和編碼器的輸入一樣,我們把解碼器的輸入向量,也加上位置編碼向量,來指示每個詞的位置,
??解碼器中的 Self Attention 層,和編碼器中的 Self Attention 層不太一樣:在解碼器里,Self Attention 層只允許關注到輸出序列中早于當前位置之前的單詞,具體做法是:在 Self Attention 分數經過 Softmax 層之前,屏蔽當前位置之后的那些位置,
??Encoder-Decoder Attention層的原理和多頭注意力(multiheaded Self Attention)機制類似,不同之處是:Encoder-Decoder Attention層是使用前一層的輸出來構造 Query 矩陣,而 Key 矩陣和 Value 矩陣來自于解碼器最終的輸出,
4.5 最后的線性層和 Softmax 層
??Decoder 最終的輸出是一個向量,其中每個元素是浮點數,輸出向量經過Softmax 層后面的線性層(普通的全連接神經網路)映射為一個更長的向量,這個向量稱為 logits 向量,
??現在假設我們的模型有 10000 個英語單詞(模型的輸出詞匯表),這些單詞是從訓練集中學到的,因此logits 向量有 10000 個數字,每個數表示一個單詞的得分,經過Softmax 層歸一化后轉換為概率,概率值最大的詞,就是這個時間步的輸出單詞,

??Transformer 是深度學習的集大成之作,融合了多項實用技術,不僅在自然語言處理領域的許多問題中得到了應用,在計算機視覺、推薦系統等領域也得到了廣泛應用,
??但是Transformer也有一個缺點,就是引數量過大,三個角色映射矩陣、多頭注意力機制,FFNN,以及多個block的堆疊,導致一個實用的Transformer含有巨大的引數量,模型變得不容易訓練,尤其是資料集小的時候,基于這種情況,BERT應運而生,
4.6 Transformer 的輸入
??和通常的 NLP 任務一樣,我們首先會使用詞嵌入演算法(embedding algorithm),將每個詞轉換為一個詞向量,實際中向量一般是 256 或者 512 維,整個輸入的句子是一個向量串列,其中有 n個詞向量,
??在實際中,每個句子的長度不一樣,我們會取一個適當的值,作為向量串列的長度,如果一個句子達不到這個長度,那么就填充全為 0 的詞向量;如果句子超出這個長度,則做截斷,句子長度是一個超引數,通常是訓練集中的句子的最大長度,
??編碼器中,每個位置的詞都經過 Self Attention 層,得到的每個輸出向量都單獨經過前饋神經網路層,每個向量經過的前饋神經網路都是一樣的,第一 個層 編碼器的輸入是詞向量,而后面的編碼器的輸入是上一個編碼器的輸出,
5. Transformer 的訓練程序
??假設輸出詞匯只包含 6 個單詞(“a”, “am”, “i”, “thanks”, “student”, and “”(“”表示句子末尾)),我們模型的輸出詞匯表,是在訓練之前的資料預處理階段構造的,當我們確定了輸出詞匯表,我們可以用向量來表示詞匯表中的每個單詞,這個表示方法也稱為 one-hot encoding
5.1 損失函式
??用一個簡單的例子來說明訓練程序,比如:把“merci”翻譯為“thanks”,這意味著我們希望模型最終輸出的概率分布,會指向單詞 ”thanks“(在“thanks”這個詞的概率最高),但模型還沒訓練好,它輸出的概率分布可能和我們希望的概率分布相差甚遠,
??由于模型的引數都是隨機初始化的,模型在每個詞輸出的概率都是隨機的,我們可以把這個概率和正確的輸出概率做對比,然后使用反向傳播來調整模型的權重,使得輸出的概率分布更加接近正確輸出,比較概率分布的差異可以用交叉熵,
??在實際中,我們使用的句子不只有一個單詞,例如–輸入是:“je suis étudiant” ,輸出是:“i am a student”,這意味著,我們的模型需要輸出多個概率分布,滿足如下條件:
??每個概率分布都是一個向量,長度是 vocab_size(我們的例子中,向量長度是 6,但實際中更可能是 30000 或者 50000)
第一個概率分布中,最高概率對應的單詞是 “i”
第二個概率分布中,最高概率對應的單詞是 “am”
以此類推,直到第 5 個概率分布中,最高概率對應的單詞是 “”,表示沒有下一個單詞了,
5.2 貪婪解碼和集束搜索
??貪婪解碼(greedy decoding):模型每個時間步只產生一個輸出,可以認為:模型是從概率分布中選擇概率最大的詞,并丟棄其他詞,
??集束搜索(beam search):每個時間步保留兩個最高概率的輸出詞,然后在下一個時間步,重復執行這個程序:假設第一個位置概率最高的兩個輸出的詞是”I“和”a“,這兩個詞都保留,然后根據第一個詞計算第二個位置的詞的概率分布,再取出 2 個概率最高的詞,對于第二個位置和第三個位置,我們也重復這個程序,
??在我們的例子中,beam_size 的值是 2(含義是:在所有時間步,我們保留兩個最高概率),top_beams 的值也是 2(表示我們最侄訓回傳兩個翻譯的結果),beam_size 和 top_beams 都是你可以在實驗中嘗試的超引數,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/294850.html
標籤:AI
