在⾃然語⾔處理的不少應⽤中,輸⼊和輸出均可以是不定⻓序列。以機器翻譯爲例,輸⼊能夠是⼀段不定⻓的英語⽂本序列,輸出能夠是⼀段不定⻓的法語⽂本序列,例如:git
英語輸⼊:「They」、「are」、「watching」、「.」github
法語輸出:「Ils」、「regardent」、「.」面試
當輸⼊和輸出都是不定⻓序列時,咱們可使⽤編碼器—解碼器(encoder-decoder)或者seq2seq模型。序列到序列模型,簡稱seq2seq模型。這兩個模型本質上都⽤到了兩個循環神經⽹絡,分別叫作編碼器和解碼器。編碼器⽤來分析輸⼊序列,解碼器⽤來⽣成輸出序列。兩 個循環神經網絡是共同訓練的。算法
下圖描述了使⽤編碼器—解碼器將上述英語句⼦翻譯成法語句⼦的⼀種⽅法。在訓練數據集中,咱們能夠在每一個句⼦後附上特殊符號「<eos>」(end of sequence)以表⽰序列的終⽌。編碼器每一個時間步的輸⼊依次爲英語句⼦中的單詞、標點和特殊符號「<eos>」。下圖中使⽤了編碼器在 最終時間步的隱藏狀態做爲輸⼊句⼦的表徵或編碼信息。解碼器在各個時間步中使⽤輸⼊句⼦的 編碼信息和上個時間步的輸出以及隱藏狀態做爲輸⼊。咱們但願解碼器在各個時間步能正確依次 輸出翻譯後的法語單詞、標點和特殊符號「<eos>」。須要注意的是,解碼器在最初時間步的輸⼊ ⽤到了⼀個表⽰序列開始的特殊符號「」(beginning of sequence)。網絡
編碼器的做⽤是把⼀個不定⻓的輸⼊序列變換成⼀個定⻓的背景變量 c,並在該背景變量中編碼輸⼊序列信息。常⽤的編碼器是循環神經⽹絡。app
讓咱們考慮批量⼤小爲1的時序數據樣本。假設輸⼊序列是 x1, . . . , xT,例如 xi 是輸⼊句⼦中的第 i 個詞。在時間步 t,循環神經⽹絡將輸⼊ xt 的特徵向量 xt 和上個時間步的隱藏狀態變換爲當前時間步的隱藏狀態ht。咱們能夠⽤函數 f 表達循環神經⽹絡隱藏層的變換:機器學習
接下來,編碼器經過⾃定義函數 q 將各個時間步的隱藏狀態變換爲背景變量:函數
例如,當選擇 q(h1, . . . , hT ) = hT 時,背景變量是輸⼊序列最終時間步的隱藏狀態hT。學習
以上描述的編碼器是⼀個單向的循環神經⽹絡,每一個時間步的隱藏狀態只取決於該時間步及以前的輸⼊⼦序列。咱們也可使⽤雙向循環神經⽹絡構造編碼器。在這種狀況下,編碼器每一個時間步的隱藏狀態同時取決於該時間步以前和以後的⼦序列(包括當前時間步的輸⼊),並編碼了整個序列的信息。編碼
剛剛已經介紹,編碼器輸出的背景變量 c 編碼了整個輸⼊序列 x1, . . . , xT 的信息。給定訓練樣本中的輸出序列 y1, y2, . . . , yT′ ,對每一個時間步 t′(符號與輸⼊序列或編碼器的時間步 t 有區別),解碼器輸出 yt′ 的條件機率將基於以前的輸出序列 和背景變量 c,即:
爲此,咱們可使⽤另⼀個循環神經⽹絡做爲解碼器。在輸出序列的時間步 t′,解碼器將上⼀時間步的輸出 以及背景變量 c 做爲輸⼊,並將它們與上⼀時間步的隱藏狀態
變換爲當前時間步的隱藏狀態st′。所以,咱們能夠⽤函數 g 表達解碼器隱藏層的變換:
有了解碼器的隱藏狀態後,咱們可使⽤⾃定義的輸出層和softmax運算來計算,例如,基於當前時間步的解碼器隱藏狀態 st′、上⼀時間步的輸出
以及背景變量 c 來計算當前時間步輸出 yt′ 的機率分佈。
根據最⼤似然估計,咱們能夠最⼤化輸出序列基於輸⼊序列的條件機率:
並獲得該輸出序列的損失:
在模型訓練中,全部輸出序列損失的均值一般做爲須要最小化的損失函數。在上圖所描述的模型預測中,咱們須要將解碼器在上⼀個時間步的輸出做爲當前時間步的輸⼊。與此不一樣,在訓練中咱們也能夠將標籤序列(訓練集的真實輸出序列)在上⼀個時間步的標籤做爲解碼器在當前時間步的輸⼊。這叫做強制教學(teacher forcing)。
以上介紹瞭如何訓練輸⼊和輸出均爲不定⻓序列的編碼器—解碼器。本節咱們介紹如何使⽤編碼器—解碼器來預測不定⻓的序列。
在準備訓練數據集時,咱們一般會在樣本的輸⼊序列和輸出序列後面分別附上⼀個特殊符號「<eos>」表⽰序列的終⽌。咱們在接下來的討論中也將沿⽤上⼀節的所有數學符號。爲了便於討論,假設解碼器的輸出是⼀段⽂本序列。設輸出⽂本詞典Y(包含特殊符號「<eos>」)的⼤小爲|Y|,輸出序列的最⼤⻓度爲T′。全部可能的輸出序列⼀共有 種。這些輸出序列中全部特殊符號「<eos>」後⾯的⼦序列將被捨棄。
貪婪搜索(greedy search)。對於輸出序列任⼀時間步t′,咱們從|Y|個詞中搜索出條件機率最⼤的詞:
做爲輸出。⼀旦搜索出「<eos>」符號,或者輸出序列⻓度已經達到了最⼤⻓度T′,便完成輸出。咱們在描述解碼器時提到,基於輸⼊序列⽣成輸出序列的條件機率是。咱們將該條件機率最⼤的輸出序列稱爲最優輸出序列。而貪婪搜索的主要問題是不能保證獲得最優輸出序列。
下⾯來看⼀個例⼦。假設輸出詞典⾥⾯有「A」「B」「C」和「<eos>」這4個詞。下圖中每一個時間步 下的4個數字分別表明了該時間步⽣成「A」「B」「C」和「<eos>」這4個詞的條件機率。在每一個時間步,貪婪搜索選取條件機率最⼤的詞。所以,圖10.9中將⽣成輸出序列「A」「B」「C」「<eos>」。該輸出序列的條件機率是0.5 × 0.4 × 0.4 × 0.6 = 0.048。
接下來,觀察下面演⽰的例⼦。與上圖中不一樣,在時間步2中選取了條件機率第⼆⼤的詞「C」 。因爲時間步3所基於的時間步1和2的輸出⼦序列由上圖中的「A」「B」變爲了下圖中的「A」「C」,下圖中時間步3⽣成各個詞的條件機率發⽣了變化。咱們選取條件機率最⼤的詞「B」。此時時間步4所基於的前3個時間步的輸出⼦序列爲「A」「C」「B」,與上圖中的「A」「B」「C」不一樣。所以,下圖中時間步4⽣成各個詞的條件機率也與上圖中的不一樣。咱們發現,此時的輸出序列「A」「C」「B」「<eos>」的條件機率是0.5 × 0.3 × 0.6 × 0.6 = 0.054,⼤於貪婪搜索獲得的輸出序列的條件機率。所以,貪婪搜索獲得的輸出序列「A」「B」「C」「<eos>」並⾮最優輸出序列。
若是⽬標是獲得最優輸出序列,咱們能夠考慮窮舉搜索(exhaustive search):窮舉全部可能的輸出序列,輸出條件機率最⼤的序列。
雖然窮舉搜索能夠獲得最優輸出序列,但它的計算開銷 很容易過⼤。例如,當|Y| = 10000且T′ = 10時,咱們將評估
個序列:這⼏乎不可能完成。而貪婪搜索的計 算開銷是
,一般顯著小於窮舉搜索的計算開銷。例如,當|Y| = 10000且T′ = 10時,我 們只需評估
個序列。
束搜索(beam search)是對貪婪搜索的⼀個改進算法。它有⼀個束寬(beam size)超參數。咱們將它設爲 k。在時間步 1 時,選取當前時間步條件機率最⼤的 k 個詞,分別組成 k 個候選輸出序列的⾸詞。在以後的每一個時間步,基於上個時間步的 k 個候選輸出序列,從 k |Y| 個可能的輸出序列中選取條件機率最⼤的 k 個,做爲該時間步的候選輸出序列。最終,咱們從各個時間步的候選輸出序列中篩選出包含特殊符號「<eos>」的序列,並將它們中全部特殊符號「<eos>」後⾯的⼦序列捨棄,獲得最終候選輸出序列的集合。
束寬爲2,輸出序列最⼤⻓度爲3。候選輸出序列有A、C、AB、CE、ABD和CED。咱們將根據這6個序列得出最終候選輸出序列的集合。在最終候選輸出序列的集合中,咱們取如下分數最⾼的序列做爲輸出序列:
其中 L 爲最終候選序列⻓度,α ⼀般可選爲0.75。分⺟上的 Lα 是爲了懲罰較⻓序列在以上分數中較多的對數相加項。分析可知,束搜索的計算開銷爲 。這介於貪婪搜索和窮舉搜索的計算開銷之間。此外,貪婪搜索可看做是束寬爲 1 的束搜索。束搜索經過靈活的束寬 k 來權衡計算開銷和搜索質量。
評價機器翻譯結果一般使⽤BLEU(Bilingual Evaluation Understudy)(雙語評估替補)。對於模型預測序列中任意的⼦序列,BLEU考察這個⼦序列是否出如今標籤序列中。
具體來講,設詞數爲 n 的⼦序列的精度爲 pn。它是預測序列與標籤序列匹配詞數爲 n 的⼦序列的數量與預測序列中詞數爲 n 的⼦序列的數量之⽐。舉個例⼦,假設標籤序列爲A、B、C、D、E、F,預測序列爲A、B、B、C、D,那麼:
預測序列一元詞組:A/B/C/D,都在標籤序列裏存在,因此P1=4/5,以此類推,p2 = 3/4, p3 = 1/3, p4 = 0。設 分別爲標籤序列和預測序列的詞數,那麼,BLEU的定義爲:
其中 k 是咱們但願匹配的⼦序列的最⼤詞數。能夠看到當預測序列和標籤序列徹底⼀致時, BLEU爲1。
由於匹配較⻓⼦序列⽐匹配較短⼦序列更難,BLEU對匹配較⻓⼦序列的精度賦予了更⼤權重。例如,當 pn 固定在0.5時,隨着n的增⼤,。另外,模型預測較短序列每每會獲得較⾼pn 值。所以,上式中連乘項前⾯的係數是爲了懲罰較短的輸出而設的。舉個例⼦,當k = 2時,假設標籤序列爲A、B、C、D、E、F,而預測序列爲A、 B。雖然p1 = p2 = 1,但懲罰係數exp(1-6/2) ≈ 0.14,所以BLEU也接近0.14。
做者:@mantchs
GitHub:github.com/NLP-LOVE/ML…