[英]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鏈接上的完整代碼
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文檔中的配方以創建累積分布 (這就是人們在評論中描述的內容)
如果這些值形成了它們的鍵出現的相對概率,那么這里的竅門就是。 您必須將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.