我正在实施 Jurafsky + Martin 的语音和语言处理(第 2 版)中介绍的 forward-backward/Baum-Welch 算法,作为词性标注器。我的代码大致结构如下:
#Initialize transition probability matrix A and observation likelihood matrix B
(A,B) = init() #Assume this is correct
#Begin forward-backward/Baum-Welch algorithm
for training_sentence in training_data:
(A,B) = forward_backward(A,B,training_sentence, vocabulary, hidden_state_set)
#Use new A,B to test
i = 0
for test_sentence in test_data:
predicted_tag_sequence = viterbi(test_sentence, vocabulary, A,B)
update_confusion_matrix(predicted_tag_sequence, actual_tag_sequences[i])
i += 1
我的实现在调用 forward_backward 之前初始化 A 和 B。然后,用于 forward_backward 每次迭代的 A,B 是从前一次迭代计算的 A,B。
我遇到了两个问题:
- 在第一次迭代之后,A 和 B 非常稀疏,以至于 forward_backward 的未来迭代没有期望最大化步骤。
- 最终的 A 和 B 非常稀疏,以至于在应用 Viterbi 时,每个单词都被分配了一些任意标签(因为 A 和 B 非常稀疏,句子上几乎任何标签序列的概率都是 0)。
我可能做错了什么?我最大的担忧是理论上的:我在上一次迭代中使用 A、B 调用 forward_backward 是否正确?或者我应该将我的初始 A,B 用于 forward_backward 的所有迭代,将我的最终 A,B 作为结果的平均值?如果我的代码理论上没问题,还有什么问题?