如何在 Keras 中從零開始開發一個神經機器翻譯系統?
機器翻譯是一項具有挑戰性的任務,包含一些使用高度複雜的語言知識開發的大型統計模型。
神經機器翻譯的工作原理是——利用深層神經網路來解決機器翻譯問題。
在本教程中,你將了解如何開發一個神經機器翻譯系統,可以用於將德語翻譯成英語。
學習完本教程後,你將知道:
如何清理和準備數據來訓練神經機器翻譯系統
如何開發機器翻譯的編碼器 - 解碼器模型
如何使用訓練有素的模型對新輸入短語進行推理,並對模型技巧進行評價
讓我們開始吧。
如何在 Keras 開發神經機器翻譯系統 照片由 Bj?rn Gro? 提供
教程概述
教程分為 4 個部分:
德語翻譯成英語的數據集
準備文本數據
訓練神經翻譯模型
評估神經翻譯模型
Python 環境
本教程預設你安裝了Python 3 SciPy環境。
你必須安裝帶有TensorFlow或Theano後端的Keras(2.0 或更高版本)。
本教程還假定你已經安裝了NumPy和Matplotlib。
關於安裝環境,如需要幫助,請看這篇文章:
How to Setup a Python Environment for Machine Learning and Deep Learning with Anaconda(http://t.cn/R87zlIb)
德語翻譯成英語的數據集
在本教程中,我們將使用德語譯成英語的數據集作為語言學習的抽認卡的基礎。
數據集可以從 ManyThings.org(http://www.manythings.org/) 網站獲得,案例是從 Tatoeba Project(http://tatoeba.org/home) 項目中提取出來的。該數據集由德語短語和英語單片語成,我們使用的是 Anki flashcard software(https://apps.ankiweb.net/) 軟體。
該頁面提供了許多語言對的列表,我鼓勵你探索其他語言:
Tab-delimited Bilingual Sentence Pairs(http://www.manythings.org/anki/)
本教程中使用的數據集可以在這裡下載:
German – English deu-eng.zip(http://www.manythings.org/anki/deu-eng.zip)
將數據集下載到當前工作目錄並解壓;例如:
你會有一個叫deu.txt的文件。txt 中包含 152,820 對德語階段的英語,每一行有一行,並有一個標籤分隔語言。
例如,文件的前 5 行看起來如下:
我們使用德語詞句序列作為輸入,將其翻譯成英語的的詞句序列,這就是我們的預測問題。
這個開發的模型將適用於一些初學者級別的德語短語。
準備文本數據
下一步是準備用於建模的文本數據。
先查看原始數據,請注意,你所有看到的內容,很可能就是我們在數據清洗過程中所需要用到的。
例如,在我回顧原始數據時,請注意到以下幾點:
有標點符號。
文本包含大寫和小寫。
在德語中有一些特殊的字元。
英語中有重複的短語,有不同的德語翻譯。
這個文件是按句子長度排序的,在文件的末尾有很長的句子。
一個好的文本清理程序可以處理一些或全部的這些問題。
數據準備分為兩部分:
清理文檔
分離文檔
1. 清理文檔
首先,我們必須以保存 Unicode 德語字元的方式載入數據。下面的函數名為load_doc(),它將把文件載入為一個文本blob。
每行包含一對短語,先是英語,然後是德語,然後用製表符分隔。
我們必須逐行拆分已載入的文本。函數to_pairs()將分割載入的文本。
我們現在準備好清理每個句子。我們將執行的具體清理操作如下:
刪除所有非輸出字元。
刪除所有標點字元。
將所有 Unicode 字元規範化為 ASCII(如拉丁字元)。
將案例規範化為小寫。
刪除所有不按字母順序排列的令牌。
我們將在載入的數據集中對每一對語句執行這些操作。
clean_pairs()函數執行這些操作。
最後,既然數據已經被清理,我們可以將短語對列表保存到準備使用的文件中。
函數save_clean_data()使用pickle API將清理文本列表保存到文件中。
將所有這些組合在一起,下面列出了完整的示例。
運行該示例將在當前工作目錄中創建一個名為 「english-german.pkl」 的清理文本。
一些清理文本的例子被列印出來,以便我們在運行結束時進行評估,以確認清理的操作是按預期執行的。
2. 分離文本
清理的數據包含了超過 15 萬個短語對,而其中的一些對到文件的結尾是很長的。
這是一個很好的例子來開發一個小的翻譯模型。 模型的複雜性隨著實例數量、短語長度和辭彙量的增加而增加。
雖然我們有一個良好的數據集來進行建模,但是我們會稍微簡化這個問題,以極大地減少模型所需的模型的大小,並將所需的訓練時間轉換成適合模型的時間。
你可以在更完整的數據集上開發一個模型作為擴展。我們將通過將數據集減少到文件中的前 10,000 個示例來簡化問題;這些將是數據集中最短的短語。
此外,我們將把前 9000 個例子作為培訓的示例和剩下的 1,000 個例子來測試 fit 模型。
下面是一個完整的示例,它載入乾淨的數據,拆分它,並將數據的分割部分保存到新文件中。
運行這個例子創建了三個新文件:english-german-both.pkl它包含了我們可以用來定義問題參數的所有用於訓練和測試例子,例如 max 短語長度和辭彙表,以及english-german-train.pkl和english-german-test.pkl文件。用於訓練和測試數據集的 pkl 文件。
現在我們已經準備好開發翻譯模型。
訓練神經翻譯模型
在這部分中,我們會來建立翻譯模型。
這部分包含了載入和準備好清洗好的文本數據給模型,然後在這些數據上定義和訓練該模型。
讓我們開始載入數據集,以便於準備數據。下面的函數:load_clean_sentences()用於載入訓練的數據集,反過來也可以載入測試的數據集。
我們會使用或者結合訓練,測試數據集定義了對最大長度和問題的辭彙量。
這挺簡單。我們能夠從單獨的數據集中定義這些屬性,然後在測試集中截斷太長或者是超過辭彙量的例子。
我們使用Keras Tokenize類去講辭彙映射成數值,如建模所需要的。我們會使用分離標記生成器給英語序列和德文序列,下面這個函數是create_tokenizer()會訓練在一列短語中的標記生成器。
同樣地,max_length()函數會找在一列單詞中最長的序列。
我們可以調用這些函數結合數據集來準備標記生成器,辭彙大小和最大的長度,英文和德文短語。
現在我們準備開始訓練數據集。
每個輸入輸出序列都必須編碼成數值,並填充為最大的辭彙長度。
這是因為,我們要使用一個嵌入的單詞給輸出序列,並對輸出序列進行熱編碼。下面這個函數為:encode_sequences()能執行這些操作,並返回結果。
輸出序列需要一次熱編碼。這是應為模型會預測每個辭彙的可能性作為輸出。
函數encode_output()會熱編碼英文到輸出序列中。
我們可以使用這兩個函數準備訓練和測試數據集給訓練模型。
現在可以開始定義模型了。
在這個問題上,我們使用了編碼 - 解碼器LSTM模型。在這個架構中,輸出序列是一個前端模型編碼器編碼好的序列,後端模型稱為解碼器,會一個辭彙一個辭彙地進行解碼。
函數define_model()定義了模型,用了一些參數來設置模型,比如說輸入輸出的辭彙量大小,和輸入輸出的最大辭彙長度,和最大數量的內存單元。
這個模型設置在這問題不是最優的,這意味你有很多的潛力來調整它,提高翻譯的技巧。
最後,我們開始訓練模型。
我們在批大小(batch size)大小為 64 的情況下在所有樣本數據集上完成 30 次訓練迭代
我們使用檢查點來確保每次在測試集中,模型技能提高時,模型都被保存到文件中。
我們可以將所有這些結合在一起,並適用於神經翻譯模型。
下面列出了完整的工作示例。
首先運行示例列印數據集的參數摘要,例如辭彙大小和最大短語長度。
接下來,列印定義的模型的摘要,允許我們確認模型配置。
該模型的圖也被創建,提供了關於模型配置的另一個視角。
接下來,我們開始訓練模型。
現代 CPU 硬體每個時代大約需要 30 秒;不需要 GPU。
在運行過程中,模型將被保存到文件model.h5中,準備在下一步中進行推理。
評估神經網路翻譯模型
我們會評估訓練和測試數據集。
該模型應該在訓練數據集上表現得非常好,理想的情況是已經推廣到在測試數據集上表現良好。
理想情況下,我們將使用單獨的驗證數據集來幫助選擇訓練期間的模型而不是測試集。你可以試試這個作為擴展。
清洗好的的數據集必須像之前一樣載入和準備。
接下來,訓練期間保存的最佳模型必須載入。
評估包含了兩個步驟:首先生成翻譯的輸出序列,然後重複這個過程中的許多輸入的例子,總結模型的技巧在多個案例。
從推論開始,模型可以以一次性的方式預測整個輸出序列。
這是一系列整數,我們可以枚舉並在標記器中查找以映射回單詞。
下面這個函數word_for_id(),將執行這個反向映射:
我們可以對翻譯中的每個整數執行此映射,並將結果作為一串單詞來返回。 下面的函數predict_sequence()對單個編碼的源短語執行此操作。
接下來,我們可以對數據集中的每個源短語重複此操作,並將預測結果與英文中的預期目標短語進行比較。
我們可以在屏幕中列印一些對比結果,來篩選模型在實踐中的表現。
我們還將計算 BLEU 得分,以獲得模型表現如何的定量概念。
evaluate_model()函數實現了這個內容,為提供的數據集中的每個短語調用上述predict_sequence()函數。
我們可以將所有這些結合在一起,並在訓練和測試數據集上評估載入的模型。
下面提供了完整的代碼展示。
首先運行示例列印源文本,期望和預測翻譯的示例,以及訓練數據集的分數,然後列印測試數據集。
考慮到數據集的隨機洗牌和神經網路的隨機性,你的具體結果將有所不同。
首先查看測試數據集的結果,我們可以看到這些翻譯是可讀的並且大部分是正確的。
比如: 「ich liebe dich」 正確地翻譯為 「i love you「
我們還可以看到 BLEU-4 得分為 0.51,這提供了我們對這個模型可能期望的上限。
看看測試集的結果,看看可讀的翻譯,這不是一件容易的事情。
比如說,我們看到 「ich mag dich nicht」 翻譯成 「我不喜歡你」。
我們也看到一些糟糕的翻譯和一個很好的例子,模型可能會受到進一步的調整,比如說 「ich bin etwas beschwipst」 翻譯成 「我有一點點」 而不是預想的 「我有點醉了」
BLEU-4 得分為 0.076238,提供了一個基本的技能來進一步改進模型。
拓展
本節列出了一些您可能希望拓展討論的想法。
數據清洗。可以對數據執行不同的數據清理操作,例如不去除標點符號或規範化大小寫,或者刪除重複的英語短語。
辭彙表。可以對辭彙表進行細化,或者刪除在數據集中使用少於 5 次或 10 次的單詞,替換為 「unk」。
更多的數據。用於擬合模型的數據集可以擴展到 50,000,100,000 個短語或更多。
輸入順序。輸入短語的順序可以顛倒,這已經有相關報告表明能為提升能力,或者可以使用雙向輸入層。
層數。編碼器和解碼器模型可以用附加層進行擴展,並進行更多的訓練迭代,從而為模型提供更多的表徵能力。
存儲單元。編碼器和解碼器中的存儲器單元數量可以增加,為模型提供更多的表徵能力。
正則。該模型可以使用正則化,如權重或激活正則化,或在 LSTM 層使用丟棄。
預訓練的詞向量。預先訓練的單詞向量可以在模型中使用
遞歸模型。可以使用該模型的遞歸公式,其中輸出序列中的下一個單詞可以以輸入序列和到目前為止產生的輸出序列為條件。
※谷歌 2018 技術實習生正式開放申請!還有這些 AI 職位虛左以待!
TAG:AI研習社 |