小白看得懂的 Transformer (圖解)(2)
第一步是計算查詢矩陣、鍵矩陣和值矩陣。為此,我們將將輸入句子的詞嵌入裝進矩陣X中,將其乘以我們訓練的權重矩陣(WQ,WK,WV)。
x矩陣中的每一行對應于輸入句子中的一個單詞。我們再次看到詞嵌入向量 (512,或圖中的4個格子)和q/k/v向量(64,或圖中的3個格子)的大小差異。
最后,由于我們處理的是矩陣,我們可以將步驟2到步驟6合并為一個公式來計算自注意力層的輸出。自注意力的矩陣運算形式
“大戰多頭怪”
通過增加一種叫做“多頭”注意力(“multi-headed” attention)的機制,論文進一步完善了自注意力層,并在兩方面提高了注意力層的性能:
1.它擴展了模型專注于不同位置的能力。在上面的例子中,雖然每個編碼都在z1中有或多或少的體現,但是它可能被實際的單詞本身所支配。如果我們翻譯一個句子,比如“The animal didn’t cross the street because it was too tired”,我們會想知道“it”指的是哪個詞,這時模型的“多頭”注意機制會起到作用。
2.它給出了注意力層的多個“表示子空間”(representation subspaces)。接下來我們將看到,對于“多頭”注意機制,我們有多個查詢/鍵/值權重矩陣集(Transformer使用八個注意力頭,因此我們對于每個編碼器/****有八個矩陣集合)。這些集合中的每一個都是隨機初始化的,在訓練之后,每個集合都被用來將輸入詞嵌入(或來自較低編碼器/****的向量)投影到不同的表示子空間中。
在“多頭”注意機制下,我們為每個頭保持獨立的查詢/鍵/值權重矩陣,從而產生不同的查詢/鍵/值矩陣。和之前一樣,我們拿X乘以WQ/WK/WV矩陣來產生查詢/鍵/值矩陣。
如果我們做與上述相同的自注意力計算,只需八次不同的權重矩陣運算,我們就會得到八個不同的Z矩陣。
這給我們帶來了一點挑戰。前饋層不需要8個矩陣,它只需要一個矩陣(由每一個單詞的表示向量組成)。所以我們需要一種方法把這八個矩陣壓縮成一個矩陣。那該怎么做?其實可以直接把這些矩陣拼接在一起,然后用一個附加的權重矩陣WO與它們相乘。
這幾乎就是多頭自注意力的全部。這確實有好多矩陣,我們試著把它們集中在一個圖片中,這樣可以一眼看清。
既然我們已經摸到了注意力機制的這么多“頭”,那么讓我們重溫之前的例子,看看我們在例句中編碼“it”一詞時,不同的注意力“頭”集中在哪里:
當我們編碼“it”一詞時,一個注意力頭集中在“animal”上,而另一個則集中在“tired”上,從某種意義上說,模型對“it”一詞的表達在某種程度上是“animal”和“tired”的代表。
然而,如果我們把所有的attention都加到圖示里,事情就更難解釋了:
使用位置編碼表示序列的順序
到目前為止,我們對模型的描述缺少了一種理解輸入單詞順序的方法。
為了解決這個問題,Transformer為每個輸入的詞嵌入添加了一個向量。這些向量遵循模型學習到的特定模式,這有助于確定每個單詞的位置,或序列中不同單詞之間的距離。這里的直覺是,將位置向量添加到詞嵌入中使得它們在接下來的運算中,能夠更好地表達的詞與詞之間的距離。
為了讓模型理解單詞的順序,我們添加了位置編碼向量,這些向量的值遵循特定的模式。
如果我們假設詞嵌入的維數為4,則實際的位置編碼如下:
尺寸為4的迷你詞嵌入位置編碼實例
這個模式會是什么樣子?
在下圖中,每一行對應一個詞向量的位置編碼,所以第一行對應著輸入序列的第一個詞。每行包含512個值,每個值介于1和-1之間。我們已經對它們進行了顏色編碼,所以圖案是可見的。
20字(行)的位置編碼實例,詞嵌入大小為512(列)。你可以看到它從中間分裂成兩半。這是因為左半部分的值由一個函數(使用正弦)生成,而右半部分由另一個函數(使用余弦)生成。然后將它們拼在一起而得到每一個位置編碼向量。
原始論文里描述了位置編碼的公式(第3.5節)。你可以在 get_timing_signal_1d()中看到生成位置編碼的代碼。這不是唯一可能的位置編碼方法。然而,它的優點是能夠擴展到未知的序列長度(例如,當我們訓練出的模型需要翻譯遠比訓練集里的句子更長的句子時)。
*博客內容為網友個人發布,僅代表博主個人觀點,如有侵權請聯系工作人員刪除。