神經(jīng)機(jī)器翻譯(seq2seq)教程(Neural Machine Translation (seq2seq) Tutorial)

原文:https://www.tensorflow.org/versions/r1.5/tutorials/seq2seq

(全文99.9%由google翻譯稼虎,自學(xué)使用)

作者:Thang Luong厨钻,Eugene Brevdo脆贵,Rui Zhao(Google Research Blogpost毁枯,Github)

本教程的這個(gè)版本需要TensorFlow Nightly磺陡。 為了使用穩(wěn)定的TensorFlow版本沼本,請考慮其他分支兢交,如tf-1.4薪捍。

如果使用這個(gè)代碼庫進(jìn)行研究,請引用此配喳。

介紹(Introduction)

序列 - 序列(seq2seq)模型(Sutskever et al., 2014, Cho et al., 2014
)在機(jī)器翻譯酪穿,語音識別和文本摘要等各種任務(wù)中取得了巨大的成功。 本教程為讀者提供了seq2seq模型的全面理解晴裹,并展示了如何從頭構(gòu)建一個(gè)有競爭力的seq2seq模型被济。 我們專注于神經(jīng)機(jī)器翻譯(NMT)的任務(wù),它是seq2seq模型的第一個(gè)測試平臺涧团。 包含的代碼是輕量級的只磷,高質(zhì)量的,生產(chǎn)就緒泌绣,并結(jié)合最新的研究思路钮追。 我們通過以下方式達(dá)到這個(gè):

  1. 使用最近的解碼器/注意力包裝器(decoder / attention wrapper)API,TensorFlow 1.2數(shù)據(jù)迭代器
  2. 結(jié)合我們強(qiáng)大的專業(yè)知識阿迈,建立循環(huán)和seq2seq模型
  3. 為建立最好的NMT模型和重現(xiàn)Google’s NMT (GNMT) 系統(tǒng)提供技巧和竅門元媚。

我們相信提供人們可以輕松重現(xiàn)的benchmarks是非常重要的。 因此苗沧,我們提供了完整的實(shí)驗(yàn)結(jié)果刊棕,并在以下公開可用的數(shù)據(jù)集上對模型進(jìn)行預(yù)訓(xùn)練:

  1. 小規(guī)模:IWSLT Evaluation Campaign提供的英語 - 越南語TED對話語料庫(133K個(gè)句子對)。
  2. 大規(guī)模:WMT Evaluation Campaign提供的德英平行語料庫(4.5M句子對)崎页。

我們首先建立一些關(guān)于NMT的seq2seq模型的基本知識鞠绰,解釋如何建立和訓(xùn)練一個(gè)vanilla NMT模型。 第二部分將著重于構(gòu)建具有注意力機(jī)制的競爭性NMT模型飒焦。 然后,我們將討論一些技巧和訣竅,以建立最佳NMT模型(包括速度和翻譯質(zhì)量)牺荠,如TensorFlow最佳實(shí)踐(批處理翁巍,分段),雙向RNN休雌,波束搜索(beam search [這個(gè)是啥灶壶?])以及使用GNMT注意力擴(kuò)展到多個(gè)GPU。

基礎(chǔ)知識(Basic)

神經(jīng)機(jī)器翻譯的背景(Background on Neural Machine Translation)

在過去杈曲,傳統(tǒng)的基于短語的翻譯系統(tǒng)通過將源語句拆分成多個(gè)片段然后將其逐句翻譯來執(zhí)行他們的任務(wù)驰凛。 這導(dǎo)致了翻譯產(chǎn)出的不流暢,并不像我們?nèi)祟惙g的那樣担扑。 我們閱讀整個(gè)源句子恰响,理解它的意思,然后產(chǎn)生一個(gè)翻譯涌献。 神經(jīng)機(jī)器翻譯(NMT)模仿的就是這種方式胚宦!


圖1.編碼器 - 解碼器架構(gòu) - 用于NMT的一般方法的例子。 編碼器將源語句轉(zhuǎn)換為通過解碼器傳遞的“意義”向量以產(chǎn)生翻譯燕垃。

具體而言枢劝,NMT系統(tǒng)首先使用編碼器讀取源句子來構(gòu)建“思想”向量,表示句子含義的數(shù)字序列; 解碼器然后處理句子向量以發(fā)出翻譯卜壕,如圖1所示您旁。這通常被稱為編碼器 - 解碼器體系結(jié)構(gòu)。 NMT以這種方式解決了傳統(tǒng)的基于短語的方法中的局部翻譯問題:它可以捕捉語言的長期依賴性轴捎,例如性別協(xié)議; 語法結(jié)構(gòu)等; 并通過谷歌神經(jīng)機(jī)器翻譯系統(tǒng)(Google Neural Machine Translation systems)展示了更流利的翻譯鹤盒。

NMT模型根據(jù)其確切的體系結(jié)構(gòu)而有所不同。 對于序列數(shù)據(jù)轮蜕,很自然的選擇是大多數(shù)NMT模型所使用的遞歸神經(jīng)網(wǎng)絡(luò)(RNN)昨悼。 編碼器和解碼器通常使用RNN。 但是跃洛,RNN模型在以下方面有所不同:(a)方向性 - 單向或雙向; (b)深度 - 單層或多層; 和(c)類型 - 通常是普通RNN率触,長期短期記憶(LSTM)或門控循環(huán)單元(GRU)。 有興趣的讀者可以在這篇博文中找到關(guān)于RNN和LSTM的更多信息汇竭。

在本教程中葱蝗,我們以單向的深度多層RNN為例,將LSTM作為一個(gè)遞歸單元细燎。 我們在圖2中展示了這樣模型的一個(gè)例子两曼。在這個(gè)例子中,我們建立了一個(gè)模型玻驻,將源句子"I am a student"翻譯成目標(biāo)句子"Je suisétudiant"悼凑。 在高層次上偿枕,NMT模型由兩個(gè)遞歸神經(jīng)網(wǎng)絡(luò)組成:編碼器RNN僅僅消耗輸入的源單詞而不作任何預(yù)測; 另一方面,解碼器在預(yù)測下一個(gè)單詞的同時(shí)處理目標(biāo)語句户辫。

欲了解更多信息渐夸,我們向讀者介紹本教程所基于的Luong (2016)

圖2.神經(jīng)機(jī)器翻譯 - 一個(gè)深度循環(huán)架構(gòu)的例子渔欢,將源句子“I am a student”翻譯成目標(biāo)句子“Je suistétudiant”墓塌。 這里,“<s>”表示解碼過程的開始奥额,而“</ s>”表示解碼器停止苫幢。

安裝教程(Installing the Tutorial)

要安裝本教程,您需要在系統(tǒng)上安裝TensorFlow垫挨。 本教程需要TensorFlow Nightly韩肝。 要安裝TensorFlow,請按照此處的安裝說明進(jìn)行操作棒拂。
一旦安裝了TensorFlow伞梯,您可以運(yùn)行以下命令來下載本教程的源代碼:

git clone https://github.com/tensorflow/nmt/

訓(xùn)練 - 如何建立我們的第一個(gè)NMT系統(tǒng)(Training – How to build our first NMT system)

首先,我們將深入探討用具體的代碼片斷構(gòu)建NMT模型的核心帚屉,我們將通過它更詳細(xì)地解釋圖2谜诫。 我們將數(shù)據(jù)準(zhǔn)備和完整的代碼推遲到以后。 這部分是指文件model.py攻旦。

在底層喻旷,編碼器和解碼器RNNs接收以下輸入:首先是源句子,然后是指示從編碼轉(zhuǎn)換到解碼模式的邊界標(biāo)記"<s>" 牢屋,和目標(biāo)語句且预。 對于訓(xùn)練,我們會給系統(tǒng)提供以下張量烙无,這些張量在時(shí)間上是主要格式锋谐,包含文字索引:

  • encoder_inputs [max_encoder_time,batch_size]:源輸入單詞截酷。
  • decoder_inputs [max_decoder_time涮拗,batch_size]:目標(biāo)輸入單詞。
  • decoder_outputs [max_decoder_time迂苛,batch_size]:目標(biāo)輸出單詞三热,這些是decoder_input向左移動(dòng)一個(gè)時(shí)間步,右邊添加一個(gè)句尾結(jié)束標(biāo)記三幻。
    這里為了提高效率就漾,我們一起訓(xùn)練多個(gè)句子(batch_size)媒抠。 測試稍有不同缩膝,所以我們稍后再討論拆魏。

嵌入(Embedding)

鑒于單詞的分類性質(zhì)咱娶,模型必須首先查找源和目標(biāo)的嵌入來檢索相應(yīng)的詞表示(word representations)叔汁。 為了使這個(gè)嵌入層起作用养葵,首先為每種語言選擇一個(gè)詞匯表蜒什。 通常拇泛,選擇詞匯量V荣倾,只有最頻繁的V詞才被視為唯一悯搔。 所有其他單詞都轉(zhuǎn)換為"unknown"標(biāo)記,并獲得相同的嵌入舌仍。 嵌入權(quán)重妒貌,每種語言一套,通常在訓(xùn)練中學(xué)習(xí)铸豁。

# Embedding
embedding_encoder = variable_scope.get_variable(
    "embedding_encoder", [src_vocab_size, embedding_size], ...)
# Look up embedding:
#   encoder_inputs: [max_time, batch_size]
#   encoder_emb_inp: [max_time, batch_size, embedding_size]
encoder_emb_inp = embedding_ops.embedding_lookup(
    embedding_encoder, encoder_inputs)

同樣灌曙,我們可以構(gòu)建embedding_decoder和decoder_emb_inp。 請注意节芥,可以選擇使用預(yù)訓(xùn)練詞表示(例如word2vec或Glove vectors)來初始化嵌入權(quán)重在刺。 一般來說,給定大量的訓(xùn)練數(shù)據(jù)头镊,我們可以從頭學(xué)習(xí)這些嵌入蚣驼。

編碼器(Encoder)

一旦檢索出來,嵌入字就作為輸入被輸入到主網(wǎng)絡(luò)中相艇,主網(wǎng)絡(luò)由兩個(gè)多層RNN組成 - 一個(gè)源語言的編碼器和一個(gè)目標(biāo)語言的解碼器颖杏。 這兩個(gè)RNN原則上可以分享相同的權(quán)重; 然而,在實(shí)踐中坛芽,我們經(jīng)常使用兩個(gè)不同的RNN參數(shù)(這些模型在擬合大型訓(xùn)練數(shù)據(jù)集時(shí)效果更好)留储。 編碼器RNN使用零矢量作為其起始狀態(tài),并且如下構(gòu)建:

# Build RNN cell
encoder_cell = tf.nn.rnn_cell.BasicLSTMCell(num_units)

# Run Dynamic RNN
#   encoder_outputs: [max_time, batch_size, num_units]
#   encoder_state: [batch_size, num_units]
encoder_outputs, encoder_state = tf.nn.dynamic_rnn(
    encoder_cell, encoder_emb_inp,
    sequence_length=source_sequence_length, time_major=True)

請注意咙轩,為避免浪費(fèi)計(jì)算获讳,句子具有不同的長度,我們通過source_sequence_length告訴dynamic_rnn確切的源句子長度活喊。 由于我們的輸入是時(shí)序重要的丐膝,我們設(shè)置time_major = True。 在這里胧弛,我們只建立一個(gè)單層的LSTM尤误,encoder_cell。 我們將介紹如何構(gòu)建多層LSTM结缚,添加dropout损晤,并在后面的章節(jié)中使用attention。

解碼器(Decoder)

解碼器也需要訪問源信息红竭,一個(gè)簡單的方法就是用編碼器的最后一個(gè)隱藏狀態(tài)encoder_state來初始化它尤勋。 在圖2中喘落,我們將源語詞“student”的隱藏狀態(tài)傳遞給解碼器端。

# Build RNN cell
decoder_cell = tf.nn.rnn_cell.BasicLSTMCell(num_units)
# Helper
helper = tf.contrib.seq2seq.TrainingHelper(
    decoder_emb_inp, decoder_lengths, time_major=True)
# Decoder
decoder = tf.contrib.seq2seq.BasicDecoder(
    decoder_cell, helper, encoder_state,
    output_layer=projection_layer)
# Dynamic decoding
outputs, _ = tf.contrib.seq2seq.dynamic_decode(decoder, ...)
logits = outputs.rnn_output

在這里最冰,這個(gè)代碼的核心部分是BasicDecoder對象瘦棋、解碼器,其接收decoder_cell(類似于encoder_cell)暖哨,幫助器赌朋,以及之前的encoder_state作為輸入。 通過分離出解碼器和幫助器篇裁,我們可以重用不同的代碼庫沛慢,例如,可以用GreedyEmbeddingHelper代替TrainingHelper來進(jìn)行貪婪的解碼达布。 請參閱helper.py团甲。

最后,我們沒有提到projection_layer是一個(gè)稠密的矩陣黍聂,它將頂部隱藏狀態(tài)轉(zhuǎn)化為維數(shù)為V的logit向量躺苦。我們在圖2的頂部說明了這個(gè)過程。

projection_layer = layers_core.Dense(
    tgt_vocab_size, use_bias=False)

損失(Loss)

基于上面的logits产还,我們現(xiàn)在準(zhǔn)備計(jì)算我們的訓(xùn)練損失:

crossent = tf.nn.sparse_softmax_cross_entropy_with_logits(
    labels=decoder_outputs, logits=logits)
train_loss = (tf.reduce_sum(crossent * target_weights) /
    batch_size)

這里匹厘,target_weights是與decoder_outputs相同大小的0-1矩陣。 它將目標(biāo)序列長度之外的值填充0雕沉。

重要說明:值得指出的是集乔,我們用batch_size來分割損失,所以我們的超參數(shù)對batch_size是“不變的”坡椒。 有些人用(batch_size * num_time_steps)來劃分損失扰路,減少了短句的錯(cuò)誤。 更微妙的是倔叼,我們的超參數(shù)(應(yīng)用于前一種方式)不能用于后一種方式汗唱。 例如,如果兩種方法都使用SGD來學(xué)習(xí)1.0丈攒,則后一種方法有效地使用1 / num_time_steps的更小的學(xué)習(xí)速率哩罪。

梯度計(jì)算和優(yōu)化(Gradient computation & optimization)

現(xiàn)在我們已經(jīng)定義了NMT模型的正向傳播。 計(jì)算反向傳播只是幾行代碼的問題:

# Calculate and clip gradients
params = tf.trainable_variables()
gradients = tf.gradients(train_loss, params)
clipped_gradients, _ = tf.clip_by_global_norm(
    gradients, max_gradient_norm)

訓(xùn)練RNNs的重要步驟之一是梯度裁剪巡验。 在這里际插,我們在全局范圍內(nèi)進(jìn)行裁剪。 最大值max_gradient_norm通常設(shè)置為5或1的值显设。最后一步是選擇優(yōu)化器框弛。 Adam優(yōu)化器是一個(gè)常用的選擇。 我們也選擇一個(gè)學(xué)習(xí)率捕捂。 learning_rate的值通成悖可以在0.0001到0.001之間; 隨著訓(xùn)練的進(jìn)行可以減少斗搞。

# Optimization
optimizer = tf.train.AdamOptimizer(learning_rate)
update_step = optimizer.apply_gradients(
    zip(clipped_gradients, params))

在我們自己的實(shí)驗(yàn)中,我們使用標(biāo)準(zhǔn)SGD(tf.train.GradientDescentOptimizer)慷妙,其學(xué)習(xí)速率逐步降低僻焚,這樣可以獲得更好的性能。 參見 benchmarks膝擂。

未完待續(xù)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虑啤,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子猿挚,更是在濱河造成了極大的恐慌咐旧,老刑警劉巖,帶你破解...
    沈念sama閱讀 211,496評論 6 491
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件绩蜻,死亡現(xiàn)場離奇詭異,居然都是意外死亡室埋,警方通過查閱死者的電腦和手機(jī)办绝,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,187評論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來姚淆,“玉大人孕蝉,你說我怎么就攤上這事‰绶辏” “怎么了降淮?”我有些...
    開封第一講書人閱讀 157,091評論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長搏讶。 經(jīng)常有香客問我佳鳖,道長,這世上最難降的妖魔是什么媒惕? 我笑而不...
    開封第一講書人閱讀 56,458評論 1 283
  • 正文 為了忘掉前任系吩,我火速辦了婚禮,結(jié)果婚禮上妒蔚,老公的妹妹穿的比我還像新娘穿挨。我一直安慰自己,他們只是感情好肴盏,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,542評論 6 385
  • 文/花漫 我一把揭開白布科盛。 她就那樣靜靜地躺著,像睡著了一般菜皂。 火紅的嫁衣襯著肌膚如雪贞绵。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,802評論 1 290
  • 那天幌墓,我揣著相機(jī)與錄音但壮,去河邊找鬼冀泻。 笑死,一個(gè)胖子當(dāng)著我的面吹牛蜡饵,可吹牛的內(nèi)容都是我干的弹渔。 我是一名探鬼主播,決...
    沈念sama閱讀 38,945評論 3 407
  • 文/蒼蘭香墨 我猛地睜開眼溯祸,長吁一口氣:“原來是場噩夢啊……” “哼肢专!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起焦辅,我...
    開封第一講書人閱讀 37,709評論 0 266
  • 序言:老撾萬榮一對情侶失蹤博杖,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后筷登,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體剃根,經(jīng)...
    沈念sama閱讀 44,158評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,502評論 2 327
  • 正文 我和宋清朗相戀三年前方,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了狈醉。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,637評論 1 340
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡惠险,死狀恐怖苗傅,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情班巩,我是刑警寧澤渣慕,帶...
    沈念sama閱讀 34,300評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站抱慌,受9級特大地震影響逊桦,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜遥缕,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,911評論 3 313
  • 文/蒙蒙 一卫袒、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧单匣,春花似錦夕凝、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,744評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至鸡号,卻和暖如春转砖,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,982評論 1 266
  • 我被黑心中介騙來泰國打工府蔗, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留晋控,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 46,344評論 2 360
  • 正文 我出身青樓姓赤,卻偏偏與公主長得像赡译,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子不铆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,500評論 2 348