隱馬爾科夫和維特比算法

HMM概念介紹

HMM是關于時序的概率模型,描述一個隱藏的馬爾科夫鏈隨機生成不可觀測的狀態隨機序列,再由各個狀態生成一個可觀測的隨機序列的過程。

下面用一個例子來解釋:
我在東京的女朋友每天根據天氣{下雨,天晴}決定當天的活動{散步,購物,清理房間}中的一種,她不告訴我每天東京的天氣狀況,我只能從他的朋友圈看到他今天的活動。
這個例子其中{下雨,天晴}便是隱含狀態鏈;{散步,購物,清理房間}是可見狀態鏈;隱含狀態(天氣)之間的相互轉換概率叫做狀態轉移概率;盡管可見狀態(活動)之間沒有轉換概率,但是隱含狀態和可見狀態之間有一個概率(即不同的天氣狀況下進行不同的活動的概率)叫做發射概率;還有個初始概率即最開始是晴天還是雨天的概率。

hmm.png

任何一個HMM都可以通過下列五元組來描述:

    :param obs:觀測序列
    :param states:隱狀態
    :param start_p:初始概率(隱狀態)
    :param trans_p:轉移概率(隱狀態)
    :param emit_p: 發射概率 (隱狀態表現為顯狀態的概率)

HMM的三個問題

HMM有三個基本問題:

  1. 預測問題(解碼問題)
    知道天氣有幾種狀況(隱含狀態數量),天氣之間的轉換概率(轉移概率),根據每天的活動情況(可見狀態鏈),我想知道每天的天氣狀況(隱含狀態鏈)。

  2. 概率計算問題
    知道天氣有幾種狀況(隱含狀態數量),天氣之間的轉換概率(轉移概率),根據每天的活動情況(可見狀態鏈),我想知道今天做了這種活動的概率。

  3. 學習問題
    知道天氣有幾種狀況(隱含狀態數量),不知道天氣之間的轉換概率(轉移概率),根據每天的活動情況(可見狀態鏈),我想反推出天氣之間的轉換概率(轉移概率)。


問題解決

本文重點介紹第一個問題的解決算法維特比算法。

維特比算法

假設我在朋友圈看到我女朋友最近三天的活動分別是{散步、購物、清理房間},那我該如何估算這三天的天氣狀況。
預測問題可以用維特比算法來解決。維特比算法實際是用動態規劃求解隱馬爾科夫模型預測問題,即用動態規劃求概率最大路徑,即每天最可能的天氣狀況。

很明顯,第一天天晴還是下雨可以算出來:

  1. 定義 V[時間][今天天氣] = 概率,注意今天天氣指的是,前幾天的天氣都確定下來了(概率最大)今天天氣是X的概率,這里的概率就是一個累乘的概率了。

  2. 因為第一天我的朋友去散步了,所以第一天下雨的概率V[第一天][下雨] = 初始概率[下雨] * 發射概率[下雨][散步] = 0.6 * 0.1 = 0.06,同理可得V[第一天][天晴] = 0.24 。從直覺上來看,因為第一天朋友出門了,她一般喜歡在天晴的時候散步,所以第一天天晴的概率比較大,數字與直覺統一了。

  3. 從第二天開始,對于每種天氣Y,都有前一天天氣是X的概率 * X轉移到Y的概率 * Y天氣下朋友進行這天這種活動的概率。因為前一天天氣X有兩種可能,所以Y的概率有兩個,選取其中較大一個作為V[第二天][天氣Y]的概率,同時將今天的天氣加入到結果序列中。

  4. 比較V[最后一天][下雨][最后一天][天晴]的概率,找出較大的哪一個對應的序列,就是最終結果。

Python實現

# 打印路徑概率表
def print_dptable(V):
    print("    ", end=' ')
    for i in range(len(V)): 
        print("%7d" % i, end=' ')
    print('\n')
 
    for y in V[0].keys():
        print("%.5s: " % y, end=' ')
        for t in range(len(V)):
            print("%.7s" % ("%f" % V[t][y]), end=' ')
        print('\n')
 
 
def viterbi(obs, states, start_p, trans_p, emit_p):
    """
    :param obs:觀測序列
    :param states:隱狀態
    :param start_p:初始概率(隱狀態)
    :param trans_p:轉移概率(隱狀態)
    :param emit_p: 發射概率(隱狀態表現為顯狀態的概率)
    :return:
    """
    # 路徑概率表 V[時間][隱狀態] = 概率
    V = [{}]
    # 一個中間變量,代表當前狀態是哪個隱狀態
    path = {}
 
    # 初始化初始狀態 (t == 0)
    for y in states:
        V[0][y] = start_p[y] * emit_p[y][obs[0]]
        path[y] = [y]
 
    # 對 t > 0 跑一遍維特比算法
    for t in range(1, len(obs)):
        V.append({})
        newpath = {}
 
        for y in states:
            # 概率 隱狀態 =    前狀態是y0的概率 * y0轉移到y的概率 * y表現為當前狀態的概率
            (prob, state) = max([(V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]], y0) for y0 in states])
            # 記錄最大概率
            V[t][y] = prob
            # 記錄路徑
            newpath[y] = path[state] + [y]
 
        # 不需要保留舊路徑
        path = newpath
 
    print_dptable(V)
    (prob, state) = max([(V[len(obs) - 1][y], y) for y in states])
    return (prob, path[state])
 
 
def main():
    states = ('Rainy', 'Sunny')
    observations = ('walk', 'shop', 'clean')
    start_probability = {'Rainy': 0.6, 'Sunny': 0.4}
    transition_probability = {
        'Rainy' : {'Rainy': 0.7, 'Sunny': 0.3},
        'Sunny' : {'Rainy': 0.4, 'Sunny': 0.6},
    }
    emission_probability = {
        'Rainy' : {'walk': 0.1, 'shop': 0.4, 'clean': 0.5},
        'Sunny' : {'walk': 0.6, 'shop': 0.3, 'clean': 0.1},
    }
    
    result = viterbi(observations,
                   states,
                   start_probability,
                   transition_probability,
                   emission_probability)
    return result
 
 
result = main()
print(result)

結果

           0       1       2 
Rainy:  0.06000 0.03840 0.01344 
Sunny:  0.24000 0.04320 0.00259 
(0.01344, ['Sunny', 'Rainy', 'Rainy'])

HMM和維特比算法在NLP上的應用

具體到分詞系統,可以將天氣當成“標簽”,活動當成“字或詞”。那么,幾個NLP的問題就可以轉化為:

  • 詞性標注
    給定一個詞的序列(也就是句子),找出最可能的詞性序列(標簽是詞性)。如ansj分詞和ICTCLAS分詞等。

  • 分詞
    給定一個字的序列,找出最可能的標簽序列(斷句符號:[詞尾]或[非詞尾]構成的序列)。結巴分詞目前就是利用BMES標簽來分詞的,B(開頭),M(中間),E(結尾),S(獨立成詞)

  • 命名實體識別
    給定一個詞的序列,找出最可能的標簽序列(內外符號:[內]表示詞屬于命名實體,[外]表示不屬于)。如ICTCLAS實現的人名識別、翻譯人名識別、地名識別都是用同一個Tagger實現的。


參考

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,001評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,786評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,986評論 0 381
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,204評論 1 315
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,964評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,354評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,410評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,554評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,106評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,918評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,093評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,648評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,342評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,755評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,009評論 1 289
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,839評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,107評論 2 375

推薦閱讀更多精彩內容