python自然語言處理-馬爾科夫模型
阿新 • • 發佈:2018-12-24
1.概念學習
馬爾科夫模型常用於分析大量隨機事件,隨機事件的特點是一個離散事件發生之後,另一個離散事件將在前一個事件的條件下以一定的概率發生。以天氣的馬爾科夫模型為例:
在這個天氣系統模型中,如果今天是晴天,那麼明天有70%的可能是晴天,20%的可能是多雲,10%的可能下雨。如果今天是下雨天,那麼明天有50%的可能也下雨,25%的可能是晴天,25%的可能是多雲。
需要注意以下幾點:
- 任何一個節點引出的所有可能的總和必須等於100%。無論是多麼複雜的系統,必然會在下一步發生若干事件中的一個事件;
- 雖然這個天氣系統在任一時間都只有三種可能,但是你可以用這個模型生成一個天氣狀態的無限次轉移列表;
- 只有當前節點的狀態會影響後一天的狀態。如果你在“晴天”節點上,即使前100天都是晴天或雨天都沒有關係,明天晴天的概率還是70%;
- 有些節點可能比其他節點較難到達,這個現象的原因用數學來解釋非常複雜,但是可以直觀地看出,在這個系統中任意時間節點上,第二天是“雨天”的可能性(指向它的箭頭概率之後下雨100%),比“晴天”和“多雲”要小很多
2. 實戰演練
繼續前面的總統演講的例項,分析一個具體的例項:文字分析與寫作,通過演講內容的結構生成任意長度的(下面的示例中長為100)馬爾科夫鏈組成的句子:對這段程式碼進行分析,buildWordDict函式把網上的演講文字字串作為引數,然後對字串做一些清理和格式化處理,去掉引號,把其他標點符號兩端加上空格,這樣就可以對每一個單詞進行有效的處理。最後,再建立如下所示的二維字典-字典裡有字典:from urllib.request import urlopen from random import randint def wordListSum(wordList): sum=0 for word,value in wordList.items(): sum+=value return sum def retrieveRandomWord(wordList): randIndex=randint(1,wordListSum(wordList)) for word,value in wordList.items(): randIndex-=value if randIndex<0: return word def buildWordDict(text): #剔除換行符和引號 text=text.replace("\n"," ") text=text.replace("\"","") text=text.replace("--","") #保證每個標點符號都和前面的單詞在一起 #這樣不會被剔除,保留在馬爾科夫鏈中 punctuation=[',','.',';',':'] for symbol in punctuation: text=text.replace(symbol," "+symbol+" ") words=text.split(" ") #過濾空單詞 words=[word for word in words id word !=""] wordDict={} for i in range(1,len(words)): if words[i-1] not in wordDict: #為單詞新建一個字典 wordDict[words[i-1]]={} if words[i] not in wordDict[words[i-1]]: wordDict[words[i-1]][words[i]] = 0 wordDict[words[i-1]][words[i]]=wordDict[words[i-1]][words[i]]+1 return wordDict text=str(urlopen("http://pythonscraping.com/files/inaugurationSpeech.txt").read(),'utf-8') wordDict=buildWordDict(text) #生成鏈長為100的馬爾科夫鏈 length=100 chain="" currentWord="I" for i in range(0,length): chain += str(currentWord) currentWord=retrieveRandomWord(wordDict[currentWord]) print(chain)
{word_a:{word_b:2,word_c:1,word_d:1},
word_e:{word_b:5,word_d:2}...}
在這個字典中,“word_a”出現了四次,其中兩次後面跟的單詞是“word_b”,一次是“word_c”,一次是“word_d”。“word_e”出現了七次,其中五次後面跟的是“word_b”,兩次是“word_d”。
如果我們要畫出整個結果的節點模型,那麼“word_a”可能帶有50%的概率箭頭指向“word_b”(四次中出現了兩次),帶25%的概率箭頭指向“word_c”,還有帶25%的箭頭指向“word_d”。
一旦字典建成,不管你現在看到文章的哪個詞,都可以用這個字典作為查詢表來選擇下一個節點。這個字典的字典是這麼使用的,如果我們現在位於“word_e”節點,那麼下一步就要把字典{word_b:5,word_d:2}傳遞到retrieveRanddomWord。這個函式會按照字典中單詞頻次的權重隨機獲取一個單詞。先確定一個隨機的開始詞(例子使用的是“I”),我們可以通過馬爾科夫鏈隨意地重複,生成我們需要的任意長度的句子。
上述例項的執行結果如下,且每次執行的結果會出現不一致: