如何用簡易程式碼自動生成經典語錄

weixin_34293059發表於2018-01-08
2509688-66eeee75972406f2.png

                           不要空想不可能的事情”

                            “增加自己的幸福感”

                            “我們最終將創造地面,並呵護它”

                            “保持希望並學會放棄奇蹟”

上面所有引號內的句子都是由一段程式碼生成的,使用的程式由少於20行的python程式碼組成。

當涉及到生成自然語言時,人們通常會想到使用高階數學的高階人工智慧系統,然而,這並不總是正確的。在本文中,我將使用馬爾科夫鏈和一個雞湯語錄資料集來生成新的雞湯文字。

馬爾科夫鏈

馬爾可夫鏈是一種僅基於前一事件來預測下一事件的隨機模型。拿貓咪的狀態切換來簡單舉例:我有一隻貓咪,她不是吃、睡覺就是在玩玩具。雖然她大部分時間是睡覺,不過偶爾會醒來吃點東西,通常情況下她吃完東西后會精力特別旺盛的玩玩具,之後繼續回去睡覺或者接著吃東西。

我家貓咪的狀態可以很容易地用馬爾可夫鏈建模,因為她根據她以前的狀態決定接下來做什麼。她不太可能醒來後馬上玩玩具,但是飯後非常可能。這些狀態轉換也可以在狀態轉換圖中進行說明。

2509688-914bdcf6b7312e6a.png

每個圓圈都是一個狀態,箭頭指向下一個狀態,每個箭頭旁邊的數字是由一個狀態轉換到另一個狀態的概率。正如您所看到的,轉換的概率完全基於之前的狀態。

使用馬爾科夫鏈生成文字

使用馬爾科夫鏈生成文字運用了相同的想法,並嘗試計算出一個詞在另一個詞之後出現的概率。 為了確定轉換的概率,我們用一些語句例子來訓練模型。例如:

我喜歡吃蘋果。

你吃橘子。

僅從這些訓練資料我們可以得出結論,“我”、“喜歡”和“吃”總是保持這樣的排列順序,而且“你”和“吃”總放一起;然而,“橘子”或者“蘋果”出現在“吃”後面的機率是一樣的。下面的轉換圖能更好的闡述我所說的。

2509688-5b4bcab06b9c3eff.png

這兩個訓練句子能夠生成兩個新的語句,但是情況並非總是如此。我用下面的4個句子訓練了另一個模型,然而結果非常不同。

我的朋友在鎮上做最好吃的覆盆子派。

我認為蘋果派是最好吃的派。

史蒂夫認為蘋果是世界上最好的電腦。

我有兩臺電腦,但都不是蘋果電腦,因為我既不是史蒂夫也不富裕。

由這四句話訓練的模型的轉換圖要大得多了。

2509688-c8e578ebdb9205f1.png

儘管該圖看上去與典型的馬爾科夫鏈轉換圖非常不同,但其背後的主要思想是相同的。路徑從“開始”節點開始,隨機選擇下個單詞直到“結束”節點。每個單詞的概率由連線的寬度表示。

即使只訓練了四個句子,這個模型也可以生成上百個不同的句子。

2509688-45454100a43fb0ae.png

程式碼

生成器的程式碼非常簡單,除了Python的隨機模組之外,不需要任何額外的模組或庫。它由兩部分組成,一部分是訓練,另一部分是生成。

訓練

這些訓練程式碼構造了我們稍後將用來生成語錄的模型。我把一個字典作為模型;它裡面的單詞作為關鍵字,並把潛在的後面的單詞作為列表裡對應的值。例如,前兩行訓練過的模型的字典:“我喜歡吃桔子”,“你吃蘋果”看起來像下面這樣:

{'START': ['i', 'you'], 'i': ['like'], 'like': ['to'], 'to': ['eat'], 'you': ['eat'], 'eat': ['apples', 'oranges'], 'END': ['apples', 'oranges']}

我們不需要計算下一個單詞出現的概率,因為如果它們出現的概率更高,那麼它們將會在潛在的單詞列表中出現好幾次。例如,如果我們新增額外的訓練語句“我們吃蘋果”,那麼“蘋果”一詞就出現在“吃”的後面兩次,因此概率更高。模型字典中就出現了更高的概率。

{'START': ['i', 'we', 'you'], 'i': ['like'], 'like': ['to'], 'to': ['eat'], 'you': ['eat'], 'we': ['eat'], 'eat': ['apples', 'oranges', 'apples'], 'END': ['apples', 'oranges', 'apples']}

此外,在上面的模型字典中還有兩個額外的項,“START”和“END”,它們表示生成的句子或語錄的開始詞和結束詞。

1 for linein dataset_file:

2 line = line.lower().split()

3for i, wordin enumerate(line):

4 if i== len(line)-1:

5model['END'] = model.get('END', []) + [word

6 else:

7 if i== 0: 

生成

生成器由一個迴圈組成。它開始隨機的選擇一個開始詞並新增到一個列表中,之後在字典中搜尋包含潛在的下個單詞的列表,並隨機選擇一個新增到上個列表,它會繼續選擇潛在的下個單詞直到碰到結束詞,之後停止迴圈,並輸出生成的單詞序列或者“語錄”。

1import random 

2

3generated = []

4 while True:

5 if not generated:

6 words = model['START']

7 elif generated[-1]in model['END']:

8 break

我已經使用馬爾科夫鏈生成了語錄,當它作為文字生成器應用到應用程式時,可以提供任意的輸入,並將會生成相似的文字。

使用馬爾可夫鏈文字生成器還可以做的另一件很酷的事情,那就是混合不同型別的文字。 比如在我最喜歡的電視節目瑞克和莫蒂中,有一個叫阿布拉多夫·林肯的人物,他是亞伯拉罕·林肯和阿道夫·希特勒的混合體。你可以通過將兩位領導人的演講作為馬爾可夫鏈文字生成器的訓練資料,從而實現了這個人物。馬爾可夫鏈是一種令人難以置信的東西,它在所有的應用程式中都有大量的應用。文字生成並不是它最有用的應用程式,但我認為必須是最有趣的應用之一。

本文由阿里云云棲社群組織翻譯。

文章原標題《How I generated inspirational quotes with less than 20 lines of python code》

作者:Ramtin Alami

譯者:奧特曼,審校:袁虎。

相關文章