Ruby写的向前算法
隐马尔科夫模型中有三个问题:
1) 估计问题:给定一个观察序列O=O1O2…OT和模型u = (A, B, π), 如何快速地计算出给定模型u情况下,观察序列O的概率,即P(O | u) |
2) 序列问题: 给定观察序列O=O1O2…OT和模型u = (A, B, π), 如何快速有效地选择在一定意义下“最优”的状态序列Q=q1q2…qT,使得该状态序列“最好地解释”观察序列?
3) 训练问题或参数估计:给定一个观察序列O=O1O2…OT,如何根据最大似然估计来求模型的参数值?即如何调节模型u=(A, B, π)的参数,使得P(O | u)最大? |
问题1是一个解码问题,前向算法可以解决该问题(forward procedure),也是动态规划法的一种应用。
关于前向算法的基础知识可以看这篇文章
最后是ruby代码:
class FowardAlgorithm
def initialize(pi, trans_pro, emit_pro)
@pi = pi
@trans_pro = trans_pro
@emit_pro = emit_pro
end
def alpha1(state, ob)
@pi[state] * @emit_pro[state][ob]
end
def alpha(t, state)
# t starts from 0, states starts from 9
if t.equal? 0
alpha1(state, @ob[0])
else
sum = (0...@trans_pro.size).inject(0.0) { |sum, i| sum += alpha(t-1, i) * @trans_pro[i][state] }
sum * @emit_pro[state][@ob[t]]
end
end
def p_rerial_n ob
n = ob.size
n -= 1
@ob = ob
# time & states
res = 0.0
0..@trans_pro.size.times { |i|
#print "time #{n}, state #{i}"
tmp = alpha n, i
res += tmp
}
res
end
end
def test
pi = [0.2, 0.4, 0.4]
trans_pro = [
[0.5, 0.2, 0.3],
[0.3, 0.5, 0.2],
[0.2, 0.3, 0.5]
]
emit_pro = [
[0.5, 0.5],
[0.4, 0.6],
[0.7, 0.3]
]
f = FowardAlgorithm.new pi, trans_pro, emit_pro
puts f.p_rerial_n([0, 1, 0, 1])
end
if $PROGRAM_NAME == __FILE__
test
end