[英]Understanding the Viterbi algorithm
我一直在尋找Viterbi算法的精確分步示例。
考慮將輸入的句子標記為:
The cat saw the angry dog jump
從這個我想產生最可能的輸出為:
D N V T A N V
我們如何使用維特比算法通過Trigram-HMM獲得以上輸出?
(PS:我正在尋找一個精確的逐步說明,而不是一段代碼或數學表示形式。將所有概率都假定為數字。)
萬分感謝!
對於維特比算法和隱馬爾可夫模型,首先需要轉移概率和發射概率。
在您的示例中,過渡概率為P(D-> N),P(N-> V),發射概率(假設雙鏈模型)為P(D | the),P(N | cat)。
當然,在實際示例中,單詞比貓,鋸等要多得多。您必須遍歷所有訓練數據才能估算出P(D | the),P(N | cat), P(N | car)。 然后,我們使用Viterbi算法查找最可能的標簽序列,例如
D N V T A N V
給出您的觀察。
這是我對Viterbi的實現。
def viterbi(vocab, vocab_tag, words, tags, t_bigram_count, t_unigram_count, e_bigram_count, e_unigram_count, ADD_K):
vocab_size = len(vocab)
V = [{}]
for t in vocab_tag:
# Prob of very first word
prob = np.log2(float(e_bigram_count.get((words[0],t),0)+ADD_K))-np.log2(float(e_unigram_count[t]+vocab_size*ADD_K))
# trigram V[0][0]
V[0][t] = {"prob": prob, "prev": None}
for i in range(1,len(words)):
V.append({})
for t in vocab_tag:
V[i][t] = {"prob": np.log2(0), "prev": None}
for t in vocab_tag:
max_trans_prob = np.log2(0);
for prev_tag in vocab_tag:
trans_prob = np.log2(float(t_bigram_count.get((t, prev_tag),0)+ADD_K))-np.log2(float(t_unigram_count[prev_tag]+vocab_size*ADD_K))
if V[i-1][prev_tag]["prob"]+trans_prob > max_trans_prob:
max_trans_prob = V[i-1][prev_tag]["prob"]+trans_prob
max_prob = max_trans_prob+np.log2(e_bigram_count.get((words[i],t),0)+ADD_K)-np.log2(float(e_unigram_count[t]+vocab_size*ADD_K))
V[i][t] = {"prob": max_prob, "prev": prev_tag}
opt = []
previous = None
max_prob = max(value["prob"] for value in V[-1].values())
# Get most probable state and its backtrack
for st, data in V[-1].items():
if data["prob"] == max_prob:
opt.append(st)
previous = st
break
for t in range(len(V) - 2, -1, -1):
opt.insert(0, V[t + 1][previous]["prev"])
previous = V[t][previous]["prev"]
return opt
我建議您在其中一本可用的書中進行查找,例如Chris Bishop的“模式識別和機器學習”。 維特比算法是一個非常基本的東西,並且在文獻中已經詳細描述了各個級別。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.