python 日常筆記 hmmlearn 隱性馬爾科夫模型案例分析

問題:

什么是馬爾科夫模型?用來干什么?
大家可以參考這篇簡書

<隱性馬爾科夫模型簡介,只聊原理, (保證沒有數(shù)學)>
http://www.itdecent.cn/p/3b4fbcea2744

python 實現(xiàn)

關(guān)于HMM有兩個主要問題:
已知上述三個參數(shù),和當前觀測序列,求解隱藏狀態(tài)的變化
所有參數(shù)未知,只有數(shù)據(jù),如何獲得三個參數(shù)
需要使用hmmlearn 包

導入需要的庫

import random
import datetime   # 可有可無,用來記錄模型學習時間,
import numpy as np
from hmmlearn import hmm

已知參數(shù)和當前的觀測序列,求解隱含狀態(tài)的序列

隱藏狀態(tài):

hidden_states = ["A", "B" ]
n_hidden_states = len(hidden_states)

觀察情況

observations = ["1", "2", "3", "4", "5", "6"]
n_observations = len(observations)

初始狀態(tài)矩陣

start_probability = np.array([0.8, 0.2,])

狀態(tài)轉(zhuǎn)移矩陣

transition_probability = np.array([[0.2, 0.8], 
                                   [0.8, 0.2]]
                                 )

發(fā)射矩陣

emission_probability = np.array([ [1/6,  1/6,  1/6,  1/6,  1/6,  1/6,], 
                                  [0.25, 0.25, 0.25, 0.25, 0,    0] ]
                               )

構(gòu)建模型

model = hmm.MultinomialHMM(n_components=n_hidden_states)

將上述設(shè)定的參數(shù)傳入其中

model.startprob_=start_probability
model.transmat_=transition_probability
model.emissionprob_=emission_probability

輸入我們觀察到的序列

observations_sequence = np.array([[0, 1, 2,1, 3, 3, 4, 0, 5, 3]]).T
print("觀察到的取出的色子點數(shù):", ", ".join(map(lambda x: observations[int(x)], observations_sequence)))
logprob, box = model.decode(observations_sequence, algorithm="viterbi")
print("decode 方法計算:    ", ", ".join(map(lambda x: hidden_states[x], box)))
box = model.predict(observations_sequence)
print("predict方法計算:    ", ", ".join(map(lambda x: hidden_states[int(x)], box)), '\n')


observations_sequence = np.array([[2, 1, 1,0, 2, 3, 0, 1, 1, 2, 2,1,0,0,3,3]]).T
print("取出的色子點數(shù):", ", ".join(map(lambda x: observations[int(x)], observations_sequence)))
box = model.predict(observations_sequence)
print("從哪個盒子取的:", ", ".join(map(lambda x: hidden_states[int(x)], box)),'\n')


observations_sequence = np.array([[5, 4, 3, 2, 2, 3, 0, 4, 5, 4, 1,1,0,0,3,3]]).T
print("取出的色子點數(shù):", ", ".join(map(lambda x: observations[int(x)], observations_sequence)))
box = model.predict(observations_sequence)
print("從哪個盒子取的:", ", ".join(map(lambda x: hidden_states[int(x)], box)))

輸出的結(jié)果是
觀察到的取出的色子點數(shù): 1, 2, 3, 2, 4, 4, 5, 1, 6, 4
decode 方法計算: A, B, A, B, A, B, A, B, A, B
predict方法計算: A, B, A, B, A, B, A, B, A, B

取出的色子點數(shù): 3, 2, 2, 1, 3, 4, 1, 2, 2, 3, 3, 2, 1, 1, 4, 4
從哪個盒子取的: A, B, A, B, A, B, A, B, A, B, A, B, A, B, A, B

取出的色子點數(shù): 6, 5, 4, 3, 3, 4, 1, 5, 6, 5, 2, 2, 1, 1, 4, 4
從哪個盒子取的: A, A, B, A, B, A, B, A, A, A, B, A, B, A, B, A

所有參數(shù)未知,只有數(shù)據(jù),如何獲得三個參數(shù)

方案: 我們先假定一個初始概率分布,轉(zhuǎn)移矩陣,以及發(fā)射矩陣,按照這些參數(shù)生成很多很多數(shù)據(jù).
然后將數(shù)據(jù)放到HMM模型里,利用數(shù)據(jù)學習,檢查模型學到的參數(shù)和我們假定的參數(shù)是不是一致。
按照假象的規(guī)則去生成一些列數(shù)據(jù)

#  初始狀態(tài) 判斷標準,小于此值為A 大于此值為B
a_b_init_critia = 0.2

# state_change
state_change = {"A": 0.3,   # 此時如果是A, 那么取random, 如果小于 此值就是A 否則為B
                "B": 0.6    # 此時如果是B, 那么取random, 如果小于 此值就是A 否則為B
               }
# 點數(shù)情況
observations = ["1", "2", "3", "4", "5", "6"]
# 點數(shù)對應(yīng)的 index
point={"A": [0,1,2,3,4,5],  "B": [0,1,2,3]}

data_size = 10000
whole_data = []
lengths = []
for i in range(data_size):
    dice = "A" if random.random() < a_b_init_critia else "B"
    data = []
    sequence_length = random.randint(2, 25)
    for _ in range(sequence_length):
#         print(dice, end="  ")
        data.append([random.sample(point[dice], 1)[0]])
        dice = "A" if random.random() < state_change[dice] else "B"
#     print(f"一共投了  {sequence_length} 次 \n點數(shù)的index  {data} \n")
    whole_data.append(data)
    lengths.append(sequence_length)
whole_data = np.concatenate(whole_data)

將數(shù)據(jù)填入模型中,進行學習

print(f"開始學習 {datetime.datetime.now()} 共 {len(lengths)}條數(shù)據(jù)")
hmm_model = hmm.MultinomialHMM(n_components=len(point),
                               n_iter=100000,  # Maximum number of iterations to perform.
                               tol=0.000001,   # Convergence threshold. EM will stop if the gain in log-likelihood is below this value.
                               verbose = False, # When True per-iteration convergence reports are printed to sys.stderr. 
                              )
hmm_model.fit(whole_data, lengths)

# 學習之后,查看參數(shù)
print(f"結(jié)束學習 {datetime.datetime.now()}")
print('因為是無監(jiān)督學習,所以模型不會把 A B 排定先后順序,但是 三個參數(shù)是相互關(guān)聯(lián)的,所以順序其實無關(guān)系')
print('初始概率')
print(hmm_model.startprob_,'\n')
print('狀態(tài)轉(zhuǎn)移矩陣')
print(hmm_model.transmat_,'\n')
print('從隱藏狀態(tài)到 顯示狀態(tài)的發(fā)散矩陣')
print(hmm_model.emissionprob_,'\n')

輸出的結(jié)果是
開始學習 2020-01-05 10:03:02.832792 共 10000條數(shù)據(jù)
結(jié)束學習 2020-01-05 13:05:53.612298
因為是無監(jiān)督學習,所以模型不會把 A B 排定先后順序,但是 三個參數(shù)是相互關(guān)聯(lián)的,所以順序其實無關(guān)系
初始概率
[0.20509604 0.79490396]

狀態(tài)轉(zhuǎn)移矩陣
[[0.31460223 0.68539777]
[0.6213235 0.3786765 ]]

從隱藏狀態(tài)到 顯示狀態(tài)的發(fā)散矩陣
[[1.67834277e-01 1.74886284e-01 1.69078215e-01 1.68723388e-01
1.61611529e-01 1.57866306e-01]
[2.51185996e-01 2.46793569e-01 2.46239587e-01 2.53539909e-01
1.54840968e-06 2.23939182e-03]]

可見學習的還是很好的, 只是時間有點長(3個小時),
但是結(jié)果非常符合預(yù)期, 主要原因是,我們的數(shù)據(jù)非常干凈,沒有噪音. 如果在數(shù)據(jù)中混雜這噪音,可能結(jié)果就不會這么好了

ref

https://hmmlearn.readthedocs.io/en/latest/api.html

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 國債逆回購優(yōu)勢 1000元以上,即可參與保本保收益,特殊時間點,年化利率10%以上安全超高,不存在資金不能歸還的情...
    石頭說錢閱讀 3,686評論 0 1
  • 看到一位網(wǎng)友說的:看透不如看淡。心中大贊! 這是一個鼓勵進取、提倡建功立業(yè)的火熱時代。烈火烹油、鮮花著錦,大家總是...
    一棵開滿鮮花的樹閱讀 824評論 2 3
  • 人言輕樂好, 沿岸走一遭。 聲打疾湖草, 風吹緩柳濤。 友聽澤水鬧, 云教雨荷逃。 曲盡終歸笑, 清魂潤晚悄。 ...
    葉翼欣筆閱讀 1,191評論 5 89
  • 一個月前,參加一個合唱團,昨天終于比賽結(jié)束,從預(yù)賽到?jīng)Q賽一路第一。以至于大家賽后從合唱臺下來,還沉浸在演唱...
    芊芊女巫閱讀 326評論 2 2
  • 薦 語 在愛與被愛的過程中,我們都曾經(jīng)歷過痛苦、恐懼,也體驗過狂喜與極樂,我們渴望建立真摯的親密關(guān)係,卻又害怕再度...
    金色弧線閱讀 467評論 0 2

友情鏈接更多精彩內(nèi)容