Python scikit-learn HMM 存在问题的解决方法

原创,如转载请注明出处http://blog.csdn.net/menglongli/article/details/17355897


背景:

HMM隐式马尔可夫,在语音识别里面有着很重要的应用,在视频识别里,也有很多人效仿使用之。

作为一名Pythoner 表示 Python版本的HMM实现库很少。

虽然少,但是还是有的,我们把目光投向scikit-learn库,scikit-learn是一个很好用的机器学习的第三方库。

(在这里,我用的Python版本是 2.7,以及与其对应的scikit learn)

但是里面的HMM模块是存在问题的,而且也被遗弃很久,有网上别处的原文如下:

So far, there are a few implementations of HMMs for Python. There is the one in scikit-learn (http://scikit-learn.org/stable/modules/hmm.html) that has been abandoned for some time and recently resumed. However it still seems to have numerical problems and misses support for special cases of HMMs with tied parameters. 


《scikit-learn user guide, Release 0.12-git 》是一本sklearn学习的指导书,书中有一些关于HMM的应用的demo,但是并不多。


存在问题:

比如我想用fit函数去训练一个HMM模型

我在这里特意给出一个不连续的观察状态 0,1,2,3,9


from sklearn import hmm
X=[0,1,2,1,1,2,0,3,9]

model = hmm.MultinomialHMM(n_components=4)
model.n_symbols=10
model.fit([X],n_iter=100)

print model.eval(X)


我在这里对以上的代码做一些说明:

HMM训练时候的这个fit训练函数传入的是一个list,即一组观察序列,也就说不能写成 fit(X,n_iter=100)。

对于多组观察序列

X1=[0,1,2,1,1,2,0,3,9]
X2=[3,3,3,1,1,0,1,3,3]

我们写成下面的样子即可。

fit([X1,X2],n_iter=100)



一切都按预想的编写,但是在运行时候则会出现这样的控制台信息:

Traceback (most recent call last):
  File "F:/Coding/PyCharm/VideoHandlingTry/trySklearnGHMM.py", line 6, in
    model.fit([X],n_iter=100)
  File "C:\Python27\lib\site-packages\sklearn\hmm.py", line 1038, in fit
    raise ValueError(err_msg % obs)
ValueError: Input must be both positive integer array and every element must be continuous, but [[0, 1, 2, 1, 1, 2, 0, 3, 9]] was given.


即HMM要求所输入的input必须是连续的整数才行,而我们在训练HMM的时候知道,某一个观察序列,并不一定会出现所有的预设的状态。


解决方法:

还好这个世界上有很多的大牛,他们不断完善代码,

https://github.com/scikit-learn/scikit-learn/blob/5165fba67e420c37d83b06361e86f1998c13aecd/sklearn/hmm.py

这个是在网上找到的、别人修改过的HMM的fix版本,用它覆盖掉安装的C:\Python27\Lib\site-packages\sklearn\hmm.py的文件,




再次运行上面的代码,不再发生错误,能够训练并得到估计的结果:


(-6.0698265432603344, array([[  1.19209233e-07,   1.19209233e-07,   1.19209233e-07,
          9.99999642e-01],
       [  1.19209233e-07,   9.99999642e-01,   1.19209233e-07,
          1.19209233e-07],
       [  1.19209233e-07,   1.61880953e-06,   9.99998143e-01,
          1.19209233e-07],
       [  1.19209233e-07,   9.95753076e-01,   1.19210165e-07,
          4.24668605e-03],
       [  1.19209233e-07,   9.99999642e-01,   1.19209332e-07,
          1.19209233e-07],
       [  1.19209233e-07,   1.19209233e-07,   9.99999642e-01,
          1.19209233e-07],
       [  1.19209233e-07,   1.19209233e-07,   1.19209233e-07,
          9.99999642e-01],
       [  9.99999642e-01,   1.19209233e-07,   1.19209233e-07,
          1.19209233e-07],
       [  9.99999642e-01,   1.19209233e-07,   1.19209233e-07,
          1.19209233e-07]]))


对结果进行简要说明,-6.0698265432603344是得到的评估的值,是LOG的结果,所以是负的,越接近0,表示越符合当前的HMM模型。


PS:

另外一个需要注意的地方,就是在这个hmm模型的ctor(读see-tor,表示constructor构造函数)里面没有预留n_symbols这个参数,写代码的时候建议在训练 fit 函数执行前单独给出。如果不给出的话,则需要保证input里面的整数是连续的,即X2这种,(X1不行,因为9与0,1,2,3不构成连续),但是如果在训练前给出了n_symbols的值之后(model.n_symbols=10),X1也变成了合法的输入。当然啦,上面这句话成立的前提就是,你已经按替换了HMM的代码,即 fix 过的代码。如果用原来的库里面的HMM代码的话,写了 n_symbols 也是徒劳,即必须严格保证连续(而那不是我们想要的)。


你可能感兴趣的:(编程语言之Python,工具效率)