1. 程式人生 > >python自然語言處理-馬爾科夫模型

python自然語言處理-馬爾科夫模型

1.概念學習  

  馬爾科夫模型常用於分析大量隨機事件,隨機事件的特點是一個離散事件發生之後,另一個離散事件將在前一個事件的條件下以一定的概率發生。以天氣的馬爾科夫模型為例:

在這個天氣系統模型中,如果今天是晴天,那麼明天有70%的可能是晴天,20%的可能是多雲,10%的可能下雨。如果今天是下雨天,那麼明天有50%的可能也下雨,25%的可能是晴天,25%的可能是多雲。

需要注意以下幾點:

  • 任何一個節點引出的所有可能的總和必須等於100%。無論是多麼複雜的系統,必然會在下一步發生若干事件中的一個事件;
  • 雖然這個天氣系統在任一時間都只有三種可能,但是你可以用這個模型生成一個天氣狀態的無限次轉移列表;
  • 只有當前節點的狀態會影響後一天的狀態。如果你在“晴天”節點上,即使前100天都是晴天或雨天都沒有關係,明天晴天的概率還是70%;
  • 有些節點可能比其他節點較難到達,這個現象的原因用數學來解釋非常複雜,但是可以直觀地看出,在這個系統中任意時間節點上,第二天是“雨天”的可能性(指向它的箭頭概率之後下雨100%),比“晴天”和“多雲”要小很多
很明顯,這是一個很簡單的系統,而馬爾科夫模型可以演化成任意規模的複雜系統。事實上,Google的page rank演算法也是基於馬爾科夫模型,把網站做為節點,入站/出站連結作為節點之間的連線。連線某一個節點的“可能性”(likehood)表示一個網站的相對關注度。也就是說,如果我們的天氣系統表示一個微型網際網路,那麼“雨天”的頁面等級(page rank)相對比較低,而“多雲”的頁面等級相對比較高。

2. 實戰演練

繼續前面的總統演講的例項,分析一個具體的例項:文字分析與寫作,通過演講內容的結構生成任意長度的(下面的示例中長為100)馬爾科夫鏈組成的句子:
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)
  對這段程式碼進行分析,buildWordDict函式把網上的演講文字字串作為引數,然後對字串做一些清理和格式化處理,去掉引號,把其他標點符號兩端加上空格,這樣就可以對每一個單詞進行有效的處理。最後,再建立如下所示的二維字典-字典裡有字典:
{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”),我們可以通過馬爾科夫鏈隨意地重複,生成我們需要的任意長度的句子。    上述例項的執行結果如下,且每次執行的結果會出現不一致: