如何用簡單易懂的例子解釋隱馬爾可夫模型?

建議打開鏈接看原文
作者:肉很多
鏈接:https://www.zhihu.com/question/20962240/answer/33614574
來源:知乎
著作權歸作者所有,轉載請聯繫作者獲得授權。
WARNING:這篇文章是給零基礎人士看的。目標是讓普通初中生以及只有初中基礎人士無障礙理解HMM框架。追求數學嚴謹性人士、追求用簡潔符號表達模型的同學以及數理基礎良好的大神請自行移步參閱文獻。

講這種東西就得先搞清HMM到底幹了什麼,初學者很容易對“模型在幹嘛”這個問題上犯暈。我個人特別討厭跟初學者上來就講state space/transition matrix/emission probability云云的講法(注:比如《統計學習方法》李航博士那種講法。雖然用來準備面試很方便,但初學者肯定會被符號和幾個概念繞暈了;另外,私以爲他換掉符號和前人文獻不保持一致的做法又會讓初學者又多了一道坎去翻。總之,不太厚道)。因爲初學時,對大多非理科出身的人而言,用抽象的名詞與符號描述的“語言系統”還沒固化在腦袋裏。用抽象符號在那兒講就好比“一羣人還沒學會走,就逼着他們快點跑”。這是不太現實的。

綜上,用複雜抽象的語言描述不合適的,這個學習曲線過於陡峭,別人需要時間消化。基於此原因,我發現,對零基礎小夥伴們用遊戲的例子去類比地解釋往往比較容易降低學習難度,比如這樣講:

我是一戰士,修煉出了三種戰鬥形態,分別爲暴怒態,正常狀態和防禦態。同時我也會三個被動技能,分別是普通平A,爆擊(攻擊傷害翻倍),吸血(生命汲取)。
我在暴怒狀態下打出暴擊的概率是80%,打出吸血概率爲5%;
在平衡形態下,打出暴擊的比率爲30%,打出吸血的概率是20%;
在防禦形態下,暴擊成功概率爲5%,吸血概率爲60%。
總結一下,戰士在不同狀態下能打出技能的概率不一樣。

本來,戰士這個職業在暴怒態時,身邊會有一圈紅光環;防禦態時,會有一圈藍光環。但是,現在我正在玩遊戲,遊戲突然出了個bug:有個傻x程序員改了遊戲的代碼,他給寫崩了,從此戰士身邊光環都看不見了。那我沒法通過看腳下的光環知道戰士在爆什麼狀態了。

話說,現在問題來了:由於看不到腳下光環,我只能估計“戰士”在爆什麼狀態;但我現在打一boss,砍10次,發現8次都是暴擊,血嘩嘩地翻倍在掉,你覺得我這戰士最可能是爆了什麼狀態?

(每次用這個不規範的例子和新手講,他們立刻就懂了;而且他們接下來還會問:”’暴怒狀態’不能總持續吧?這不科學,應該限定個一段時間後,暴怒狀態消失的概率爲50%….”你瞧瞧連狀態轉換的transition prob自己都能假設出來了,都會搶答了都lol…“HMM的在幹什麼”的問題很容易地讓他們就理解了)

綜上,一個戰士的狀態會不斷隨時間變化;然後他的被動技能發動概率會因爲所處不同狀態而不同。這就是HMM想表達的東西。並且我們還可以通過它回答一些有趣的問題:通過戰士發動的技能來推測戰士所出的狀態。

這個例子只是個感性認識,它其實只是告訴了我們hmm比較“像什麼東西”。顯然,我們還需要更規範更嚴謹地去介紹什麼是HMM,去規範化這個模型。這個例子裏的“戰士”可以換成其它答案裏的天氣,換成硬幣等等。但無論用什麼說法,我們已經能通過這個例子抓住核心問題了:HMM模型就是這樣一個系統——它有一個能不斷改變的隱藏的狀態(在這個例子裏就是戰士爆的狀態。它會變,而且由於一個碼農的緣故,狀態變得不可見)在持續地影響它的外在表現(在這個例子裏就是戰士打出的技能是暴擊、平a、還是吸血的概率)。再重複一遍:HMM模型就是這樣一個系統——它有一個會隨時間改變的隱藏的狀態,在持續地影響它的外在表現。

現在我們再繼續規範一下這個例子,讓它更貼近那種嚴謹描述。
因爲我們知道戰士打人總爆擊,角色特別bug,這沒法玩啊。所以我們要限制一下戰士爆狀態。
我們在遊戲裏做了個限制:
我們設定,戰士一開始進入遊戲世界時是正常狀態的。而且,每過一段時間(比如1分鐘),戰士就會自動爆一次狀態。最後,每一次爆發還和上一次狀態爆的狀態是什麼有關:
1.上一次如果是正常狀態,那下次變爲暴怒的概率比較大。下次轉換成暴怒狀態,平衡狀態或防禦狀態的概率我們假設分別爲60%,30%,10%。這保證了戰士職業下次能有較大的概率能打出暴擊!
2.同理,若當我們上次在暴怒態時,下次繼續保持暴怒態的概率就得限制一下。下次繼續保持暴怒的概率就設爲10%,而轉換成正常狀態的概率是60%,轉換成防禦態的概率是30%;
3.如果上次是防禦態,那麼我們也讓它下次也儘量變正常。(不然總吸血啊)那他下次轉成其它三態的概率(三態和以上對應書寫順序一致)分別爲爲10%,60,30%。
這樣服務器就能限制戰士的爆暴怒態的次數,讓它不那麼imba。

順便提一下,其實以上的這種限定——讓戰士下一次爆不同狀態的概率只和上次處在什麼狀態有關係——叫馬爾可夫性質(markov property)。
經過這樣的設定後,不僅僅戰士這個職業不會那麼imba,而且,我們可以靠以上這些數字來計算之前只能感性理解的問題了。比如:我這個戰士在第一分鐘的時候是正常狀態,那麼我第二分鐘趕去死亡谷打一個boss能暴擊的概率是多少?(這個當作思考題,提示:想想兩個問題,上一狀態和下一狀態間轉換的概率是多少?不同狀態下發不同技能的概率是多少?)

最後總結一下。以上例子中講明瞭HMM的五樣“要素”:
1.狀態和狀態間轉換的概率
2.不同狀態下,有着不同的外在表現的概率。
3.最開始設置的初始狀態
4.能轉換的所有狀態的集合
5.能觀察到外在表現的結合

Hidden 說明的是狀態的不可見性;Markov說明的是狀態和狀態間是markov chain。這就是爲什麼叫Hidden Markov Model。

我相信你們再去看其它答案裏寫的就明白多了。

ps:懂了是什麼之後再去看paper就好多了。沒記錯的話去,看《A tutorial on Hidden Markov Models and selected applications in Speech recognition》。另外,HMM除了上文提到的“五要素”,還有“三個基本問題”。這文章將hmm的三個基本問題講得很清楚。

進化版:
作者:Yang Eninala
鏈接:https://www.zhihu.com/question/20962240/answer/33438846
來源:知乎
著作權歸作者所有,轉載請聯繫作者獲得授權。
隱馬爾可夫(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.一個簡單問題
其實這個問題實用價值不高。由於對下面較難的問題有幫助,所以先在這裏提一下。

知道骰子有幾種,每種骰子是什麼,每次擲的都是什麼骰子,根據擲骰子擲出的結果,求產生這個結果的概率。解法無非就是概率相乘:
解法無非就是概率相乘:

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的最大概率是

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

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

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

同上,我們可以計算第三個骰子是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:

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

3.擲一串骰子出來,讓我猜猜你是誰
(答主很懶,還沒寫,會寫一下EM這個號稱算法的方法)

上述算法呢,其實用到了遞歸,逆向推導,循環這些方法,我只不過用很直白的語言寫出來了。如果你們去看專業書籍呢,會發現更加嚴謹和專業的描述。畢竟,我只做了會其意,要知其形,還是要看書的。

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