用hmmlearn學習隱馬爾科夫模型HMM

    在以前的HMM系列中,咱們對隱馬爾科夫模型HMM的原理以及三個問題的求解方法作了總結。本文咱們就從實踐的角度用Python的hmmlearn庫來學習HMM的使用。關於hmmlearn的更多資料在官方文檔有介紹。html

1. hmmlearn概述

    hmmlearn安裝很簡單,"pip install hmmlearn"便可完成。git

    hmmlearn實現了三種HMM模型類,按照觀測狀態是連續狀態仍是離散狀態,能夠分爲兩類。GaussianHMM和GMMHMM是連續觀測狀態的HMM模型,而MultinomialHMM是離散觀測狀態的模型,也是咱們在HMM原理系列篇裏面使用的模型。github

    對於MultinomialHMM的模型,使用比較簡單,"startprob_"參數對應咱們的隱藏狀態初始分佈$\Pi$, "transmat_"對應咱們的狀態轉移矩陣$A$, "emissionprob_"對應咱們的觀測狀態機率矩陣$B$。算法

    對於連續觀測狀態的HMM模型,GaussianHMM類假設觀測狀態符合高斯分佈,而GMMHMM類則假設觀測狀態符合混合高斯分佈。通常狀況下咱們使用GaussianHMM即高斯分佈的觀測狀態便可。如下對於連續觀測狀態的HMM模型,咱們只討論GaussianHMM類。app

    在GaussianHMM類中,"startprob_"參數對應咱們的隱藏狀態初始分佈$\Pi$, "transmat_"對應咱們的狀態轉移矩陣$A$, 比較特殊的是觀測狀態機率的表示方法,此時因爲觀測狀態是連續值,咱們沒法像MultinomialHMM同樣直接給出矩陣$B$。而是採用給出各個隱藏狀態對應的觀測狀態高斯分佈的機率密度函數的參數。ide

    若是觀測序列是一維的,則觀測狀態的機率密度函數是一維的普通高斯分佈。若是觀測序列是$N$維的,則隱藏狀態對應的觀測狀態的機率密度函數是$N$維高斯分佈。高斯分佈的機率密度函數參數能夠用$\mu$表示高斯分佈的指望向量,$\Sigma$表示高斯分佈的協方差矩陣。在GaussianHMM類中,「means」用來表示各個隱藏狀態對應的高斯分佈指望向量$\mu$造成的矩陣,而「covars」用來表示各個隱藏狀態對應的高斯分佈協方差矩陣$\Sigma$造成的三維張量。函數

2. MultinomialHMM實例

    下面咱們用咱們在HMM系列原理篇中的例子來使用MultinomialHMM跑一遍。學習

    完整代碼參見個人github:https://github.com/ljpzzz/machinelearning/blob/master/natural-language-processing/hmm.ipynbui

    首先創建HMM的模型:url

import numpy as np from hmmlearn import hmm states = ["box 1", "box 2", "box3"] n_states = len(states) observations = ["red", "white"] n_observations = len(observations) start_probability = np.array([0.2, 0.4, 0.4]) transition_probability = np.array([ [0.5, 0.2, 0.3], [0.3, 0.5, 0.2], [0.2, 0.3, 0.5] ]) emission_probability = np.array([ [0.5, 0.5], [0.4, 0.6], [0.7, 0.3] ]) model = hmm.MultinomialHMM(n_components=n_states) model.startprob_=start_probability model.transmat_=transition_probability model.emissionprob_=emission_probability

    如今咱們來跑一跑HMM問題三維特比算法的解碼過程,使用和原理篇同樣的觀測序列來解碼,代碼以下:

seen = np.array([[0,1,0]]).T logprob, box = model.decode(seen, algorithm="viterbi") print("The ball picked:", ", ".join(map(lambda x: observations[x], seen))) print("The hidden box", ", ".join(map(lambda x: states[x], box)))

    輸出結果以下:

('The ball picked:', 'red, white, red')
('The hidden box', 'box3, box3, box3')

    能夠看出,結果和咱們原理篇中的手動計算的結果是同樣的。

    也能夠使用predict函數,結果也是同樣的,代碼以下:

box2 = model.predict(seen) print("The ball picked:", ", ".join(map(lambda x: observations[x], seen))) print("The hidden box", ", ".join(map(lambda x: states[x], box2)))

    你們能夠跑一下,看看結果是否和decode函數相同。

    如今咱們再來看看求HMM問題一的觀測序列的機率的問題,代碼以下:

print model.score(seen)

    輸出結果是:

-2.03854530992

    要注意的是score函數返回的是以天然對數爲底的對數機率值,咱們在HMM問題一中手動計算的結果是未取對數的原始機率是0.13022。對比一下:$$ln0.13022 \approx -2.0385$$

    如今咱們再看看HMM問題二,求解模型參數的問題。因爲鮑姆-韋爾奇算法是基於EM算法的近似算法,因此咱們須要多跑幾回,好比下面咱們跑三次,選擇一個比較優的模型參數,代碼以下:

import numpy as np from hmmlearn import hmm states = ["box 1", "box 2", "box3"] n_states = len(states) observations = ["red", "white"] n_observations = len(observations) model2 = hmm.MultinomialHMM(n_components=n_states, n_iter=20, tol=0.01) X2 = np.array([[0,1,0,1],[0,0,0,1],[1,0,1,1]]) model2.fit(X2) print model2.startprob_ print model2.transmat_ print model2.emissionprob_ print model2.score(X2) model2.fit(X2) print model2.startprob_ print model2.transmat_ print model2.emissionprob_ print model2.score(X2) model2.fit(X2) print model2.startprob_ print model2.transmat_ print model2.emissionprob_ print model2.score(X2)

    結果這裏就略去了,最終咱們會選擇分數最高的模型參數。

    以上就是用MultinomialHMM解決HMM模型三個問題的方法。

3. GaussianHMM實例

    下面咱們再給一個GaussianHMM的實例,這個實例中,咱們的觀測狀態是二維的,而隱藏狀態有4個。所以咱們的「means」參數是$4 \times 2$的矩陣,而「covars」參數是$4 \times 2 \times 2$的張量。

    創建模型以下:

startprob = np.array([0.6, 0.3, 0.1, 0.0]) # The transition matrix, note that there are no transitions possible # between component 1 and 3
transmat = np.array([[0.7, 0.2, 0.0, 0.1], [0.3, 0.5, 0.2, 0.0], [0.0, 0.3, 0.5, 0.2], [0.2, 0.0, 0.2, 0.6]]) # The means of each component
means = np.array([[0.0,  0.0], [0.0, 11.0], [9.0, 10.0], [11.0, -1.0]]) # The covariance of each component
covars = .5 * np.tile(np.identity(2), (4, 1, 1)) # Build an HMM instance and set parameters
model3 = hmm.GaussianHMM(n_components=4, covariance_type="full") # Instead of fitting it from the data, we directly set the estimated # parameters, the means and covariance of the components
model3.startprob_ = startprob model3.transmat_ = transmat model3.means_ = means model3.covars_ = covars

     注意上面有個參數covariance_type,取值爲"full"意味全部的$\mu,\Sigma$都須要指定。取值爲「spherical」則$\Sigma$的非對角線元素爲0,對角線元素相同。取值爲「diag」則$\Sigma$的非對角線元素爲0,對角線元素能夠不一樣,"tied"指全部的隱藏狀態對應的觀測狀態分佈使用相同的協方差矩陣$\Sigma$

    咱們如今跑一跑HMM問題一解碼的過程,因爲觀測狀態是二維的,咱們用的三維觀測序列, 因此這裏的 輸入是一個$3 \times 2$的矩陣,代碼以下:

seen = np.array([[1.1,2.0],[-1,2.0],[3,7]]) logprob, state = model3.decode(seen, algorithm="viterbi") print state

     輸出結果以下:

[0 0 1]

    再看看HMM問題一對數機率的計算:

print model3.score(seen)

    輸出以下:

-41.1211281377

    以上就是用hmmlearn學習HMM的過程。但願能夠幫到你們。

 

(歡迎轉載,轉載請註明出處。歡迎溝通交流: liujianping-ok@163.com) 

相關文章
相關標籤/搜索