【深度剖析HMM(附Python代碼)】4.HMM代碼測試及hmmlearn介紹

相信經過上幾節的說明,大家對於HMM應該有比較好的瞭解,也許大家已經自己試着運行代碼了。
這一節主要介紹下另一個著名的HMM的Python庫——hmmlearn,這個庫提供了三個HMM模型(高斯HMM、離散HMM及高斯混合HMM),比我的代碼速度更快,而且更有穩定,而且其還提供了相應的教程和API函數說明:http://hmmlearn.readthedocs.io/en/latest/index.html
而本文提供的代碼更爲簡單,比較適合初學者學習參考,但不適合實際應用,實際應用可以使用hmmlearn。
爲了考察本文代碼的準確性,本節選擇hmmlearn作爲參考組,利用python測試工具unnitest,來考察代碼的正確性。大體思路是先利用hmmlearn初始化一個具體HMM模型作爲參照組,並生成一段序列,再將該序列作爲本文HMM模型的訓練樣本,最後比較同參照組的參數差別。

1、python測試工具unnitest

測試工具unnitest非常容易使用,首先是建立一個繼承自TestCase的測試類,然後通過覆蓋setUp()完成相關初始化,最後通過覆蓋tearDown()方法清除測試中產生的數據,爲以後的TestCase留下一個乾淨的環境。我們需要在測試類中編寫以test_開頭的測試函數,unnitest會在測試中自動執行以test_開頭的測試函數,unnitest的使用框架:


import unittest  
  
class XXXXX(unittest.TestCase):  
  
    def setUp(self):  
	# 自行編寫
	pass


if __name__ == '__main__':  
    unittest.main() 

參考文獻:
https://docs.python.org/2/library/unittest.html

對離散HMM模型的測試代碼

# 計算平方誤差
def s_error(A, B):
    return sqrt(np.sum((A-B)*(A-B)))/np.sum(B)


class DiscreteHMM_Test(unittest.TestCase):


    def setUp(self):
        # 建立兩個HMM,隱藏狀態個數爲4,X可能分佈爲10類
        n_state =4
        n_feature = 10
        X_length = 1000
        n_batch = 100 # 批量數目
        self.n_batch = n_batch
        self.X_length = X_length
        self.test_hmm = hmm.DiscreteHMM(n_state, n_feature)
        self.comp_hmm = ContrastHMM(n_state, n_feature)
        self.X, self.Z = self.comp_hmm.module.sample(self.X_length*10)
        self.test_hmm.train(self.X, self.Z)


    def test_train_batch(self):
        X = []
        Z = []
        for b in range(self.n_batch):
            b_X, b_Z = self.comp_hmm.module.sample(self.X_length)
            X.append(b_X)
            Z.append(b_Z)


        batch_hmm = hmm.DiscreteHMM(self.test_hmm.n_state, self.test_hmm.x_num)
        batch_hmm.train_batch(X, Z)
        # 判斷概率參數是否接近
        # 初始概率判定沒有通過!!!
        self.assertAlmostEqual(s_error(batch_hmm.start_prob, self.comp_hmm.module.startprob_), 0, 1)
        self.assertAlmostEqual(s_error(batch_hmm.transmat_prob, self.comp_hmm.module.transmat_), 0, 1)
        self.assertAlmostEqual(s_error(batch_hmm.emission_prob, self.comp_hmm.module.emissionprob_), 0, 1)


    def test_train(self):
        # 判斷概率參數是否接近
        # 單批量的初始概率一定是不準的
        # self.assertAlmostEqual(s_error(self.test_hmm.start_prob, self.comp_hmm.module.startprob_), 0, 1)
        self.assertAlmostEqual(s_error(self.test_hmm.transmat_prob, self.comp_hmm.module.transmat_), 0, 1)
        self.assertAlmostEqual(s_error(self.test_hmm.emission_prob, self.comp_hmm.module.emissionprob_), 0, 1)


    def test_X_prob(self):
        X,_ = self.comp_hmm.module.sample(self.X_length)
        prob_test = self.test_hmm.X_prob(X)
        prob_comp = self.comp_hmm.module.score(X)
        self.assertAlmostEqual(s_error(prob_test, prob_comp), 0, 1)


    def test_predict(self):
        X, _ = self.comp_hmm.module.sample(self.X_length)
        prob_next = self.test_hmm.predict(X,np.random.randint(0,self.test_hmm.x_num-1))
        self.assertEqual(prob_next.shape,(self.test_hmm.n_state,))


    def test_decode(self):
        X,_ = self.comp_hmm.module.sample(self.X_length)
        test_decode = self.test_hmm.decode(X)
        _, comp_decode = self.comp_hmm.module.decode(X)
        self.assertAlmostEqual(s_error(test_decode, comp_decode), 0, 1)


if __name__ == '__main__':
    unittest.main()


2、hmmlearn產生HMM模型

利用hmmlearn初始化一個高斯HMM模型

class ContrastHMM():
    def __init__(self, n_state, n_feature):
        self.module = hmmlearn.hmm.GaussianHMM(n_components=n_state,covariance_type="full")
        # 初始概率
        self.module.startprob_ = np.random.random(n_state)
        self.module.startprob_ = self.module.startprob_ / np.sum(self.module.startprob_)
        # 轉換概率
        self.module.transmat_ = np.random.random((n_state,n_state))
        self.module.transmat_ = self.module.transmat_ / np.repeat(np.sum(self.module.transmat_, 1),n_state).reshape((n_state,n_state))
        # 高斯發射概率
        self.module.means_ = np.random.random(size=(n_state,n_feature))*10
        self.module.covars_ = .5 * np.tile(np.identity(n_feature), (n_state, 1, 1))


利用hmmlearn初始化一個離散HMM模型

class ContrastHMM():
    def __init__(self, n_state, n_feature):
        self.module = hmmlearn.hmm.MultinomialHMM(n_components=n_state)
        # 初始概率
        self.module.startprob_ = np.random.random(n_state)
        self.module.startprob_ = self.module.startprob_ / np.sum(self.module.startprob_)
        # print self.module.startprob_
        # 轉換概率
        self.module.transmat_ = np.random.random((n_state,n_state))
        self.module.transmat_ = self.module.transmat_ / np.repeat(np.sum(self.module.transmat_, 1),n_state).reshape((n_state,n_state))
        # print self.module.transmat_
        # 發射概率
        self.module.emissionprob_ = np.random.random(size=(n_state,n_feature))
        self.module.emissionprob_ = self.module.emissionprob_ / np.repeat(np.sum(self.module.emissionprob_, 1),n_feature).reshape((n_state,n_feature))
        # print self.module.emissionprob_


PS:

項目說明:http://blog.csdn.net/tostq/article/details/70846702

代碼下載:https://github.com/tostq/Easy_HMM (點星是對作者最好的支持!!!^_^)


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章