2012-07-12 2 views
2

this Stack Overflow answer에있는 비터 비 알고리즘의 파이썬 구현을 루비로 변환하려고합니다. 전체 스크립트는 내 의견과 함께이 질문의 하단에 찾을 수 있습니다.이 파이썬 비터 비 알고리즘을 이해하는 데 도움이 필요합니다

불행히도 저는 파이썬에 대해 거의 알지 못해 번역이 내가 원하는 것보다 더 어렵다는 것을 증명합니다. 그래도 나는 진전을 이루었습니다. 지금 당장 내 뇌를 완전히 녹이고있는 유일한 라인은 다음과 같습니다.

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

누군가가 설명해 주시겠습니까? 당신은 list comprehension보고있다

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) 

답변

1

:

다음은 전체 파이썬 스크립트입니다.

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) 

내가 그 그것을 설명 도움이되기를 바랍니다 :

확장 된 버전은 다음과 같이 보인다. 그렇지 않은 경우 자유롭게 질문을 편집하고 이해하지 못하는 문장을 지적하십시오.

관련 문제