基于 transformer 的編碼器-解碼器模型是 表征學習 和 模型架構 這兩個領域多年研究成果的結晶。本文簡要介紹了神經編碼器-解碼器模型的歷史,更多背景知識,建議讀者閱讀由 Sebastion Ruder 撰寫的這篇精彩 博文。此外,建議讀者對 自注意力 (self-attention) 架構 有一個基本了解,可以閱讀 Jay Alammar 的 這篇博文 復習一下原始 transformer 模型。
本文分 4 個部分:
背景 - 簡要回顧了神經編碼器-解碼器模型的歷史,重點關注基于 RNN 的模型。
編碼器-解碼器 - 闡述基于 transformer 的編碼器-解碼器模型,并闡述如何使用該模型進行推理。
編碼器 - 闡述模型的編碼器部分。
解碼器 - 闡述模型的解碼器部分。
每個部分都建立在前一部分的基礎上,但也可以單獨閱讀。這篇分享是第二部分 編碼器-解碼器。如果你還沒有看過 第一部分 背景,可以先讀一讀。
編碼器-解碼器
2017 年,Vaswani 等人引入了 transformer 架構,從而催生了 基于 transformer 的編碼器-解碼器模型。
與基于 RNN 的編碼器-解碼器模型類似,基于 transformer 的編碼器-解碼器模型由一個編碼器和一個解碼器組成,且其編碼器和解碼器均由 殘差注意力模塊 (residual attention blocks) 堆疊而成?;?transformer 的編碼器-解碼器模型的關鍵創新在于: 殘差注意力模塊無需使用循環結構即可處理長度 可變的輸入序列 。不依賴循環結構使得基于 transformer 的編碼器-解碼器可以高度并行化,這使得模型在現代硬件上的計算效率比基于 RNN 的編碼器-解碼器模型高出幾個數量級。
回憶一下,要解決 序列到序列 問題,我們需要找到輸入序列 到變長輸出序列 的映射。我們看看如何使用基于 transformer 的編碼器-解碼器模型來找到這樣的映射。
與基于 RNN 的編碼器-解碼器模型類似,基于 transformer 的編碼器-解碼器模型定義了在給定輸入序列 條件下目標序列 的條件分布:
基于 transformer 的編碼器部分將輸入序列 編碼為 隱含狀態序列 ,即:
然后,基于 transformer 的解碼器負責建模在給定隱含狀態序列 的條件下目標向量序列 的概率分布:
根據貝葉斯法則,該序列分布可被分解為每個目標向量 在給定隱含狀態 和其所有前驅目標向量 時的條件概率之積:
因此,在生成 時,基于 transformer 的解碼器將隱含狀態序列 及其所有前驅目標向量 映射到 logit 向量 。然后經由 softmax 運算對 logit 向量 進行處理,從而生成條件分布 。這個流程跟基于 RNN 的解碼器是一樣的。然而,與基于 RNN 的解碼器不同的是,在這里,目標向量 的分布是 顯式 (或直接) 地以其所有前驅目標向量 為條件的,稍后我們將詳細介紹。此處第 0 個目標向量 仍表示為 向量。有了條件分布 ,我們就可以??自回歸?生成輸出了。至此,我們定義了可用于推理的從輸入序列 到輸出序列 的映射。
我們可視化一下使用 基于 transformer 的編碼器-解碼器模型 _自回歸_地生成序列的完整過程。
上圖中,綠色為基于 transformer 的編碼器,紅色為基于 transformer 的解碼器。與上一節一樣,我們展示了如何將表示為的英語句子 “I want to buy a car” 翻譯成表示為的德語句子 “Ich will ein Auto kaufen”。
首先,編碼器將完整的輸入序列 = “I want to buy a car” (由淺綠色向量表示) 處理為上下文相關的編碼序列 。這里上下文相關的意思是, 舉個例子 , 的編碼不僅取決于輸入 = “buy”,還與所有其他詞 “I”、“want”、“to”、“a”、“car” 及 “EOS” 相關,這些詞即該詞的 上下文 。
接下來,輸入編碼 與 BOS 向量 ( 即 ) 被一起饋送到解碼器。解碼器將輸入 和 ? 變換為第一個 logit (圖中以深紅色顯示),從而得到第一個目標向量 的條件分布:
然后,從該分布中采樣出第一個目標向量 = (由灰色箭頭表示),得到第一個輸出后,我們會并將其繼續饋送到解碼器?,F在,解碼器開始以 = “BOS” 和 ? = “Ich” 為條件來定義第二個目標向量的條件分布 :
再采樣一次,生成目標向量 = “will”。重復該自回歸過程,直到第 6 步從條件分布中采樣到 EOS:
這里有一點比較重要,我們僅在第一次前向傳播時用編碼器將 映射到 。從第二次前向傳播開始,解碼器可以直接使用之前算得的編碼 。為清楚起見,下圖畫出了上例中第一次和第二次前向傳播所需要做的操作。
可以看出,僅在步驟 時,我們才需要將 “I want to buy a car EOS” 編碼為 。從 開始,解碼器只是簡單地復用了已生成的編碼。
在 transformers 庫中,這一自回歸生成過程是在調用 .generate() 方法時在后臺完成的。我們用一個翻譯模型來實際體驗一下。
from?transformers?import?MarianMTModel,?MarianTokenizer tokenizer?=?MarianTokenizer.from_pretrained("Helsinki-NLP/opus-mt-en-de") model?=?MarianMTModel.from_pretrained("Helsinki-NLP/opus-mt-en-de") #?create?ids?of?encoded?input?vectors input_ids?=?tokenizer("I?want?to?buy?a?car",?return_tensors="pt").input_ids #?translate?example output_ids?=?model.generate(input_ids)[0] #?decode?and?print print(tokenizer.decode(output_ids))
輸出:
? ?
.generate() 接口做了很多事情。首先,它將 input_ids 傳遞給編碼器。然后,它將一個預定義的標記連同已編碼的 input_ids 一起傳遞給解碼器 (在使用 MarianMTModel 的情況下,該預定義標記為 )。接著,它使用波束搜索解碼機制根據最新的解碼器輸出的概率分布 自回歸地采樣下一個輸出詞。更多有關波束搜索解碼工作原理的詳細信息,建議閱讀 這篇博文。
我們在附錄中加入了一個代碼片段,展示了如何“從頭開始”實現一個簡單的生成方法。如果你想要完全了解 自回歸 生成的幕后工作原理,強烈建議閱讀附錄。
總結一下:
基于 transformer 的編碼器實現了從輸入序列 到上下文相關的編碼序列 之間的映射。
基于 transformer 的解碼器定義了條件分布 。
給定適當的解碼機制,可以自回歸地從中采樣出輸出序列 。
太好了,現在我們已經大致了解了 基于 transformer 的 編碼器-解碼器模型的工作原理。下面的部分,我們將更深入地研究模型的編碼器和解碼器部分。更具體地說,我們將確切地看到編碼器如何利用自注意力層來產生一系列上下文相關的向量編碼,以及自注意力層如何實現高效并行化。然后,我們將詳細解釋自注意力層在解碼器模型中的工作原理,以及解碼器如何通過 交叉注意力 層以編碼器輸出為條件來定義分布 。在此過程中,基于 transformer 的編碼器-解碼器模型如何解決基于 RNN 的編碼器-解碼器模型的長程依賴問題的答案將變得顯而易見。
可以從 此處 獲取 "Helsinki-NLP/opus-mt-en-de" 的解碼參數??梢钥吹?,其使用了 num_beams=6 的波束搜索。
敬請關注其余部分的文章。
編輯:黃飛
?
評論
查看更多