簡體   English   中英

如何用馬爾可夫鏈構建文本?

[英]How to build text with Markov Chain?

目前,我具有從文本文件成功解析的結構:

Chain={'damn':[{'you':0.2}, {'it':0.4}, {'fool!':0.4}]}

現在,我正在努力根據狀態(Chain中的當前鍵)構建輸出文本。 為什么? 因為我的單詞概率是浮點格式,所以我不知道如何將它們轉換為百分比。 我的第一個想法是這樣的:

def buildText(self, Chain):
    self.state = outText = choice(list(Chain.keys()))
    for i in range(self.iterations):
        step = uniform(0,1)
        self.getState(Chain)
        outText = outText + ' ' + self.state + ' '
    return outText

def getState(self, Chain):
    step = uniform(0,1.1)
    print('Current step is: ', step, ' And state is: ', self.state)
    for d in Chain[self.state]:
        for key in d:
            if d[key] < step:
                print('New state--', key)
                self.state = key
                return
            else:
                continue

但是此函數會生成重復文本,因為,正如我提到的那樣,我不知道如何根據概率格式正確編碼隨機函數。 任何建議將不勝感激! Github鏈接上的完整代碼

Python> = 3.6

random現在包括random.choices將權重

import random, collections

# convert Chain to a sensible format instead of a list of single element dictionaries
accumulator = {}
for dic in chain['damn']:
    accumulator.update(dic)
values = list(d.keys())
weights = list(d.values())

# Get one value
print(random.choices(values, weights=weights)[0])

# Test distribution
print(collections.Counter(random.choices(values, weights=weights)[0] for i in range(100)))

# prints Counter({'fool!': 41, 'it': 39, 'you': 20})    

Python <3.6

請參閱Python文檔中的配方以創建累積分布 (這就是人們在評論中描述的內容)

如果這些值形成了它們的鍵出現的相對概率,那么這里的竅門就是。 您必須將random.uniform(0, tot)作為階躍值random.uniform(0, tot)其中tot是概率之和(此處為1)。 然后將其與第一個概率進行比較。 如果較小,則選擇該值,否則從步長值中減去該概率,然后用下一個概率進行迭代。 如果您想超級安全,則可以使所有可能性不受四舍五入錯誤的影響(在SO上搜索損壞的浮點算法 ...)

代碼可以是:

def buildText(self, Chain):
    self.state = outText = choice(list(Chain.keys()))
    for i in range(self.iterations):
        self.getState(Chain)
        outText = outText + ' ' + self.state + ' '
    return outText
def getState(self, Chain):
    states = Chain[self.state]
    if len(states) == 1:                # beware of corner case: one single option
        k = list(states[0].keys())[0]
        self.state = k
        return
    tot = sum(list(d.values())[0] for d in states)
    step = uniform(0, tot)
    # print(step, '/', tot)                  # uncomment to control what happens
    for s in states[:-1]:                    # test up to last item in list
        k, v = list(s.items())[0]
        if step <= v:                        # less we choose this one
            self.state = k
            return
        step -= v                            # else decrease the step
    self.state = list(states[-1].keys())[0]  # last option is a "catch all"

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM