我一直在寻找维特比算法的精确分步示例。
将输入句子的句子标记视为:
The cat saw the angry dog jump
从此我想生成最可能的输出:
D N V T A N V
我们如何使用Viterbi算法使用trigram-HMM获得上述输出?
(PS:我正在寻找一个精确的一步一步解释,而不是一段代码或数学表示。假设所有概率都是数字。)
非常感谢!
答案 0 :(得分:1)
对于维特比算法和隐马尔可夫模型,首先需要转移概率和发射概率。
在您的示例中,转移概率是P(D-> N),P(N> V)并且发射概率(假设二元模型)是P(D |),P(N | cat) )。
当然,在现实世界的例子中,有比cat,saw等更多的单词。你必须遍历所有训练数据以估计P(D | the),P(N |猫),P(N |车)。然后我们使用维特比算法来找到最可能的标签序列,例如
D N V T A N V
根据你的观察。
这是我对维特比的实施。
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
答案 1 :(得分:-1)
我建议您在其中一本书中查找,例如: Chris Bishop“模式识别与机器学习”。维特比算法是一个非常基本的东西,已在文献中以不同层次的细节进行了描述。