Skip to main content
 首页 » 编程设计

python之需要帮助理解这个 Python Viterbi 算法

2025年05月04日7qq号

我正在尝试转换在 this Stack Overflow answer 中找到的维特比算法的 Python 实现进入 ruby 。完整的脚本可以在这个问题的底部找到我的评论。

不幸的是,我对 Python 知之甚少,所以翻译比我想象的要难。尽管如此,我还是取得了一些进步。现在,唯一让我的大脑完全融化的台词是:

prob_k, k = max((probs[j] * word_prob(text[j:i]), j) for j in range(max(0, i - max_word_length), i)) 

有人可以解释一下它在做什么吗?

这是完整的 Python 脚本:

import re 
from itertools import groupby 
 
# text will be a compound word such as 'wickedweather'. 
def viterbi_segment(text): 
  probs, lasts = [1.0], [0] 
 
  # Iterate over the letters in the compound. 
  # eg. [w, ickedweather], [wi, ckedweather], and so on. 
  for i in range(1, len(text) + 1): 
    # I've no idea what this line is doing and I can't figure out how to split it up? 
    prob_k, k = max((probs[j] * word_prob(text[j:i]), j) for j in range(max(0, i - max_word_length), i)) 
    # Append values to arrays. 
    probs.append(prob_k) 
    lasts.append(k) 
 
  words = [] 
  i = len(text) 
  while 0 < i: 
    words.append(text[lasts[i]:i]) 
    i = lasts[i] 
  words.reverse() 
  return words, probs[-1] 
 
# Calc the probability of a word based on occurrences in the dictionary. 
def word_prob(word): 
  # dictionary.get(key) will return the value for the specified key. 
  # In this case, thats the number of occurances of thw word in the 
  # dictionary. The second argument is a default value to return if 
  # the word is not found. 
  return dictionary.get(word, 0) / total 
 
# This ensures we ony deal with full words rather than each 
# individual letter. Normalize the words basically. 
def words(text): 
  return re.findall('[a-z]+', text.lower()) 
 
# This gets us a hash where the keys are words and the values are the 
# number of ocurrances in the dictionary. 
dictionary = dict((w, len(list(ws))) 
  # /usr/share/dixt/words is a file of newline delimitated words. 
  for w, ws in groupby(sorted(words(open('/usr/share/dict/words').read())))) 
 
# Assign the length of the longest word in the dictionary. 
max_word_length = max(map(len, dictionary)) 
 
# Assign the total number of words in the dictionary. It's a float 
# because we're going to divide by it later on. 
total = float(sum(dictionary.values())) 
 
# Run the algo over a file of newline delimited compound words. 
compounds = words(open('compounds.txt').read()) 
for comp in compounds: 
  print comp, ": ", viterbi_segment(comp) 

请您参考如下方法:

您正在查看 list comprehension .

展开后的版本看起来像这样:

all_probs = [] 
 
for j in range(max(0, i - max_word_length), i): 
    all_probs.append((probs[j] * word_prob(text[j:i]), j)) 
 
prob_k, k = max(all_probs) 

我希望这有助于解释它。如果没有,请随时编辑您的问题并指出您不理解的陈述。