维特比算法(HMM)的质量差

2024-06-17 10:53:51 发布

您现在位置:Python中文网/ 问答频道 /正文

我最近一直在尝试研究隐马尔可夫模型和维特比算法。我找到了一个名为hmmlearn(http://hmmlearn.readthedocs.io/en/latest/tutorial.html)的库来帮助我为两个状态生成一个状态序列(使用高斯发射)。然后我想用维特比重新确定状态序列。我的代码可以工作,但是预测大约5%的状态是错误的(取决于高斯辐射的平均值和方差)。hmmlearn库有一个.predict方法,该方法还使用Viterbi来确定状态序列。在

我现在的问题是hmmlearn的Viterbi算法比我手写的要好得多(错误率比我的5%低0.5%)。我在代码中找不到任何主要问题,所以我不知道为什么会这样。下面是我的代码,我首先生成状态和观察序列Z和X,用hmmlearn预测Z,最后用我自己的代码预测它:

# Import libraries
import numpy as np
import scipy.stats as st
from hmmlearn import hmm

# Generate a sequence
model = hmm.GaussianHMM(n_components = 2, covariance_type = "spherical")
model.startprob_ = pi
model.transmat_ = A
model.means_ = obs_means
model.covars_ = obs_covars

X, Z = model.sample(T)

## Predict the states from generated observations with the hmmlearn library
Z_pred = model.predict(X)

# Predict the state sequence with Viterbi by hand
B = np.concatenate((st.norm(mean_1,var_1).pdf(X), st.norm(mean_2,var_2).pdf(X)), axis = 1)
delta = np.zeros(shape = (T, 2))
psi = np.zeros(shape= (T, 2))

### Calculate starting values
for s in np.arange(2):
    delta[0, s] = np.log(pi[s]) + np.log(B[0, s])
    psi = np.zeros((T, 2))

### Take everything in log space since values get very low as t -> T
for t in range(1,T):
    for s_post in range(0, 2):
        delta[t, s_post] = np.max([delta[t - 1, :] + np.log(A[:, s_post])], axis = 1) + np.log(B[t, s_post])
        psi[t, s_post] = np.argmax([delta[t - 1, :] + np.log(A[:, s_post])], axis = 1)

### Backtrack
states = np.zeros(T, dtype=np.int32)
states[T-1] = np.argmax(delta[T-1])

for t in range(T-2, -1, -1):
    states[t] = psi[t+1, states[t+1]]

我不确定我的代码是否有一个大错误,或者hmmlearn只是使用了一个更精细的Viterbi算法。我注意到,通过研究错误预测的状态,发射概率B的影响似乎太大,因为它导致状态变化太频繁,即使转移到另一个状态的概率真的很低。在

我对python比较陌生,所以请原谅我糟糕的代码编写。提前感谢您的任何提示!在

编辑:正如你在代码中看到的,我很笨,用方差代替标准差来确定排放概率。与Viterbi算法实现后,得到了与Viterbi相同的结果。在


Tags: 代码in算法logmodel状态npzeros