馬爾可夫鏈是一個隨機過程,在這個過程中,我們假設前一個或前幾個狀態對預測下一個狀態起決定性作用。和拋硬幣不同,這些事件之間不是相互獨立的。通過一個例子更容易理解。
想象一下天氣只能是下雨天或者晴天。也就是說,狀態空間是雨天或者晴天。我們可以將馬爾可夫模型表示為一個轉移矩陣,矩陣的每一行代表一個狀態,每一列代表該狀態轉移到另外一個狀態的概率。
然而,通過這個狀態轉移示意圖更容易理解。
換句話說,假如今天是晴天,那麼有90%的概率明天也是晴天,有10%的概率明天是下雨天。
文章生成器
馬爾可夫模型有個很酷的應用是一種語言模型,在這個模型中,我們根據當前的一個或幾個詞預測下一個詞是什麼。如果我們只是根據上一個詞預測,則它是一個一階馬爾可夫模型。如果我們用上兩個詞預測,則它是一個二階馬爾可夫模型。
在我的例項中,我使用Henry Thoreau的小說Walden做訓練。為了好做實驗,我也加入了Nietszche的Thus Spoke Zarathustra,以及一些Obama的演講。無論你訓練什麼樣的文字,模型都會生成相似的結果,是不是很酷?
首先我們引入NLTK,它是Python中最好的NLP庫。我想說,雖然我們這裡做的自然語言處理很簡單,但NLTK的內建函式還是幫我節省了很多程式碼。然後我們利用split()函式將字串(從文字檔案中獲得的)轉換成一個陣列。
1 2 3 4 5 |
import nltk import random file = open('Text/Walden.txt', 'r') walden = file.read() walden = walden.split() |
上邊兩個函式是程式碼的基本函式。我們最終要使用的NLTK中的“條件頻率字典”必須以成對陣列作為輸入,所以短語“Hi my name is Alex”需要變為[(“Hi”, “my”), (“my, “name”), (“name”, “is”), (“is”, “Alex”)]。函式makePairs以一個陣列(以詞分割字串得到)作為輸入,輸出符合上邊格式的陣列。
生成文章的方法,需要一個條件頻率分佈作為輸入。想想看,“農場”的後邊每一個詞出現的次數是多少?這是一個“條件頻率分佈”的輸出(對於所有的詞,而不只是“農場”)。生成函式的其餘部分是根據訓練資料中觀察到的分佈輸出文字。我通過建立一個出現在當前詞後邊的每一個片語成的陣列實現這一點。陣列中也有正確的計數,因此,接下來我只需要隨機選擇陣列中的一個詞即可,而這個過程也是服從分佈的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
def makePairs(arr): pairs = [] for i in range(len(arr)): if i < len(arr)-1: temp = (arr[i], arr[i+1]) pairs.append(temp) return pairs def generate(cfd, word = 'the', num = 50): for i in range(num): arr = [] # make an array with the words shown by proper count for j in cfd[word]: for k in range(cfd[word][j]): arr.append(j) print(word, end=' ') word = arr[int((len(arr))*random.random())] |
最後三行程式碼,我們輸出了一些很像Walden風格的文字。
1 2 3 |
pairs = makePairs(walden) cfd = nltk.ConditionalFreqDist(pairs) generate(cfd) |
輸出結果:
我建議你看一下我Github上的iPython筆記,因為我繼續完成了一個方法。利用這個方法,你只需要輸入一個檔名,它就能輸出生成的文字。Obama的例子也非常的酷。
如果你想自己嘗試一下,只需要建立一個文字檔案,然後把它放在合適的目錄即可。
打賞支援我翻譯更多好文章,謝謝!
打賞譯者
打賞支援我翻譯更多好文章,謝謝!