一区二区三区日韩精品-日韩经典一区二区三区-五月激情综合丁香婷婷-欧美精品中文字幕专区

分享

PaddlePaddle

 冬城溪酒之秦文 2017-12-05


機(jī)器翻譯(machine translation, MT)是用計(jì)算機(jī)來(lái)實(shí)現(xiàn)不同語(yǔ)言之間翻譯的技術(shù)。被翻譯的語(yǔ)言通常稱(chēng)為源語(yǔ)言(source language),翻譯成的結(jié)果語(yǔ)言稱(chēng)為目標(biāo)語(yǔ)言(target language)。機(jī)器翻譯即實(shí)現(xiàn)從源語(yǔ)言到目標(biāo)語(yǔ)言轉(zhuǎn)換的過(guò)程,是自然語(yǔ)言處理的重要研究領(lǐng)域之一。

早期機(jī)器翻譯系統(tǒng)多為基于規(guī)則的翻譯系統(tǒng),需要由語(yǔ)言學(xué)家編寫(xiě)兩種語(yǔ)言之間的轉(zhuǎn)換規(guī)則,再將這些規(guī)則錄入計(jì)算機(jī)。該方法對(duì)語(yǔ)言學(xué)家的要求非常高,而且我們幾乎無(wú)法總結(jié)一門(mén)語(yǔ)言會(huì)用到的所有規(guī)則,更何況兩種甚至更多的語(yǔ)言。因此,傳統(tǒng)機(jī)器翻譯方法面臨的主要挑戰(zhàn)是無(wú)法得到一個(gè)完備的規(guī)則集合[1]。

為解決以上問(wèn)題,統(tǒng)計(jì)機(jī)器翻譯(Statistical Machine Translation, SMT)技術(shù)應(yīng)運(yùn)而生。在統(tǒng)計(jì)機(jī)器翻譯技術(shù)中,轉(zhuǎn)化規(guī)則是由機(jī)器自動(dòng)從大規(guī)模的語(yǔ)料中學(xué)習(xí)得到的,而非我們?nèi)酥鲃?dòng)提供規(guī)則。因此,它克服了基于規(guī)則的翻譯系統(tǒng)所面臨的知識(shí)獲取瓶頸的問(wèn)題,但仍然存在許多挑戰(zhàn):1)人為設(shè)計(jì)許多特征(feature),但永遠(yuǎn)無(wú)法覆蓋所有的語(yǔ)言現(xiàn)象;2)難以利用全局的特征;3)依賴(lài)于許多預(yù)處理環(huán)節(jié),如詞語(yǔ)對(duì)齊、分詞或符號(hào)化(tokenization)、規(guī)則抽取、句法分析等,而每個(gè)環(huán)節(jié)的錯(cuò)誤會(huì)逐步累積,對(duì)翻譯的影響也越來(lái)越大。

近年來(lái),深度學(xué)習(xí)技術(shù)的發(fā)展為解決上述挑戰(zhàn)提供了新的思路。將深度學(xué)習(xí)應(yīng)用于機(jī)器翻譯任務(wù)的方法大致分為兩類(lèi):1)仍以統(tǒng)計(jì)機(jī)器翻譯系統(tǒng)為框架,只是利用神經(jīng)網(wǎng)絡(luò)來(lái)改進(jìn)其中的關(guān)鍵模塊,如語(yǔ)言模型、調(diào)序模型等(見(jiàn)圖1的左半部分);2)不再以統(tǒng)計(jì)機(jī)器翻譯系統(tǒng)為框架,而是直接用神經(jīng)網(wǎng)絡(luò)將源語(yǔ)言映射到目標(biāo)語(yǔ)言,即端到端的神經(jīng)網(wǎng)絡(luò)機(jī)器翻譯(End-to-End Neural Machine Translation, End-to-End NMT)(見(jiàn)圖1的右半部分),簡(jiǎn)稱(chēng)為NMT模型。


圖1. 基于神經(jīng)網(wǎng)絡(luò)的機(jī)器翻譯系統(tǒng)

本教程主要介紹NMT模型,以及如何用PaddlePaddle來(lái)訓(xùn)練一個(gè)NMT模型。

效果展示

以中英翻譯(中文翻譯到英文)的模型為例,當(dāng)模型訓(xùn)練完畢時(shí),如果輸入如下已分詞的中文句子:

這些 是 希望 的 曙光 和 解脫 的 跡象 .
如果設(shè)定顯示翻譯結(jié)果的條數(shù)(即柱搜索算法的寬度)為3,生成的英語(yǔ)句子如下:
0 -5.36816   These are signs of hope and relief . <e>
1 -6.23177   These are the light of hope and relief . <e>
2 -7.7914  These are the light of hope and the relief of hope . <e>
- 左起第一列是生成句子的序號(hào);左起第二列是該條句子的得分(從大到小),分值越高越好;左起第三列是生成的英語(yǔ)句子。 - 另外有兩個(gè)特殊標(biāo)志:<e>表示句子的結(jié)尾,<unk>表示未登錄詞(unknown word),即未在訓(xùn)練字典中出現(xiàn)的詞。

模型概覽

本節(jié)依次介紹GRU(Gated Recurrent Unit,門(mén)控循環(huán)單元),雙向循環(huán)神經(jīng)網(wǎng)絡(luò)(Bi-directional Recurrent Neural Network),NMT模型中典型的編碼器-解碼器(Encoder-Decoder)框架和注意力(Attention)機(jī)制,以及柱搜索(beam search)算法。

GRU

我們已經(jīng)在情感分析一章中介紹了循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)及長(zhǎng)短時(shí)間記憶網(wǎng)絡(luò)(LSTM)。相比于簡(jiǎn)單的RNN,LSTM增加了記憶單元(memory cell)、輸入門(mén)(input gate)、遺忘門(mén)(forget gate)及輸出門(mén)(output gate),這些門(mén)及記憶單元組合起來(lái)大大提升了RNN處理遠(yuǎn)距離依賴(lài)問(wèn)題的能力。

GRU[2]是Cho等人在LSTM上提出的簡(jiǎn)化版本,也是RNN的一種擴(kuò)展,如下圖所示。GRU單元只有兩個(gè)門(mén): - 重置門(mén)(reset gate):如果重置門(mén)關(guān)閉,會(huì)忽略掉歷史信息,即歷史不相干的信息不會(huì)影響未來(lái)的輸出。 - 更新門(mén)(update gate):將LSTM的輸入門(mén)和遺忘門(mén)合并,用于控制歷史信息對(duì)當(dāng)前時(shí)刻隱層輸出的影響。如果更新門(mén)接近1,會(huì)把歷史信息傳遞下去。


圖2. GRU(門(mén)控循環(huán)單元)

一般來(lái)說(shuō),具有短距離依賴(lài)屬性的序列,其重置門(mén)比較活躍;相反,具有長(zhǎng)距離依賴(lài)屬性的序列,其更新門(mén)比較活躍。另外,Chung等人[3]通過(guò)多組實(shí)驗(yàn)表明,GRU雖然參數(shù)更少,但是在多個(gè)任務(wù)上都和LSTM有相近的表現(xiàn)。

雙向循環(huán)神經(jīng)網(wǎng)絡(luò)

我們已經(jīng)在語(yǔ)義角色標(biāo)注一章中介紹了一種雙向循環(huán)神經(jīng)網(wǎng)絡(luò),這里介紹Bengio團(tuán)隊(duì)在論文[2,4]中提出的另一種結(jié)構(gòu)。該結(jié)構(gòu)的目的是輸入一個(gè)序列,得到其在每個(gè)時(shí)刻的特征表示,即輸出的每個(gè)時(shí)刻都用定長(zhǎng)向量表示到該時(shí)刻的上下文語(yǔ)義信息。

具體來(lái)說(shuō),該雙向循環(huán)神經(jīng)網(wǎng)絡(luò)分別在時(shí)間維以順序和逆序——即前向(forward)和后向(backward)——依次處理輸入序列,并將每個(gè)時(shí)間步RNN的輸出拼接成為最終的輸出層。這樣每個(gè)時(shí)間步的輸出節(jié)點(diǎn),都包含了輸入序列中當(dāng)前時(shí)刻完整的過(guò)去和未來(lái)的上下文信息。下圖展示的是一個(gè)按時(shí)間步展開(kāi)的雙向循環(huán)神經(jīng)網(wǎng)絡(luò)。該網(wǎng)絡(luò)包含一個(gè)前向和一個(gè)后向RNN,其中有六個(gè)權(quán)重矩陣:輸入到前向隱層和后向隱層的權(quán)重矩陣(W1,W3),隱層到隱層自己的權(quán)重矩陣(W2,W5),前向隱層和后向隱層到輸出層的權(quán)重矩陣(W4,W6)。注意,該網(wǎng)絡(luò)的前向隱層和后向隱層之間沒(méi)有連接。


圖3. 按時(shí)間步展開(kāi)的雙向循環(huán)神經(jīng)網(wǎng)絡(luò)

編碼器-解碼器框架

編碼器-解碼器(Encoder-Decoder)[2]框架用于解決由一個(gè)任意長(zhǎng)度的源序列到另一個(gè)任意長(zhǎng)度的目標(biāo)序列的變換問(wèn)題。即編碼階段將整個(gè)源序列編碼成一個(gè)向量,解碼階段通過(guò)最大化預(yù)測(cè)序列概率,從中解碼出整個(gè)目標(biāo)序列。編碼和解碼的過(guò)程通常都使用RNN實(shí)現(xiàn)。


圖4. 編碼器-解碼器框架

編碼器

編碼階段分為三步:

  1. one-hot vector表示:將源語(yǔ)言句子x={x1,x2,...,xT}的每個(gè)詞xi表示成一個(gè)列向量wi?{0,1}|V|,i=1,2,...,T。這個(gè)向量wi的維度與詞匯表大小|V| 相同,并且只有一個(gè)維度上有值1(該位置對(duì)應(yīng)該詞在詞匯表中的位置),其余全是0。

  2. 映射到低維語(yǔ)義空間的詞向量:one-hot vector表示存在兩個(gè)問(wèn)題,1)生成的向量維度往往很大,容易造成維數(shù)災(zāi)難;2)難以刻畫(huà)詞與詞之間的關(guān)系(如語(yǔ)義相似性,也就是無(wú)法很好地表達(dá)語(yǔ)義)。因此,需再one-hot vector映射到低維的語(yǔ)義空間,由一個(gè)固定維度的稠密向量(稱(chēng)為詞向量)表示。記映射矩陣為C?RK×|V|,用si=Cwi表示第i個(gè)詞的詞向量,K為向量維度。

  3. 用RNN編碼源語(yǔ)言詞序列:這一過(guò)程的計(jì)算公式為hi=?θ(hi?1,si),其中h0是一個(gè)全零的向量,?θ是一個(gè)非線性激活函數(shù),最后得到的h={h1,...,hT}就是RNN依次讀入源語(yǔ)言T個(gè)詞的狀態(tài)編碼序列。整句話的向量表示可以采用h在最后一個(gè)時(shí)間步T的狀態(tài)編碼,或使用時(shí)間維上的池化(pooling)結(jié)果。

第3步也可以使用雙向循環(huán)神經(jīng)網(wǎng)絡(luò)實(shí)現(xiàn)更復(fù)雜的句編碼表示,具體可以用雙向GRU實(shí)現(xiàn)。前向GRU按照詞序列(x1,x2,...,xT)的順序依次編碼源語(yǔ)言端詞,并得到一系列隱層狀態(tài)(h1,h2,...,hT)。類(lèi)似的,后向GRU按照(xT,xT?1,...,x1)的順序依次編碼源語(yǔ)言端詞,得到(h1,h2,...,hT)。最后對(duì)于詞xi,通過(guò)拼接兩個(gè)GRU的結(jié)果得到它的隱層狀態(tài),即hi=[hTi,hTi]T。


圖5. 使用雙向GRU的編碼器

解碼器

機(jī)器翻譯任務(wù)的訓(xùn)練過(guò)程中,解碼階段的目標(biāo)是最大化下一個(gè)正確的目標(biāo)語(yǔ)言詞的概率。思路是:

  1. 每一個(gè)時(shí)刻,根據(jù)源語(yǔ)言句子的編碼信息(又叫上下文向量,context vector)c、真實(shí)目標(biāo)語(yǔ)言序列的第i個(gè)詞uii時(shí)刻RNN的隱層狀態(tài)zi,計(jì)算出下一個(gè)隱層狀態(tài)zi+1。計(jì)算公式如下:

zi+1=?θ(c,ui,zi)

其中?θ是一個(gè)非線性激活函數(shù);c=qh是源語(yǔ)言句子的上下文向量,在不使用注意力機(jī)制時(shí),如果編碼器的輸出是源語(yǔ)言句子編碼后的最后一個(gè)元素,則可以定義c=hT;ui是目標(biāo)語(yǔ)言序列的第i個(gè)單詞,u0是目標(biāo)語(yǔ)言序列的開(kāi)始標(biāo)記<s>,表示解碼開(kāi)始;zii時(shí)刻解碼RNN的隱層狀態(tài),z0是一個(gè)全零的向量。

  1. zi+1通過(guò)softmax歸一化,得到目標(biāo)語(yǔ)言序列的第i+1個(gè)單詞的概率分布pi+1。概率分布公式如下:

p(ui+1|u<i+1,x)=softmax(Wszi+1+bz)

其中Wszi+1+bz是對(duì)每個(gè)可能的輸出單詞進(jìn)行打分,再用softmax歸一化就可以得到第i+1個(gè)詞的概率pi+1。

  1. 根據(jù)pi+1ui+1計(jì)算代價(jià)。
  2. 重復(fù)步驟1~3,直到目標(biāo)語(yǔ)言序列中的所有詞處理完畢。

機(jī)器翻譯任務(wù)的生成過(guò)程,通俗來(lái)講就是根據(jù)預(yù)先訓(xùn)練的模型來(lái)翻譯源語(yǔ)言句子。生成過(guò)程中的解碼階段和上述訓(xùn)練過(guò)程的有所差異,具體介紹請(qǐng)見(jiàn)柱搜索算法。

注意力機(jī)制

如果編碼階段的輸出是一個(gè)固定維度的向量,會(huì)帶來(lái)以下兩個(gè)問(wèn)題:1)不論源語(yǔ)言序列的長(zhǎng)度是5個(gè)詞還是50個(gè)詞,如果都用固定維度的向量去編碼其中的語(yǔ)義和句法結(jié)構(gòu)信息,對(duì)模型來(lái)說(shuō)是一個(gè)非常高的要求,特別是對(duì)長(zhǎng)句子序列而言;2)直覺(jué)上,當(dāng)人類(lèi)翻譯一句話時(shí),會(huì)對(duì)與當(dāng)前譯文更相關(guān)的源語(yǔ)言片段上給予更多關(guān)注,且關(guān)注點(diǎn)會(huì)隨著翻譯的進(jìn)行而改變。而固定維度的向量則相當(dāng)于,任何時(shí)刻都對(duì)源語(yǔ)言所有信息給予了同等程度的關(guān)注,這是不合理的。因此,Bahdanau等人[4]引入注意力(attention)機(jī)制,可以對(duì)編碼后的上下文片段進(jìn)行解碼,以此來(lái)解決長(zhǎng)句子的特征學(xué)習(xí)問(wèn)題。下面介紹在注意力機(jī)制下的解碼器結(jié)構(gòu)。

與簡(jiǎn)單的解碼器不同,這里zi的計(jì)算公式為:

zi+1=?θ(ci,ui,zi)

可見(jiàn),源語(yǔ)言句子的編碼向量表示為第i個(gè)詞的上下文片段ci,即針對(duì)每一個(gè)目標(biāo)語(yǔ)言中的詞ui,都有一個(gè)特定的ci與之對(duì)應(yīng)。ci的計(jì)算公式如下:

ci=Tj=1aijhj,ai=[ai1,ai2,...,aiT]

從公式中可以看出,注意力機(jī)制是通過(guò)對(duì)編碼器中各時(shí)刻的RNN狀態(tài)hj進(jìn)行加權(quán)平均實(shí)現(xiàn)的。權(quán)重aij表示目標(biāo)語(yǔ)言中第i個(gè)詞對(duì)源語(yǔ)言中第j個(gè)詞的注意力大小,aij的計(jì)算公式如下:

begin{align} a_{ij}&=frac{exp(e_{ij})}{sum_{k=1}^{T}exp(e_{ik})}\e_{ij}&=align(z_i,h_j)\end{align}

其中,align可以看作是一個(gè)對(duì)齊模型,用來(lái)衡量目標(biāo)語(yǔ)言中第i個(gè)詞和源語(yǔ)言中第j個(gè)詞的匹配程度。具體而言,這個(gè)程度是通過(guò)解碼RNN的第i個(gè)隱層狀態(tài)zi和源語(yǔ)言句子的第j個(gè)上下文片段hj計(jì)算得到的。傳統(tǒng)的對(duì)齊模型中,目標(biāo)語(yǔ)言的每個(gè)詞明確對(duì)應(yīng)源語(yǔ)言的一個(gè)或多個(gè)詞(hard alignment);而在注意力模型中采用的是soft alignment,即任何兩個(gè)目標(biāo)語(yǔ)言和源語(yǔ)言詞間均存在一定的關(guān)聯(lián),且這個(gè)關(guān)聯(lián)強(qiáng)度是由模型計(jì)算得到的實(shí)數(shù),因此可以融入整個(gè)NMT框架,并通過(guò)反向傳播算法進(jìn)行訓(xùn)練。


圖6. 基于注意力機(jī)制的解碼器

柱搜索算法

柱搜索(beam search)是一種啟發(fā)式圖搜索算法,用于在圖或樹(shù)中搜索有限集合中的最優(yōu)擴(kuò)展節(jié)點(diǎn),通常用在解空間非常大的系統(tǒng)(如機(jī)器翻譯、語(yǔ)音識(shí)別)中,原因是內(nèi)存無(wú)法裝下圖或樹(shù)中所有展開(kāi)的解。如在機(jī)器翻譯任務(wù)中希望翻譯“<s>你好<e>”,就算目標(biāo)語(yǔ)言字典中只有3個(gè)詞(<s>, <e>, hello),也可能生成無(wú)限句話(hello循環(huán)出現(xiàn)的次數(shù)不定),為了找到其中較好的翻譯結(jié)果,我們可采用柱搜索算法。

柱搜索算法使用廣度優(yōu)先策略建立搜索樹(shù),在樹(shù)的每一層,按照啟發(fā)代價(jià)(heuristic cost)(本教程中,為生成詞的log概率之和)對(duì)節(jié)點(diǎn)進(jìn)行排序,然后僅留下預(yù)先確定的個(gè)數(shù)(文獻(xiàn)中通常稱(chēng)為beam width、beam size、柱寬度等)的節(jié)點(diǎn)。只有這些節(jié)點(diǎn)會(huì)在下一層繼續(xù)擴(kuò)展,其他節(jié)點(diǎn)就被剪掉了,也就是說(shuō)保留了質(zhì)量較高的節(jié)點(diǎn),剪枝了質(zhì)量較差的節(jié)點(diǎn)。因此,搜索所占用的空間和時(shí)間大幅減少,但缺點(diǎn)是無(wú)法保證一定獲得最優(yōu)解。

使用柱搜索算法的解碼階段,目標(biāo)是最大化生成序列的概率。思路是:

  1. 每一個(gè)時(shí)刻,根據(jù)源語(yǔ)言句子的編碼信息c、生成的第i個(gè)目標(biāo)語(yǔ)言序列單詞uii時(shí)刻RNN的隱層狀態(tài)zi,計(jì)算出下一個(gè)隱層狀態(tài)zi+1。
  2. zi+1通過(guò)softmax歸一化,得到目標(biāo)語(yǔ)言序列的第i+1個(gè)單詞的概率分布pi+1。
  3. 根據(jù)pi+1采樣出單詞ui+1
  4. 重復(fù)步驟1~3,直到獲得句子結(jié)束標(biāo)記<e>或超過(guò)句子的最大生成長(zhǎng)度為止。

注意:zi+1pi+1的計(jì)算公式同解碼器中的一樣。且由于生成時(shí)的每一步都是通過(guò)貪心法實(shí)現(xiàn)的,因此并不能保證得到全局最優(yōu)解。

數(shù)據(jù)介紹

本教程使用WMT-14數(shù)據(jù)集中的bitexts(after selection)作為訓(xùn)練集,dev+test data作為測(cè)試集和生成集。

數(shù)據(jù)預(yù)處理

我們的預(yù)處理流程包括兩步: - 將每個(gè)源語(yǔ)言到目標(biāo)語(yǔ)言的平行語(yǔ)料庫(kù)文件合并為一個(gè)文件: - 合并每個(gè)XXX.srcXXX.trg文件為XXX。 - XXX中的第i行內(nèi)容為XXX.src中的第i行和XXX.trg中的第i行連接,用't'分隔。 - 創(chuàng)建訓(xùn)練數(shù)據(jù)的“源字典”和“目標(biāo)字典”。每個(gè)字典都有DICTSIZE個(gè)單詞,包括:語(yǔ)料中詞頻最高的(DICTSIZE - 3)個(gè)單詞,和3個(gè)特殊符號(hào)<s>(序列的開(kāi)始)、<e>(序列的結(jié)束)和<unk>(未登錄詞)。

示例數(shù)據(jù)

因?yàn)橥暾臄?shù)據(jù)集數(shù)據(jù)量較大,為了驗(yàn)證訓(xùn)練流程,PaddlePaddle接口paddle.dataset.wmt14中默認(rèn)提供了一個(gè)經(jīng)過(guò)預(yù)處理的較小規(guī)模的數(shù)據(jù)集。

該數(shù)據(jù)集有193319條訓(xùn)練數(shù)據(jù),6003條測(cè)試數(shù)據(jù),詞典長(zhǎng)度為30000。因?yàn)閿?shù)據(jù)規(guī)模限制,使用該數(shù)據(jù)集訓(xùn)練出來(lái)的模型效果無(wú)法保證。

流程說(shuō)明

paddle初始化

# 加載 paddle的python包
import sys
import paddle.v2 as paddle

# 配置只使用cpu,并且使用一個(gè)cpu進(jìn)行訓(xùn)練
paddle.init(use_gpu=False, trainer_count=1)
# 訓(xùn)練模式False,生成模式True
is_generating = False

模型結(jié)構(gòu)

  1. 首先,定義了一些全局變量。

    dict_size = 30000 # 字典維度
    source_dict_dim = dict_size # 源語(yǔ)言字典維度
    target_dict_dim = dict_size # 目標(biāo)語(yǔ)言字典維度
    word_vector_dim = 512 # 詞向量維度
    encoder_size = 512 # 編碼器中的GRU隱層大小
    decoder_size = 512 # 解碼器中的GRU隱層大小
    beam_size = 3 # 柱寬度
    max_length = 250 # 生成句子的最大長(zhǎng)度
    
  2. 其次,實(shí)現(xiàn)編碼器框架。分為三步:

  3. 輸入是一個(gè)文字序列,被表示成整型的序列。序列中每個(gè)元素是文字在字典中的索引。所以,我們定義數(shù)據(jù)層的數(shù)據(jù)類(lèi)型為integer_value_sequence(整型序列),序列中每個(gè)元素的范圍是[0, source_dict_dim)。

 src_word_id = paddle.layer.data(
     name='source_language_word',
     type=paddle.data_type.integer_value_sequence(source_dict_dim))
- 將上述編碼映射到低維語(yǔ)言空間的詞向量s。

 src_embedding = paddle.layer.embedding(
     input=src_word_id, size=word_vector_dim)
- 用雙向GRU編碼源語(yǔ)言序列,拼接兩個(gè)GRU的編碼結(jié)果得到h。
 src_forward = paddle.networks.simple_gru(
     input=src_embedding, size=encoder_size)
 src_backward = paddle.networks.simple_gru(
     input=src_embedding, size=encoder_size, reverse=True)
 encoded_vector = paddle.layer.concat(input=[src_forward, src_backward])
  1. 接著,定義基于注意力機(jī)制的解碼器框架。分為三步:

  2. 對(duì)源語(yǔ)言序列編碼后的結(jié)果(見(jiàn)2的最后一步),過(guò)一個(gè)前饋神經(jīng)網(wǎng)絡(luò)(Feed Forward Neural Network),得到其映射。

encoded_proj = paddle.layer.fc(
      act=paddle.activation.Linear(),
      size=decoder_size,
      bias_attr=False,
      input=encoded_vector)
  • 構(gòu)造解碼器RNN的初始狀態(tài)。由于解碼器需要預(yù)測(cè)時(shí)序目標(biāo)序列,但在0時(shí)刻并沒(méi)有初始值,所以我們希望對(duì)其進(jìn)行初始化。這里采用的是將源語(yǔ)言序列逆序編碼后的最后一個(gè)狀態(tài)進(jìn)行非線性映射,作為該初始值,即c0=hT。
backward_first = paddle.layer.first_seq(input=src_backward)
decoder_boot = paddle.layer.fc(
      size=decoder_size,
      act=paddle.activation.Tanh(),
      bias_attr=False,
      input=backward_first)
  • 定義解碼階段每一個(gè)時(shí)間步的RNN行為,即根據(jù)當(dāng)前時(shí)刻的源語(yǔ)言上下文向量ci、解碼器隱層狀態(tài)zi和目標(biāo)語(yǔ)言中第i個(gè)詞ui,來(lái)預(yù)測(cè)第i+1個(gè)詞的概率pi+1。
    • decoder_mem記錄了前一個(gè)時(shí)間步的隱層狀態(tài)zi,其初始狀態(tài)是decoder_boot。
    • context通過(guò)調(diào)用simple_attention函數(shù),實(shí)現(xiàn)公式ci=j=1Taijhj。其中,enc_vec是hj,enc_proj是hj的映射(見(jiàn)3.1),權(quán)重aij的計(jì)算已經(jīng)封裝在simple_attention函數(shù)中。
    • decoder_inputs融合了ci和當(dāng)前目標(biāo)詞current_word(即ui)的表示。
    • gru_step通過(guò)調(diào)用gru_step_layer函數(shù),在decoder_inputs和decoder_mem上做了激活操作,即實(shí)現(xiàn)公式zi+1=?θ(ci,ui,zi)。
    • 最后,使用softmax歸一化計(jì)算單詞的概率,將out結(jié)果返回,即實(shí)現(xiàn)公式p(ui|u<i,x)=softmax(Wszi+bz)。
def gru_decoder_with_attention(enc_vec, enc_proj, current_word):
     decoder_mem = paddle.layer.memory(
         name='gru_decoder', size=decoder_size, boot_layer=decoder_boot)

     context = paddle.networks.simple_attention(
         encoded_sequence=enc_vec,
         encoded_proj=enc_proj,
         decoder_state=decoder_mem)

     decoder_inputs = paddle.layer.fc(
         act=paddle.activation.Linear(),
         size=decoder_size * 3,
         bias_attr=False,
         input=[context, current_word],
         layer_attr=paddle.attr.ExtraLayerAttribute(
             error_clipping_threshold=100.0))

     gru_step = paddle.layer.gru_step(
         name='gru_decoder',
         input=decoder_inputs,
         output_mem=decoder_mem,
         size=decoder_size)

     out = paddle.layer.mixed(
         size=target_dict_dim,
         bias_attr=True,
         act=paddle.activation.Softmax(),
         input=paddle.layer.full_matrix_projection(input=gru_step))
     return out
  1. 定義解碼器框架名字,和gru_decoder_with_attention函數(shù)的前兩個(gè)輸入。注意:這兩個(gè)輸入使用StaticInput,具體說(shuō)明可見(jiàn)StaticInput文檔。

    decoder_group_name = "decoder_group"
    group_input1 = paddle.layer.StaticInput(input=encoded_vector)
    group_input2 = paddle.layer.StaticInput(input=encoded_proj)
    group_inputs = [group_input1, group_input2]
    
  2. 訓(xùn)練模式下的解碼器調(diào)用:

  3. 首先,將目標(biāo)語(yǔ)言序列的詞向量trg_embedding,直接作為訓(xùn)練模式下的current_word傳給gru_decoder_with_attention函數(shù)。

  4. 其次,使用recurrent_group函數(shù)循環(huán)調(diào)用gru_decoder_with_attention函數(shù)。
  5. 接著,使用目標(biāo)語(yǔ)言的下一個(gè)詞序列作為標(biāo)簽層lbl,即預(yù)測(cè)目標(biāo)詞。
  6. 最后,用多類(lèi)交叉熵?fù)p失函數(shù)classification_cost來(lái)計(jì)算損失值。
if not is_generating:
    trg_embedding = paddle.layer.embedding(
        input=paddle.layer.data(
            name='target_language_word',
            type=paddle.data_type.integer_value_sequence(target_dict_dim)),
        size=word_vector_dim,
        param_attr=paddle.attr.ParamAttr(name='_target_language_embedding'))
    group_inputs.append(trg_embedding)

    # For decoder equipped with attention mechanism, in training,
    # target embeding (the groudtruth) is the data input,
    # while encoded source sequence is accessed to as an unbounded memory.
    # Here, the StaticInput defines a read-only memory
    # for the recurrent_group.
    decoder = paddle.layer.recurrent_group(
        name=decoder_group_name,
        step=gru_decoder_with_attention,
        input=group_inputs)

    lbl = paddle.layer.data(
        name='target_language_next_word',
        type=paddle.data_type.integer_value_sequence(target_dict_dim))
    cost = paddle.layer.classification_cost(input=decoder, label=lbl)
  1. 生成模式下的解碼器調(diào)用:

  2. 首先,在序列生成任務(wù)中,由于解碼階段的RNN總是引用上一時(shí)刻生成出的詞的詞向量,作為當(dāng)前時(shí)刻的輸入,因此,使用GeneratedInput來(lái)自動(dòng)完成這一過(guò)程。具體說(shuō)明可見(jiàn)GeneratedInput文檔。

  3. 其次,使用beam_search函數(shù)循環(huán)調(diào)用gru_decoder_with_attention函數(shù),生成出序列id。
if is_generating:
   # In generation, the decoder predicts a next target word based on
   # the encoded source sequence and the previous generated target word.

   # The encoded source sequence (encoder's output) must be specified by
   # StaticInput, which is a read-only memory.
   # Embedding of the previous generated word is automatically retrieved
   # by GeneratedInputs initialized by a start mark <s>.

    trg_embedding = paddle.layer.GeneratedInput(
        size=target_dict_dim,
        embedding_name='_target_language_embedding',
        embedding_size=word_vector_dim)
    group_inputs.append(trg_embedding)

    beam_gen = paddle.layer.beam_search(
        name=decoder_group_name,
        step=gru_decoder_with_attention,
        input=group_inputs,
        bos_id=0,
        eos_id=1,
        beam_size=beam_size,
        max_length=max_length)

注意:我們提供的配置在Bahdanau的論文[4]上做了一些簡(jiǎn)化,可參考issue #1133。

訓(xùn)練模型

  1. 參數(shù)定義

    依據(jù)模型配置的cost定義模型參數(shù)??梢源蛴?shù)名字,如果在網(wǎng)絡(luò)配置中沒(méi)有指定名字,則默認(rèn)生成。

    if not is_generating:
        parameters = paddle.parameters.create(cost)
        for param in parameters.keys():
            print param
    
  2. 數(shù)據(jù)定義

    獲取wmt14的dataset reader。

    if not is_generating:
        wmt14_reader = paddle.batch(
            paddle.reader.shuffle(
                paddle.dataset.wmt14.train(dict_size=dict_size), buf_size=8192),
            batch_size=5)
    
  3. 構(gòu)造trainer

    根據(jù)優(yōu)化目標(biāo)cost,網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)和模型參數(shù)來(lái)構(gòu)造出trainer用來(lái)訓(xùn)練,在構(gòu)造時(shí)還需指定優(yōu)化方法,這里使用最基本的SGD方法。

    if not is_generating:
        optimizer = paddle.optimizer.Adam(
            learning_rate=5e-5,
            regularization=paddle.optimizer.L2Regularization(rate=8e-4))
        trainer = paddle.trainer.SGD(cost=cost,
                                     parameters=parameters,
                                     update_equation=optimizer)
    
  4. 構(gòu)造event_handler

    可以通過(guò)自定義回調(diào)函數(shù)來(lái)評(píng)估訓(xùn)練過(guò)程中的各種狀態(tài),比如錯(cuò)誤率等。下面的代碼通過(guò)event.batch_id % 2 == 0 指定每2個(gè)batch打印一次日志,包含cost等信息。

    if not is_generating:
        def event_handler(event):
            if isinstance(event, paddle.event.EndIteration):
                if event.batch_id % 2 == 0:
                    print "\nPass %d, Batch %d, Cost %f, %s" % (
                        event.pass_id, event.batch_id, event.cost, event.metrics)
    
  5. 啟動(dòng)訓(xùn)練

    if not is_generating:
        trainer.train(
                reader=wmt14_reader, event_handler=event_handler, num_passes=2)
    

訓(xùn)練開(kāi)始后,可以觀察到event_handler輸出的日志如下:

Pass 0, Batch 0, Cost 148.444983, {'classification_error_evaluator': 1.0}
.........
Pass 0, Batch 10, Cost 335.896802, {'classification_error_evaluator': 0.9325153231620789}
.........

生成模型

  1. 加載預(yù)訓(xùn)練的模型

    由于NMT模型的訓(xùn)練非常耗時(shí),我們?cè)?0個(gè)物理節(jié)點(diǎn)(每節(jié)點(diǎn)含有2顆6核CPU)的集群中,花了5天時(shí)間訓(xùn)練了一個(gè)模型供大家直接下載使用。該模型大小為205MB,BLEU評(píng)估值為26.92。

    if is_generating:
        parameters = paddle.dataset.wmt14.model()
    
    2. 數(shù)據(jù)定義

    從wmt14的生成集中讀取前3個(gè)樣本作為源語(yǔ)言句子。

    if is_generating:
        gen_creator = paddle.dataset.wmt14.gen(dict_size)
        gen_data = []
        gen_num = 3
        for item in gen_creator():
            gen_data.append((item[0], ))
            if len(gen_data) == gen_num:
                break
    
    3. 構(gòu)造infer

    根據(jù)網(wǎng)絡(luò)拓?fù)浣Y(jié)構(gòu)和模型參數(shù)構(gòu)造出infer用來(lái)生成,在預(yù)測(cè)時(shí)還需要指定輸出域field,這里使用生成句子的概率prob和句子中每個(gè)詞的id。

    if is_generating:
        beam_result = paddle.infer(
            output_layer=beam_gen,
            parameters=parameters,
            input=gen_data,
            field=['prob', 'id'])
    
  2. 打印生成結(jié)果

    根據(jù)源/目標(biāo)語(yǔ)言字典,將源語(yǔ)言句子和beam_size個(gè)生成句子打印輸出。

    if is_generating:
        # load the dictionary
        src_dict, trg_dict = paddle.dataset.wmt14.get_dict(dict_size)
    
        gen_sen_idx = np.where(beam_result[1] == -1)[0]
        assert len(gen_sen_idx) == len(gen_data) * beam_size
    
        # -1 is the delimiter of generated sequences.
        # the first element of each generated sequence its length.
        start_pos, end_pos = 1, 0
        for i, sample in enumerate(gen_data):
            print(" ".join([src_dict[w] for w in sample[0][1:-1]]))
            for j in xrange(beam_size):
                end_pos = gen_sen_idx[i * beam_size + j]
                print("%.4f\t%s" % (beam_result[0][i][j], " ".join(
                    trg_dict[w] for w in beam_result[1][start_pos:end_pos])))
                start_pos = end_pos + 2
            print("\n")
    

生成開(kāi)始后,可以觀察到輸出的日志如下:

Les <unk> se <unk> au sujet de la largeur des sièges alors que de grosses commandes sont en jeu
-19.0196        The <unk> will be rotated about the width of the seats , while large orders are at stake . <e>
-19.1131        The <unk> will be rotated about the width of the seats , while large commands are at stake . <e>
-19.5129        The <unk> will be rotated about the width of the seats , while large commands are at play . <e>

總結(jié)

端到端的神經(jīng)網(wǎng)絡(luò)機(jī)器翻譯是近幾年興起的一種全新的機(jī)器翻譯方法。本章中,我們介紹了NMT中典型的“編碼器-解碼器”框架和“注意力”機(jī)制。由于NMT是一個(gè)典型的Seq2Seq(Sequence to Sequence,序列到序列)學(xué)習(xí)問(wèn)題,因此,Seq2Seq中的query改寫(xiě)(query rewriting)、摘要、單輪對(duì)話等問(wèn)題都可以用本教程的模型來(lái)解決。


    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶(hù)發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶(hù) 評(píng)論公約

    類(lèi)似文章 更多

    日韩欧美黄色一级视频| 美女被后入视频在线观看| 东京热电东京热一区二区三区| 久久机热频这里只精品| 欧美精品日韩精品一区| 亚洲国产综合久久天堂| 在线精品首页中文字幕亚洲| 精品一区二区三区不卡少妇av| 91欧美日韩精品在线| 视频在线免费观看你懂的| 最近最新中文字幕免费| 国产精品刮毛视频不卡| 又色又爽又无遮挡的视频| 亚洲综合日韩精品欧美综合区| 日韩成人中文字幕在线一区| 国产美女精品午夜福利视频| 国产日韩精品激情在线观看| 隔壁的日本人妻中文字幕版| 久久99精品国产麻豆婷婷洗澡| 国产精品成人一区二区在线| 真实偷拍一区二区免费视频| 久久成人国产欧美精品一区二区| 黄色av尤物白丝在线播放网址 | 日韩欧美精品一区二区三区| 高清免费在线不卡视频| 日韩偷拍精品一区二区三区| 国产剧情欧美日韩中文在线| 国产精品亚洲欧美一区麻豆| 日本精品视频一二三区| 美女被啪的视频在线观看| 精品欧美国产一二三区| 午夜视频免费观看成人| 加勒比系列一区二区在线观看 | 国产精品涩涩成人一区二区三区| 精品少妇人妻一区二区三区 | 亚洲视频在线观看你懂的| 国产精品白丝一区二区| 国产av一区二区三区久久不卡| 久久精视频免费视频观看| 亚洲国产av在线观看一区| 国产色偷丝袜麻豆亚洲|