【算法】 隱馬爾可夫模型 HMM

隱馬爾可夫模型

(Hidden Markov Model,HMM)

以下來源於_作者 :skyme 地址:http://www.cnblogs.com/skyme/p/4651331.html
隱馬爾可夫模型(Hidden Markov Model,HMM)是統計模型,它用來描述一個含有隱含未知參數的馬爾可夫過程。其難點是從可觀察的參數中確定該過程的隱含參數。然後利用這些參數來作進一步的分析,例如模式識別。
是在被建模的系統被認爲是一個馬爾可夫過程與未觀測到的(隱藏的)的狀態的統計馬爾可夫模型。
下面用一個簡單的例子來闡述:
假設我手裏有三個不同的骰子。第一個骰子是我們平常見的骰子(稱這個骰子爲D6),6個面,每個面(1,2,3,4,5,6)出現的概率是1/6。第二個骰子是個四面體(稱這個骰子爲D4),每個面(1,2,3,4)出現的概率是1/4。第三個骰子有八個面(稱這個骰子爲D8),每個面(1,2,3,4,5,6,7,8)出現的概率是1/8。

這裏寫圖片描述

假設我們開始擲骰子,我們先從三個骰子裏挑一個,挑到每一個骰子的概率都是1/3。然後我們擲骰子,得到一個數字,1,2,3,4,5,6,7,8中的一個。不停的重複上述過程,我們會得到一串數字,每個數字都是1,2,3,4,5,6,7,8中的一個。例如我們可能得到這麼一串數字(擲骰子10次):1 6 3 5 2 7 3 5 2 4
這串數字叫做可見狀態鏈。但是在隱馬爾可夫模型中,我們不僅僅有這麼一串可見狀態鏈,還有一串隱含狀態鏈。在這個例子裏,這串隱含狀態鏈就是你用的骰子的序列。比如,隱含狀態鏈有可能是:D6 D8 D8 D6 D4 D8 D6 D6 D4 D8
一般來說,HMM中說到的馬爾可夫鏈其實是指隱含狀態鏈,因爲隱含狀態(骰子)之間存在轉換概率(transition probability)。在我們這個例子裏,D6的下一個狀態是D4,D6,D8的概率都是1/3。D4,D8的下一個狀態是D4,D6,D8的轉換概率也都一樣是1/3。這樣設定是爲了最開始容易說清楚,但是我們其實是可以隨意設定轉換概率的。比如,我們可以這樣定義,D6後面不能接D4,D6後面是D6的概率是0.9,是D8的概率是0.1。這樣就是一個新的HMM。
同樣的,儘管可見狀態之間沒有轉換概率,但是隱含狀態和可見狀態之間有一個概率叫做輸出概率(emission probability)。就我們的例子來說,六面骰(D6)產生1的輸出概率是1/6。產生2,3,4,5,6的概率也都是1/6。我們同樣可以對輸出概率進行其他定義。比如,我有一個被賭場動過手腳的六面骰子,擲出來是1的概率更大,是1/2,擲出來是2,3,4,5,6的概率是1/10。

這裏寫圖片描述

這裏寫圖片描述

其實對於HMM來說,如果提前知道所有隱含狀態之間的轉換概率和所有隱含狀態到所有可見狀態之間的輸出概率,做模擬是相當容易的。但是應用HMM模型時候呢,往往是缺失了一部分信息的,有時候你知道骰子有幾種,每種骰子是什麼,但是不知道擲出來的骰子序列;有時候你只是看到了很多次擲骰子的結果,剩下的什麼都不知道。如果應用算法去估計這些缺失的信息,就成了一個很重要的問題。這些算法我會在下面詳細講。

×××××××××××××××××××××××××××××××××××××××××××××××××××××××××
如果你只想看一個簡單易懂的例子,就不需要往下看了。
×××××××××××××××××××××××××××××××××××××××××××××××××××××××

說兩句廢話,答主認爲呢,要了解一個算法,要做到以下兩點:會其意,知其形。答主回答的,其實主要是第一點。但是這一點呢,恰恰是最重要,而且很多書上不會講的。正如你在追一個姑娘,姑娘對你說“你什麼都沒做錯!”你要是隻看姑娘的表達形式呢,認爲自己什麼都沒做錯,顯然就理解錯了。你要理會姑娘的意思,“你趕緊給我道歉!”這樣當你看到對應的表達形式呢,趕緊認錯,跪地求饒就對了。數學也是一樣,你要是不理解意思,光看公式,往往一頭霧水。不過呢,數學的表達頂多也就是晦澀了點,姑娘的表達呢,有的時候就完全和本意相反。所以答主一直認爲理解姑娘比理解數學難多了。

回到正題,和HMM模型相關的算法主要分爲三類,分別解決三種問題:
1)知道骰子有幾種(隱含狀態數量),每種骰子是什麼(轉換概率),根據擲骰子擲出的結果(可見狀態鏈),我想知道每次擲出來的都是哪種骰子(隱含狀態鏈)。
這個問題呢,在語音識別領域呢,叫做解碼問題。這個問題其實有兩種解法,會給出兩個不同的答案。每個答案都對,只不過這些答案的意義不一樣。第一種解法求最大似然狀態路徑,說通俗點呢,就是我求一串骰子序列,這串骰子序列產生觀測結果的概率最大。第二種解法呢,就不是求一組骰子序列了,而是求每次擲出的骰子分別是某種骰子的概率。比如說我看到結果後,我可以求得第一次擲骰子是D4的概率是0.5,D6的概率是0.3,D8的概率是0.2.第一種解法我會在下面說到,但是第二種解法我就不寫在這裏了,如果大家有興趣,我們另開一個問題繼續寫吧。

2)還是知道骰子有幾種(隱含狀態數量),每種骰子是什麼(轉換概率),根據擲骰子擲出的結果(可見狀態鏈),我想知道擲出這個結果的概率。
看似這個問題意義不大,因爲你擲出來的結果很多時候都對應了一個比較大的概率。問這個問題的目的呢,其實是檢測觀察到的結果和已知的模型是否吻合。如果很多次結果都對應了比較小的概率,那麼就說明我們已知的模型很有可能是錯的,有人偷偷把我們的骰子給換了。

3)知道骰子有幾種(隱含狀態數量),不知道每種骰子是什麼(轉換概率),觀測到很多次擲骰子的結果(可見狀態鏈),我想反推出每種骰子是什麼(轉換概率)。
這個問題很重要,因爲這是最常見的情況。很多時候我們只有可見結果,不知道HMM模型裏的參數,我們需要從可見結果估計出這些參數,這是建模的一個必要步驟。

問題闡述完了,下面就開始說解法。(0號問題在上面沒有提,只是作爲解決上述問題的一個輔助)

0.一個簡單問題
其實這個問題實用價值不高。由於對下面較難的問題有幫助,所以先在這裏提一下。
知道骰子有幾種,每種骰子是什麼,每次擲的都是什麼骰子,根據擲骰子擲出的結果,求產生這個結果的概率。

這裏寫圖片描述

解法無非就是概率相乘:

P=P(D6)P(D61)P(D6D8)P(D86)P(D8D8)P(D83)=131613181318

1.看見不可見的,破解骰子序列
這裏我說的是第一種解法,解最大似然路徑問題。
舉例來說,我知道我有三個骰子,六面骰,四面骰,八面骰。我也知道我擲了十次的結果(1 6 3 5 2 7 3 5 2 4),我不知道每次用了那種骰子,我想知道最有可能的骰子序列。

其實最簡單而暴力的方法就是窮舉所有可能的骰子序列,然後依照第零個問題的解法把每個序列對應的概率算出來。然後我們從裏面把對應最大概率的序列挑出來就行了。如果馬爾可夫鏈不長,當然可行。如果長的話,窮舉的數量太大,就很難完成了。
另外一種很有名的算法叫做Viterbi algorithm. 要理解這個算法,我們先看幾個簡單的列子。
首先,如果我們只擲一次骰子:

這裏寫圖片描述

看到結果爲1.對應的最大概率骰子序列就是D4,因爲D4產生1的概率是1/4,高於1/6和1/8.
把這個情況拓展,我們擲兩次骰子:

這裏寫圖片描述

結果爲1,6.這時問題變得複雜起來,我們要計算三個值,分別是第二個骰子是D6,D4,D8的最大概率。顯然,要取到最大概率,第一個骰子必須爲D4。這時,第二個骰子取到D6的最大概率是

P2(D6)=P(D4)P(D41)P(D4D6)P(D66)=13141316

同樣的,我們可以計算第二個骰子是D4或D8時的最大概率。我們發現,第二個骰子取到D6的概率最大。而使這個概率最大時,第一個骰子爲D4。所以最大概率骰子序列就是D4 D6。
繼續拓展,我們擲三次骰子:

這裏寫圖片描述

同樣,我們計算第三個骰子分別是D6,D4,D8的最大概率。我們再次發現,要取到最大概率,第二個骰子必須爲D6。這時,第三個骰子取到D4的最大概率是

P3(D4)=P2(D6)P(D6D4)P(D43)=12161314

同上,我們可以計算第三個骰子是D6或D8時的最大概率。我們發現,第三個骰子取到D4的概率最大。而使這個概率最大時,第二個骰子爲D6,第一個骰子爲D4。所以最大概率骰子序列就是D4 D6 D4。

寫到這裏,大家應該看出點規律了。既然擲骰子一二三次可以算,擲多少次都可以以此類推。我們發現,我們要求最大概率骰子序列時要做這麼幾件事情。首先,不管序列多長,要從序列長度爲1算起,算序列長度爲1時取到每個骰子的最大概率。然後,逐漸增加長度,每增加一次長度,重新算一遍在這個長度下最後一個位置取到每個骰子的最大概率。因爲上一個長度下的取到每個骰子的最大概率都算過了,重新計算的話其實不難。當我們算到最後一位時,就知道最後一位是哪個骰子的概率最大了。然後,我們要把對應這個最大概率的序列從後往前推出來。
2.誰動了我的骰子?
比如說你懷疑自己的六面骰被賭場動過手腳了,有可能被換成另一種六面骰,這種六面骰擲出來是1的概率更大,是1/2,擲出來是2,3,4,5,6的概率是1/10。你怎麼辦麼?答案很簡單,算一算正常的三個骰子擲出一段序列的概率,再算一算不正常的六面骰和另外兩個正常骰子擲出這段序列的概率。如果前者比後者小,你就要小心了。
比如說擲骰子的結果是:

這裏寫圖片描述

要算用正常的三個骰子擲出這個結果的概率,其實就是將所有可能情況的概率進行加和計算。同樣,簡單而暴力的方法就是把窮舉所有的骰子序列,還是計算每個骰子序列對應的概率,但是這回,我們不挑最大值了,而是把所有算出來的概率相加,得到的總概率就是我們要求的結果。這個方法依然不能應用於太長的骰子序列(馬爾可夫鏈)。
我們會應用一個和前一個問題類似的解法,只不過前一個問題關心的是概率最大值,這個問題關心的是概率之和。解決這個問題的算法叫做前向算法(forward algorithm)。
首先,如果我們只擲一次骰子:

這裏寫圖片描述

看到結果爲1.產生這個結果的總概率可以按照如下計算,總概率爲0.18:

這裏寫圖片描述

把這個情況拓展,我們擲兩次骰子:

這裏寫圖片描述

看到結果爲1,6.產生這個結果的總概率可以按照如下計算,總概率爲0.05:

這裏寫圖片描述

繼續拓展,我們擲三次骰子:

這裏寫圖片描述

看到結果爲1,6,3.產生這個結果的總概率可以按照如下計算,總概率爲0.03:

這裏寫圖片描述

同樣的,我們一步一步的算,有多長算多長,再長的馬爾可夫鏈總能算出來的。用同樣的方法,也可以算出不正常的六面骰和另外兩個正常骰子擲出這段序列的概率,然後我們比較一下這兩個概率大小,就能知道你的骰子是不是被人換了。

Viterbi algorithm

HMM(隱馬爾可夫模型)是用來描述隱含未知參數的統計模型,舉一個經典的例子:一個東京的朋友每天根據天氣{下雨,天晴}決定當天的活動{公園散步,購物,清理房間}中的一種,我每天只能在twitter上看到她發的推“啊,我前天公園散步、昨天購物、今天清理房間了!”,那麼我可以根據她發的推特推斷東京這三天的天氣。在這個例子裏,顯狀態是活動,隱狀態是天氣。

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

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

這裏寫圖片描述

僞碼如下:

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},
}

求解最可能的天氣

求解最可能的隱狀態序列是HMM的三個典型問題之一,通常用維特比算法解決。維特比算法就是求解HMM上的最短路徑(-log(prob),也即是最大概率)的算法。

稍微用中文講講思路,很明顯,第一天天晴還是下雨可以算出來:

  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[最後一天][下雨]和[最後一天][天晴]的概率,找出較大的哪一個對應的序列,就是最終結果。

算法的代碼可以在github上看到,地址爲:

https://github.com/hankcs/Viterbi

運行完成後根據Viterbi得到結果:

Sunny Rainy Rainy

Viterbi被廣泛應用到分詞,詞性標註等應用場景。

+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

以下來源於:知乎 作者 :傅睿卿
地址:https://www.zhihu.com/question/20962240/answer/34202445

粗略的看了一遍,覺得必須要說兩句,之前幾乎所有人答案都是在沒有具體應用方法的背景下講理論,在實際應用中反而會讓人迷糊,HMM用途大多數情況下不會是求隱變量的場合,隱變量具體是什麼在很多的學習、分類問題下都是無關緊要的!

—————以下正題—————-
首先說馬爾科夫,這是基礎,沒有這個一切都是胡鬧,之前很多答案並沒有過多的顧及馬爾科夫模型的問題,答案只能說是個隱概率模型。馬爾科夫模型描述的是當前狀態只和前一狀態相關的情況。
【先打比方】打麻將坐莊,比如現在是東風莊,那麼(理想情況下)下把有75%的概率是北風(被胡牌),25%還是東風(自己胡牌),而跟上一把是不是東風莊沒有任何關係。這就是一個標準的馬爾科夫過程,(考慮心裏因素時也可能不是,這裏不談)

【再說不恰當的案例】而最多舉得天氣的例子,就不是很合適,第一,明天下雨的概率現實中絕對不僅依賴於今天是不是晴天,這在建模時需要首先考慮模型的精度,注意,概率模型是以[你所認知的]世界爲基礎的,在某個問題下,你可以認爲全人類得癌症的概率是多少多少,在其他問題下,你可能認爲男性女性得癌症的概率分別是多少,這取決於模型的精度和你掌握的信息來定。絕大部分問題不是天生就是馬爾科夫的,首先,夏天冬天不一樣,梅雨季節更不一樣,用術語說,這是時變的,當然你可以在你的模型中忽略這些,”假裝”他是馬爾科夫的。

【再說具體點】作爲馬爾科夫的過程,就和HMM應用會扯上關係的問題來說,要注意,任何時候,當系統出於某一狀態時(也可以是以某一概率處於某些狀態),下週期處於狀態的概率要是確定的(比如剛說的75%,和25%,數值可以不知道,但一定是不會變的某個值),而不依賴於之前的狀態(前天)或系統的其他狀態(冬季)。

【如果數學一些】由於任何狀態遷移到其他狀態的概率是確定的,所以我們如果知道本週期的概率分佈,就可以求出下週期的分佈,方法用中學時代的描述就是分類討論,而本科階段開始就用矩陣乘簡單處理,這個就不多說了。要注意,能夠寫成矩陣(也就說概率是確定的)很重要。如果不是,那麼就是其他問題了,比如半隱馬爾科夫,如果有時間我下面會說,沒有的話先坑着。

—————-開始HMM,之後討論有什麼用,因爲你看完這段肯定不知道怎麼用———————–

HMM針對的問題,必須是一個上面規範定義的過程,爲什麼?因爲數學的求解能力是非常有限的,或許看似簡單的變化,導致的可能是不可接受的計算量,

【先說定義】所謂的隱,就是看不見的意思。借用一句有切身感覺的話說”當看到方便麪中油包變成固體的時候,宅男知道,冬天來了“。這裏的季節(冬天)就是隱藏起來的變量,宅男(觀察者)不出屋,所以看不到天氣,他只可以看到方便麪調料(這叫觀測)。所謂的HMM,用來描述一個我們看不到系統狀態,只能看到觀測(但觀測和狀態之間有確定性的概率關係)的狀態。

【需要強調的】第一就是剛剛的最後一句,觀測和系統的狀態之間必須有確定的概率關係,這個關係和系統的運行時間,之前的觀測,之前的狀態等等都不能有任何關係。也就是任何時候我看到固體的調料包,就代表(90%冬天,10%剛剛春天)。第二就是剛說到的,HMM是用來描述這樣一個系統使用的工具,就好像我們可以用矩陣代表一個線性方程組一樣。我們可以用HMM模型來表示一個這樣的系統,定義它的量包括:(1)每個觀測下,系統處於某狀態的概率,共計觀測類型系統狀態類型 個,(由於概率總和爲1,有效的量少觀測類型個)。(2)本週期系統處於某狀態時,下週期各狀態的概率分佈(就是剛剛馬爾科夫中的那個矩陣),數量爲 狀態類型 狀態類型 個(同上,有效的略少)。(3)系統的初始狀態分佈,就是第一週期時候系統是什麼樣子,這樣我們就可以計算出每週期的概率了。這個值一共有 狀態類型個(有效的少一個)
—————————-下面是怎麼用HMM—————————–
剛剛已經說過什麼是HMM了,就和高斯分佈一樣,HMM是描述系統分佈的一種手段,那我們怎麼用呢?(這裏我們只談用法思路,計算辦法網上很多,思路和模型本身關係不是那麼密切,就是算了)

【最常見的使用方法】我們說使用HMM時,一般時在解決這樣的一個問題:當我有一個觀測序列(樣本)時,它和我所有已經知道的HMM模型哪個最匹配。我們通常會爲每個我們預計要檢測的東西訓練一個HMM(用該類的大量樣本)。

【沿用剛剛的例子】剛在舉例子的時候沒想太周全,這裏就將就看吧。如果說我們可以用一個HMM描述宅男看方便麪的問題的話,那麼我們最可能幹的事情就是,通過觀察方便麪油包狀態,估計宅男所處的城市。是不是有點意外?居然不是看季節?其實HMM使用時最容易犯的錯誤就是弄混隱變量和我們的分類結果的關係了,關係就是沒有關係!我們首先選取了世界各地宅男看到的油包狀態,比如北京的1萬個宅男,深圳的1萬個,北冰洋的1萬個宅男各3年的觀察,作爲樣本,這時,我們系統一共涉及到了這樣幾個信息:(1)我們預計有3個HMM模型,分別是北京,深圳,北冰洋(2)我們只有2個觀測結果,即油包是固態還是液態(3)我們的隱變量通常並不明確,但本例中我們估計系統狀態可能是4季,所以我們設定4個隱變量,注意:這4個就代表四季在實際應用中完全就是猜的,而且不見得訓練的結果就是四季!

【解決例子中的問題】爲了完成這個工作,我們要幹以下幾步:(1)分別利用每個地區的1萬個樣本,各自訓練一個HMM,方法可參考網上各種文章。(2)在實際判斷一個宅男的地理位置時,拿到一個觀察序列,然後分別計算北京、深圳、北冰洋的HMM能夠得到這個觀測序列的概率。概率最大的,就是該宅男的所在提。

————————————–最後多說幾句————————————
HMM的求解是一個非常麻煩的事情,可以看成是一個EM迭代的過程,而且求解的變量非常多,這就直接導致了一些約束:(1)觀測的種類不能很多,尤其不能是連續過程(2)系統隱狀態也不宜太多(3)要檢測的目標,也就是HMM的數量,倒不是大問題,因爲這是線性增長的,多一倍求解時間只多一倍,一般都能接受

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