fengdu78 / lihang-code

《统计学习方法》的代码实现
18.66k stars 6.26k forks source link

第10章隐形马尔可夫模型注释错误及维特比算法实现错误 #19

Open Ruikun-Li opened 5 years ago

Ruikun-Li commented 5 years ago

在研读第10章隐形马尔可夫模型代码的时候,发现出现两个问题:

1.注释错误: 代码中的:N = len(Q) # 状态序列的大小 由定义可知Q应是所有可能状态的集合,而不是状态序列,状态序列为I 因此应更改为:N = len(Q) #可能存在的状态数量 以免误解

2.维特比算法实现中的错误: 在维特比算法实现的过程中多次用到argmax函数,由于其返回的是索引,因此应+1才能和正常的下标值相符合。原代码中在计算时未+1,但在输出时却加了1,导致算法计算的delta、psis参数部分正确、部分错误,最终预测的状态序列也是错误的。 原代码 psis[i][t] = np.argmax(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A])) #未+1 ... I[0][M-1] = np.argmax([delta[M-1] for delta in deltas]) #未+1 print('i%d=argmax[deltaT(i)]=%d' % (M, I[0][M-1]+1)) #输出时手动+1 for t in range(M-2, -1, -1): I[0][t] = psis[int(I[0][t+1])][t+1] #因之前未+1,因此此处直接当索引使用了 print('i%d=psis%d(i%d)=%d' % (t+1, t+2, t+2, I[0][t]+1)) #输出时手动+1 print(I) #最终输出错误

建议在计算产生索引时统一+1,以生成符合实际的下标值;而在使用索引时再-1来避免超限 更改代码: psis[i][t] = np.argmax(np.multiply([delta[t-1] for delta in deltas], [a[i] for a in A])) + 1 #索引值要+1 ... I[0][M-1] = np.argmax([delta[M-1] for delta in deltas]) + 1 #索引值要+1 print('i%d=argmax[deltaT(i)]=%d' % (M, I[0][M-1])) #直接输出 for t in range(M-2, -1, -1): I[0][t] = psis[int(I[0][t+1]) - 1][t+1] #用做索引,因此-1 print('i%d=psis%d(i%d)=%d' % (t+1, t+2, t+2, I[0][t])) #直接输出 print("状态序列I:", I)

此时所有参数及最终结果均正确,且与书本中的结果一致。

fengdu78 commented 5 years ago

谢谢,已修改