馬爾可夫鏈文本生成的簡單應用:不足20行的Python代碼生成雞湯文

提到自然語言的生成時,人們通常認為要會使用高級數學來思考先進的AI系統,然而,並不一定要這樣。在這篇文章中,我將使用馬爾可夫鏈和一個小的語錄數據集來產生新的語錄。

馬爾可夫鏈

馬爾可夫鏈是一個只根據先前事件來預測事件的隨機模型。舉一個簡單的例子:我的貓可能的狀態變化。我有一隻貓,它一般都是在吃、睡或者玩。它大多時間在睡覺。不過,她偶爾會醒來吃點東西。通常情況下,吃完以後,她會變得很活潑,開始玩玩具,然後她要麼回去睡覺,要麼再次吃東西(我想他家的貓可能是橘色的)。

我的貓的狀態可以很容易地用馬爾可夫鏈建模,因為它決定接下來做什麼,取決於它以前的狀態。它不太可能醒來後馬上開始玩,但在她吃完貓糧之後就很有可能開始玩。這些狀態轉換也可以用狀態轉換圖說明:

每個圓圈代表一個狀態,箭頭指向下一個狀態,每個箭頭旁邊的數字是從一個狀態轉換到另一個狀態的概率。正如你所看到的,狀態轉變的幾率完全基於以前的狀態。

馬爾可夫鏈的文本生成

馬爾可夫鏈文本生成的思想與此相同,即試圖找出某個詞出現在另一個詞之後的概率。為了確定轉換的概率,我們用一些例句來訓練模型。

打個比方,我們可以用下面的句子來訓練一個模型。

I like to eat apples.

You eat oranges.

只從訓練數據中我們可以得出的結論是,「I」,「like」,「to」和「eat」都是這種順序,而「you」和「eat」也總是在一起。然而,在「eat」這個詞之後出現「oranges」或「apples」的概率是相等的。轉換圖如下:

這兩個訓練句子只能夠產生兩個新的句子。接下來,我用下面的四個句子訓練了另一個模型。

my friend makes the best raspberry pies in town

i think apple pies are the best pies

steve thinks apple makes the best computers in the world

I own two computers and they』re not apple because I am not steve or rich

由四個句子訓練的模型,它的轉換圖要比兩個大得多。

即使這個圖與典型的馬爾可夫鏈轉換圖看起來差異很大,但其背後的主要思想是一樣的。路徑從「START」節點開始,按概率選取下列單詞直到結束節點。選取單詞的概率用連接的粗細表示。

上面的模型能夠產生數百個獨特的句子,即使是只有四個句子的訓練。

代碼

生成器的代碼非常簡單,除了python的random模塊外,不需要其他額外的模塊或庫。它由兩部分組成,一部分用於訓練,另一部分用於生成。

訓練

訓練代碼構建了我們稍後用於生成句子的模型。我用字典(給定句子的所有單詞)作為模型; 以單詞作為關鍵幀,並將選取下個單詞的概率列表作為相應的值。例如,前兩行已經訓練過的模型的字典:「I like to eat oranges」,「You eat apples」如下:

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

我們不需要計算下一個單詞出現的概率,因為如果它們出現的概率較大,那麼他們會在選取下個單詞的列表中出現好幾次。例如,如果我們加上「we eat apples」這個額外的訓練語句,「eat」這個詞之後的兩個句子出現「apples」這個詞,因此有更高的概率。這個更高的概率通過在「eat」的列表中出現兩次的方式插入模型字典。

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

此外,在上面的模型字典中還有兩個附加項,「START」和「END」,它們表示生成的句子的開始和結束詞。

1for linein dataset_file:

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

3 for i, wordin enumerate(line):

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

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

6 else:

7 if i== 0:

8 model[START]= model.get(START, [])+ [word]

9 model[word]= model.get(word, [])+ [line[i+1]]

生成

生成器部分由一個循環組成。它首先選擇一個隨機的啟動詞,並將其附加到一個列表。然後在字典中搜索它下一個可能的單詞列表,隨機選取其中一個單詞,將新選擇的單詞附加到列表中。它繼續在可能性的列表中隨機選擇下一個單詞,重複此過程直到它到達結束詞,然後停止循環,並輸出生成的單詞序列或者說雞湯。

01import random

02

03generated= []

04while True:

05 if not generated:

06 words= model[START]

07 elif generated[-1]in model[END]:

08 break

09 else:

10 words= model[generated[-1]]

11 generated.append(random.choice(words))

我現在使用馬爾可夫鏈生成的是雞湯文。當它們作為文本生成器時,你可以提供任何輸入,它會按你提供的輸入生成類似的文本。

「Don』t think of the overwhelming majority of the impossible.」

「Grew up your bliss and the world.」

「what we would end create, creates the ground and you are the one to warm it」

「look and give up in miracles」

以上引用框中所有的句子都是由計算機生成的,使用的程序python代碼不足20行。

馬爾可夫鏈文本生成器也可以混合不同類型的文本。例如,在我最喜歡的電視節目之一Rick and Morty中,有一個叫Abradolf Lincler的人物,他是林肯和希特勒的混合體。如果你對此感興趣,同樣可以通過將兩位領導人的演講作為訓練數據提供給馬爾可夫鏈文本生成器來生成混合體會說的內容。

Abradolf Linclerrickandmorty.wikia.com圖標

本文為atyun出品,轉載請註明出處。更多內容關注微信公眾號atyun_com;訪問網站atyun.com;或加資源群:213252181


推薦閱讀:

如何評價《python web開發實戰》?
pandas筆記(一)——入門
anaconda中如何安裝keras?
Python3 CookBook | 日期和時間
哪些技術讓你有一種 「Orz, 還有這種操作」 ?

TAG:Python | 馬爾可夫 | 文本 |