python自然语言处理-马尔科夫模型

1.概念学习  

  马尔科夫模型常用于分析大量随机事件,随机事件的特点是一个离散事件发生之后,另一个离散事件将在前一个事件的条件下以一定的概率发生。以天气的马尔科夫模型为例:

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”),我们可以通过马尔科夫链随意地重复,生成我们需要的任意长度的句子。
   上述实例的执行结果如下,且每次执行的结果会出现不一致:


  

你可能感兴趣的:(自然语言处理,markov,python自然语言处理,马尔科夫模型)