def viterbi_CRF(y, t, s):
"""
统计学习方法例11.3
:param y: 输出序列
:param t: 转移特征 [序列*y标记矩阵*[yi-1,yi]]
:param s: 状态特征 [序列*y标记]
:return: 最优路径的状态索引、概率最大值矩阵、节点矩阵
"""
y_lable = len(t[0])
y_star = np.zeros([len(y)],dtype=np.int32) # 输出路径索引
delta = np.zeros([len(y), y_lable],dtype=np.float64) #迭代矩阵
psi = np.zeros([len(y), y_lable],dtype=np.int32)
# 初始化
delta[0][0] = s[0][0]
delta[0][1] = s[0][1]
for i in range(1,len(y)):
for j in range(y_lable):
tmp = [delta[i - 1][k] + s[i][j] + t[i][k][j] for k in range(y_lable)]
psi[i][j] = np.argmax(tmp) # 记录位置
delta[i][j] = tmp[psi[i][j]] # 记录最大概率
y_star[2] = np.argmax(delta[len(y)-1]) # 获取最后deleta的最大值
for i in range(len(y)-2,-1,-1): # 回溯
y_star[i] = psi[i+1][y_star[i+1]]
return y_star,delta,psi
def test_viterbi_CRF():
y = np.array([1,2,2],dtype=np.int) # 给定输出序列
mu = np.array([1,0.5,0.8,0.5]) # 状态权重
# 状态特征 [序列*y标记]
s = np.array([[mu[0],mu[1]],
[mu[2],mu[1]],
[mu[2],mu[3]]],dtype=np.float64)
lamd = np.array([1,0.6,1,1,0.2]) # 转移权重
#
t = np.array([
[[0,0],[0,0]],
[[lamd[1],lamd[0]],[lamd[3],0]],
[[0,lamd[0]],[lamd[2],lamd[4]]]],dtype=np.float64)
y_star, delta, psi = viterbi_CRF(y,t,s)
print '最优路径索引 y*:\n',y_star
print '概率最大值矩阵 δ:\n',delta
print '节点矩阵 ψ:\n',psi
if __name__ == '__main__':
test_viterbi_CRF()
最终输出:
最优路径索引 y*:
[0 1 0]
概率最大值矩阵 δ:
[[1. 0.5]
[2.4 2.5]
[4.3 3.9]]
节点矩阵 ψ:
[[0 0]
[0 0]
[1 0]]