# [白話解析]以水滸傳為例學習隱馬爾可夫模型 ## 0x00 摘要 本文將盡量使用易懂的方式,儘可能不涉及數學公式,而是從整體的思路上來看,運用感性直覺的思考來解釋隱馬爾可夫模型。並且從名著中找了個具體應用場景來幫助大家深入這個概念。 ## 0x01 說明 在機器學習過程中,會遇到很多晦澀的概念,相關數學公式很多,大家理解起來很有困難。遇到類似情況,我們應該多從直覺角度入手思考,用類別或者舉例來**附會**,這樣往往會有更好的效果。 我在講解論述過程中給自己的要求是:在生活中或者名著中找一個例子,然後用自己的話語闡述出來。 ## 0x02 概率圖 概率圖模型是用圖來表示變數概率依賴關係的理論,結合概率論與圖論的知識,利用圖來表示與模型有關的變數的聯合概率分佈。由圖靈獎獲得者Pearl開發出來。 如果用一個詞來形容概率圖模型(Probabilistic Graphical Model)的話,那就是“優雅”。對於一個實際問題,我們希望能夠挖掘隱含在資料中的知識。概率圖模型構建了這樣一幅圖,用觀測結點表示觀測到的資料,用隱含結點表示潛在的知識,用邊來描述知識與資料的相互關係,**最後基於這樣的關係圖獲得一個概率分佈**,非常“優雅”地解決了問題。 概率圖中的節點分為隱含節點和觀測節點,邊分為有向邊和無向邊。從概率論的角度,節點對應於隨機變數,邊對應於隨機變數的依賴或相關關係,其中**有向邊表示單向的依賴,無向邊表示相互依賴關係**。 概率圖模型分為**貝葉斯網路(Bayesian Network)和馬爾可夫網路(Markov Network)**兩大類。貝葉斯網路可以用一個有向圖結構表示,馬爾可夫網路可以表 示成一個無向圖的網路結構。更詳細地說,概率圖模型包括了樸素貝葉斯模型、最大熵模型、隱馬爾可夫模型、條件隨機場、主題模型等,在機器學習的諸多場景中都有著廣泛的應用。 ## 0x03 生成式模型和判別式模型的區別 現在我們知道,概率圖可以分成有向圖模型和無向圖模型,顧名思義,就是圖裡面的邊是否有方向。那麼什麼樣的模型的邊有方向,而什麼樣的沒方向呢?這個很好想到,有方向的表達的是一種推演關係,也就是在A的前提下出現了B,這種模型又叫做生成式模型。而沒有方向表達的是一種“這樣就對了”的關係,也就是A和B同時存在就對了,這種模型又叫做判別式模型。 根據建模的究竟是聯合概率分佈 P(x,y) 還是條件概率分佈 P(y|x)。派生出生成式模型與判別式模型。 ### 1. 生成式模型 生成式模型一般用聯合概率計算(因為我們知道A的前提了,可以算聯合概率),即通過對觀測值和標註資料計算聯合概率分佈P(x,y)來達到判定估算y的目的。 生成式模型是模擬資料的生成過程,兩類隨機變數存在因果先後關係,先有因素 x,後有結果 y,這種因果關係由聯合分佈模擬: $$ P(x,y) = P(x)P(y|x) $$ 通過聯合分佈 P(x,y),生成式模型其實間接建模了 P(x): $$ P(x) = \sum_y P(x,y) $$ 需要注意的是,在模型訓練中,我學習到的是X與Y的聯合模型 P(X,Y) ,也就是說,**我在訓練階段是隻對** P(X,Y)**建模**,我需要確定維護這個聯合概率分佈的所有的資訊引數,要對每個label (y) 都需要建模。所以沒有什麼判別邊界。 完了之後在inference再對新的sample計算P(Y|X),匯出 Y,最終選擇最優概率的label為結果,但這已經不屬於建模階段了。 這裡有兩個缺陷: - P(x) 很難準確估計,因為特徵之間並非相互獨立,而是存在錯綜複雜的依賴關係。 - P(x) 在分類中也沒有直接作用。 為了克服這兩個問題,判別式模型出現。 ### 2. 判別式模型 判別式模型一般用條件概率計算(因為我們不知道前提,所以只能"假設"A條件下B的概率)。即通過求解條件概率分佈P(y|x)或者直接計算y的值來預測y。 判別式模型直接跳過了 P(x),直接對條件概率 P(y|x) 建模,就是說,直接根據X特徵來對Y建模訓練。不管 x 內部存在多複雜的關係,也不影響判別式模型對 y 的判斷,於是就能夠**放心大膽的利用各種各樣豐富的、有關聯的特徵**。 具體地,我的訓練過程是確定構件 P(Y|X) 模型裡面“複雜對映關係”中的引數,對所有的樣本只構建一個模型,確認總體判別邊界。完了再去inference一批新的sample。觀測到輸入什麼特徵,就預測最可能的label。 ### 3. 代表 生成式模型的代表是:n元語法模型、隱馬爾可夫模型、樸素貝葉斯模型等。 判別式模型的代表是:最大熵模型、支援向量機、條件隨機場、感知機模型等 他們之間的區別是這樣的: > 判別式模型是這麼工作的,他們直接將資料的Y(或者label),根據所提供的features,學習,最後畫出了一個明顯或者比較明顯的邊界(具體怎麼做到的?通過複雜的函式對映,或者決策疊加等等mechanism),這一點線性LR、線性SVM應該很明顯吧。 > > > > 生成式模型是這麼工作的,他們先從訓練樣本資料中,將所有的資料的分佈情況摸透,然後最終確定一個分佈,來作為我的所有的輸入資料的分佈,並且他是一個聯合分佈 P(X,Y) (注意X包含所有的特徵x_i ,Y包含所有的label)。然後我來了新的樣本資料(inference),好,通過學習來的模型的聯合分佈P(X,Y) ,再結合新樣本給的X,通過條件概率就能出來Y > $$ > P(類別|特徵) = \frac {P(特徵|類別)P(類別)}{P(特徵)} > $$ **** ## 0x04 馬爾可夫系列概念 提到馬爾可夫就是一個值跟前面n個值有關,所以也就是條件概率,也就是生成式模型,也就是有向圖模型。 **馬爾可夫假設**:每個事件的發生概率只取決於前一個事件。 **馬爾可夫鏈**:將滿足馬爾可夫假設的連續多個事件串聯起來,就構成了馬爾可夫鏈。馬爾科夫鏈的節點是狀態,邊是轉移概率,是template CPD的一種有向狀態轉移表達。 馬爾可夫鏈的兩個假設 - 齊次馬爾可夫假設:即t時刻的狀態只受t-1時刻狀態的影響; - 觀測獨立性假設:即任意時刻的觀測只受該時刻所處狀態的影響; **馬爾科夫模型 ** 是一種無向概率圖模型,其與馬爾科夫鏈並不是很一樣。馬爾科夫模型是與貝葉斯模型並列的一種概率圖模型。其作用是描述互相影響,互相作用,不存在因果關係的兩個隨機變數之間的關係。因為作用是相互的,所有馬爾科夫模型的邊是無向的,或者可以說是雙向的。 馬爾科夫模型的強大之處在於它解除了貝葉斯模型中的因果關係,這也就使得它可以對很多平等的東西建立相互關係。比如一幅圖片的各個畫素就是平等的,但是各個畫素之間可以相互影響(天在上,地在下)。所有馬爾科夫模型被廣泛的應用於影象處理/影象理解。 如果把事件具象為單詞,那麼馬爾可夫模型就具象為二元語法模型。馬爾可夫模型還可以看成是一個關於時間t的狀態轉換過程,也就是隨機的有限狀態機,那麼狀態序列的概率可以通過計算形成該序列所有狀態之間轉移弧上的概率乘積得出。 ## 0x05 隱馬爾可夫模型 隱馬爾可夫模型(Hidden Markov Model,HMM)是統計模型,它用來描述一個含有隱含未知引數的馬爾可夫過程。即描述一個系統隱性狀態的轉移和隱性狀態的表現概率。系統的隱性狀態指的就是一些外界不便觀察(或觀察不到)的狀態。其難點是從可觀察的引數中確定該過程的隱含引數。然後利用這些引數來作進一步的分析。 HMM是一種生成式模型,它的理論基礎是樸素貝葉斯,本質上就類似於我們將樸素貝葉斯在單樣本分類問題上的應用推廣到序列樣本分類問題上。 比如,HMM是描述兩個時序序列聯合分佈 p(x,y) 的概率模型。 - x 序列外界可見(外界指的是觀測者),稱為**觀測序列**(obsevation sequence); - y 序列外界不可見,稱為**狀態序列**(state sequence)。 比如觀測 x 為單詞,狀態 y 為詞性,我們需要根據單詞序列去猜測它們的詞性。 一個馬爾科夫過程是狀態間的轉移僅依賴於前n個狀態的過程。這個過程被稱之為n階馬爾科夫模型,其中n是影響下一個狀態選擇的(前)n個狀態。最簡單的馬爾科夫過程是一階模型,它的狀態選擇僅與前一個狀態有關。這裡要注意它與確定性系統並不相同,因為下一個狀態的選擇由相應的概率決定,並不是確定性的。 隱馬爾可夫模型之所以稱為“隱”,是因為從外界來看,狀 態序列(例如詞性)隱藏不可見,是待求的因變數。從這個角度來講,人們也稱 y 狀態為隱狀態(hidden state),而稱觀測 x 為顯狀態( visible state)“隱”指的是其中某一階的資訊我們不知道,就像是我們知道人的祖先是三葉蟲,但是由三葉蟲經歷了怎樣的演變過程才演變到人的樣子我們是不知道的,我們只能通過化石資料瞭解分佈資訊,如果這類資料很多,那麼就可以利用隱馬爾可夫模型來建模,因為缺少的資訊較多,所以這一模型的演算法比較複雜。 狀態與觀測之間的依賴關係確定之後,隱馬爾可夫模型利用三個要素來模擬時序序列的發生過程----即**初始狀態概率向量、狀態轉移概率矩陣和發射概率矩陣**。 ### 1. 隱馬爾可夫三大問題 - **概率計算問題**:給定模型,如何有效計算產生觀測序列的概率?換言之,如何評估模型與觀測序列之間的匹配程度? - **預測問題**:給定模型和觀測序列,如何找到與此觀測序列最匹配的狀態序列?換言之,如何根據觀測序列推斷出隱藏的模型狀態? - **學習問題**:給定觀測序列,如何調整模型引數使得該序列出現的概率最大?換言之,如何訓練模型使其能最好地描述觀測資料? 前兩個問題是模式識別的問題:1) 根據隱馬爾科夫模型得到一個可觀察狀態序列的概率(**評價**),被用來測量一個模型的相對適用性;2) 找到一個隱藏狀態的序列使得這個序列產生一個可觀察狀態序列的概率最大(**解碼**),即用來推測模型隱藏的部分在做什麼(“到底發生了”什麼)。第三個問題就是根據一個可以觀察到的狀態序列集產生一個隱馬爾科夫模型(**學習**)。 第二個問題是隱馬爾可夫模型的核心,很多領域對隱馬爾可夫模型的應用大部分會是問題(2),比如在機器翻譯做中文對英文的翻譯時,單詞的翻譯總是有很多個意思,而詞性往往起到很重要的作用,乍一看詞性這一序列怎麼跟我們說到的隱含的狀態序列=()很像呢!類似這樣的還有很多....... 對應的三大問題解法: 1. 向前演算法(Forward Algorithm)、向後演算法(Backward Algorithm) 2. 維特比演算法(Viterbi Algorithm) 3. 鮑姆-韋爾奇演算法(Baum-Welch Algorithm) (約等於EM演算法) 網上經典例子 > 小明現在有三天的假期,他為了打發時間,可以在每一天中選擇三件事情來做,這三件事情分別是散步、購物、打掃衛生(**對應著可觀測序列**),可是在生活中我們所做的決定一般都受到天氣的影響,可能晴天的時候想要去購物或者散步,可能下雨天的時候不想出門,留在家裡打掃衛生。而天氣(晴天、下雨天)就屬於隱藏狀態, > > 那麼,我們提出三個問題,分別對應馬爾可夫的三大問題: > > 1. 已知整個模型,我觀測到連續三天做的事情是:散步,購物,收拾。那麼,根據模型,計算產生這些行為的概率是多少。 > 2. 同樣知曉這個模型,同樣是這三件事,我想猜,這三天的天氣是怎麼樣的。 > 3. 最複雜的,我只知道這三天做了這三件事兒,而其他什麼資訊都沒有。我得建立一個模型,晴雨轉換概率,第一天天氣情況的概率分佈,根據天氣情況選擇做某事的概率分佈。 ### 2. 隱馬爾可夫的難點/建模 其實對於HMM來說,如果提前知道所有隱含狀態之間的轉換概率和所有隱含狀態到所有可見狀態之間的輸出概率,做模擬是相當容易的。但是應用HMM模型時候呢,往往是缺失了一部分資訊的,如何應用演算法去估計這些缺失的資訊,就成了一個很重要的問題。這些東西就是HMM要解決的問題。 觀察到的狀態序列與隱藏過程有一定的概率關係。我們使用隱馬爾科夫模型對這樣的過程建模,這個模型包含了一個底層隱藏的隨時間改變的馬爾科夫過程,以及一個與隱藏狀態某種程度相關的可觀察到的狀態集合。 我們使用一個隱馬爾科夫模型(HMM)對這些例子建模。這個模型包含兩組狀態集合和三組概率集合: - 隱藏狀態:一個系統的(真實)狀態,可以由一個馬爾科夫過程進行描述。 - 觀察狀態:在這個過程中‘可視’的狀態。 - pi向量:包含了(隱)模型在時間t=1時一個特殊的隱藏狀態的概率(初始概率)。 - 狀態轉移矩陣:包含了一個隱藏狀態到另一個隱藏狀態的概率 - 混淆矩陣:包含了給定隱馬爾科夫模型的某一個特殊的隱藏狀態,觀察到的某個觀察狀態的概率。 因此一個隱馬爾科夫模型是在一個標準的馬爾科夫過程中引入一組觀察狀態,以及其與隱藏狀態間的一些概率關係。 ## 0x06 水滸傳中的隱馬爾可夫應用 水滸傳中,樑中書突圍大名府就是個 **可以被改造以便於說明的** 隱馬爾可夫(HMM)案例。 > 卻說樑中書正在衙前醉了閒坐,初聽報說,尚自不甚慌;次後沒半個更次,流星探馬,接連報來,嚇得魂不附體,慌忙快叫備馬。說言未了,只見翠雲樓上,烈焰沖天,火光奪月,十分浩大。樑中書見了,急上得馬,卻待要去看時,只見兩條大漢,推兩輛車子,放在當路,便去取碗掛的燈來,望車子上點著,隨即火起。樑中書要出東門時,兩條大漢口稱:“李應、史進在此!”手拈朴刀,大踏步殺來。把門官軍,嚇得走了,手邊的傷了十數個。杜遷、宋萬卻好接著出來,四個合做一處,把住東門。樑中書見不是頭勢,帶領隨行伴當,飛奔南門。南門傳說道:“一個胖大和尚,掄動鐵禪杖;一個虎面行者,掣出雙戒刀,發喊殺入城來。”樑中書回馬,再到留守司前,只見解珍、解寶手拈鋼叉,在那裡東撞西撞;急待回州衙,不敢近前。王太守卻好過來,劉唐、楊雄兩條水火棍齊下,打得腦漿迸流,眼珠突出,死於街前。虞候押番,各逃殘生去了。樑中書急急回馬奔西門,只聽得城隍廟裡,火炮齊響,轟天震地。鄒淵、鄒潤手拿竹竿,只顧就房簷下放起火來。南瓦子前,王矮虎、一丈青殺將來。孫新、顧大嫂身邊掣出暗器,就那裡協助。銅寺前,張青、孫二孃入去,爬上鰲山,放起火來。此時北京城內百姓黎民,一個個鼠攛狼奔,一家家神號鬼哭,四下裡十數處火光亙天,四方不辨。 >   卻說樑中書奔到西門,接著李成軍馬,急到南門城上,勒住馬,在鼓樓上看時,只見城下兵馬擺滿,旗號上寫道:“大將呼延灼。”火焰光中,抖擻精神,施逞驍勇;左有韓滔,右有彭玘,黃信在後,催動人馬,雁翅一般橫殺將來,隨到門下。樑中書出不得城去,和李成躲在北門城下,望見火光明亮,軍馬不知其數,卻是豹子頭林沖,躍馬橫槍,左有馬麟,右有鄧飛,花榮在後,催動人馬,飛奔將來。再轉東門,一連火把叢中,只見沒遮攔穆弘,左有杜興,右有鄭天壽,三籌步軍好漢當先,手拈朴刀,引領一千餘人,殺入城來。樑中書徑奔南門,捨命奪路而走。吊橋邊火把齊明,只見黑旋風李逵,左有李立,右有曹正。李逵渾身脫剝,咬定牙根,手雙斧,從城濠裡飛殺過來。李立、曹正,一齊俱到。李成當先,殺開條血路,奔出城來,護著樑中書便走。只見左手下殺聲震響,火把叢中,軍馬無數,卻是大刀關勝,拍動赤兔馬,手舞青龍刀,徑搶樑中書。李成手舉雙刀,前來迎敵。那 > 李成無心戀戰,撥馬便走。左有宣贊,右有郝思文,兩肋裡撞來。孫立在後,催動人馬,併力殺來。正鬥間,背後趕上小李廣花榮,拈弓搭箭,射中李成副將,翻身落馬。李成見了,飛馬奔走,未及半箭之地,只見右手下鑼鼓亂鳴,火光奪目,卻是霹靂火秦明躍馬舞棍,引著燕順、歐鵬,背後楊志,又殺將來。李成且戰且走,折軍大半,護著樑中書,衝路走脫。 突圍有四個選擇:東南西北四門。每個門都有不同的梁山好漢。現在樑中書面對的梁山好漢就構成了一條人名鏈。 比如去南門,遇見武松,再去東門,遇見史進,再去北門,遇見林沖,再去西門,遇見宋江。 那麼能得到如下一串好漢名字:武松,史進,林沖,宋江這串好漢名字叫做可見狀態鏈。但是在隱馬爾可夫模型中,我們不僅僅有這麼一串可見狀態鏈,還有一串隱含狀態鏈。在這個例子裡,這串隱含狀態鏈就是樑中書選擇門的序列: 南門,東門,北門,西門。 後續我們就圍繞 ***樑中書*** 遇見以下各位好漢來說明: **武松,史進,林沖,宋江** ### 1. 狀態轉移矩陣 狀態轉移矩陣包含了一個隱藏狀態到另一個隱藏狀態的概率。一般來說,HMM中說到的馬爾可夫鏈其實是指隱含狀態鏈,因為隱含狀態(城門)之間存在轉換概率(transition probability)。 比如,樑中書在西門突圍失敗之後,下一個狀態是南門,東門,北門,西門的概率都是1/4。這樣設定是為了容易說清楚。但是我們其實是可以隨意設定轉換概率的。比如,我們可以這樣定義規則如下: ```java * 順時針如下:東門 ----> 南門 ----> 西門 ----> 北門 ---> 東門 ---> ... * 已經到達某門,再次選擇此門的概率是1/8,比如 東門 ---> 東門 (不大可能再次原地突圍) * 已經到達某門,如果順時針或者逆時針選擇下一個門的概率是3/8, 比如 東門 ----> 南門 或者 東門 ----> 北門 * 已經到達某門,選擇 正對門 的概率是1/8, 比如 東門 ----> 西門 (不大可能選擇穿過大名府去對面城門突圍) ``` 狀態轉移矩陣如下: $$ A= \left\{ \begin{matrix} \frac18 & \frac38 & \frac18 & \frac38\\ \frac38 & \frac18 & \frac38 & \frac18\\ \frac18 & \frac38 & \frac18 & \frac38\\ \frac38 & \frac18 & \frac38 & \frac18\\ \end{matrix} \right\} $$ ### 2. 混淆矩陣 混淆矩陣:包含了給定隱馬爾科夫模型的某一個特殊的隱藏狀態,觀察到的某個觀察狀態的概率。即儘管可見狀態之間沒有轉換概率,但是隱含狀態和可見狀態之間有一個概率叫做輸出概率(emission probability)。 水滸傳真實總結出的四個門對應的梁山好漢是: ```java * 水滸傳真實總結 * 南門: 武松,魯智深,呼延灼,韓滔,彭杞,黃信,李逵,李立,曹正,關勝,宣贊,郝思文,孫立,秦明,燕順、歐鵬,楊志。 * 東門:李應,史進,穆弘,杜興,鄭天壽 * 北門:林沖,馬麟,鄧飛,花榮 * 西門:梁山好漢大部軍馬。 * 真實中,北門遇見林沖的概率是1/4, 南門遇見武松的概率是1/17。 ``` 但這些是確定的概率,沒法說明我們的HMM模型。 所以我們需要從樑中書/吳學究的角度改造。假設吳學究派兵部署時候,給每個好漢分配到每個門是有一定概率的,也就是說,樑中書在去了某門之後,遇到某一好漢是有一定概率的。 我們這裡是簡化版本,只給定幾位好漢:**武松,史進,林沖,宋江**。 ```java * 以下為吳學究派兵時候,每個好漢分配到每個門的概率 * 南門:武松 1/2,史進 1/4,林沖 1/8,宋江 1/8 * 東門:武松 1/4,史進 1/2,林沖 1/8,宋江 1/8 * 北門:武松 1/8,史進 1/8,林沖 1/2,宋江 1/4 * 西門:武松 1/8,史進 1/8,林沖 1/4,宋江 1/2 * 就我們的例子來說,樑中書在北門 遇到武松的概率是1/8,遇見史進的概率是1/8,遇見林沖的概率是1/2,...... ``` 混淆矩陣如下: $$ B = \left\{ \begin{matrix} \frac12 & \frac14 & \frac18 & \frac18\\ \frac14 & \frac12 & \frac18 & \frac18\\ \frac18 & \frac18 & \frac12 & \frac14\\ \frac18 & \frac18 & \frac14 & \frac12\\ \end{matrix} \right\} $$ 在狀態轉移矩陣及混淆矩陣中的每一個概率都是時間無關的——也就是說,當系統演化時這些矩陣並不隨時間改變。實際上,這是馬爾科夫模型關於真實世界最不現實的一個假設。 ### 3. pi向量(初始概率) 梁山大部軍馬在西門偷襲李成,樑中書去西門可能性甚小,去東門可能性最大 ```java * 南門: 1/4 * 東門:7/16 * 北門:1/4 * 西門:1/16 ``` pi向量如下: $$ pi= \left\{ \begin{matrix} \frac14 \\ \frac7{16} \\ \frac14 \\ \frac1{16} \\ \end{matrix} \right\} $$ ## 0x07 水滸傳HMM對應的三類問題 ### 1. 序列概率過程 --- 估計(Evaluation) **概率計算問題**:給定模型,如何有效計算產生觀測序列的概率。即根據隱馬爾科夫模型得到一個可觀察狀態序列的概率(**評價**)。 ```java 結合我們水滸傳的例子,就是已經知道門有幾種(隱含狀態數量),每種門是什麼(轉換概率),根據"選門之後看到哪位好漢"的結果(可見狀態鏈),我想知道看到這個結果的概率。 比如連續三次,看到的人分別是:武松,史進,林沖。那麼根據模型,計算產生這些行為的概率是多少。 ``` #### 1.1 直接計演算法(窮舉搜尋) 列舉所有可能的狀態序列,然後**計算每種狀態序列情況下的觀測序列概率,最後求和**。時間複雜度非常高,對於每一個t,都有N種隱藏狀態,那整個序列T的所有可能就是N的T次方,然後求和又是T的所有複雜度。 #### 1.2 前向演算法(基本動態規劃思想) 我們使用前向演算法(forward algorithm)來計算給定隱馬爾科夫模型(HMM)後的一個觀察序列的概率,並因此選擇最合適的隱馬爾科夫模型(HMM)。 這個演算法採用了DP思想,減少計算量,即每一次直接引用前一個時刻的計算結果以避免重複計算,跟Viterbi一樣的技巧相應地,其時間複雜度與T成線性關係。 給定一個隱馬爾科夫模型(HMM),我們將考慮遞迴地計算一個觀察序列的概率。我們首先定義區域性概率(partial probability),它是到達網格中的某個中間狀態時的概率。對於最後的觀察狀態,其區域性概率包括了通過所有可能的路徑到達這些狀態的概率。由此可見,對於這些最終區域性概率求和等價於對於網格中所有可能的路徑概率求和,也就求出了給定隱馬爾科夫模型(HMM)後的觀察序列概率。 **注:窮舉搜尋的時間複雜度是2TN^T,前向演算法的時間複雜度是N^2T,其中T指的是觀察序列長度,N指的是隱藏狀態數目。** ### 2. 序列標註過程 --- 解碼(Decoding) **預測問題**:給定模型和觀測序列,如何找到與此觀測序列最匹配的狀態序列?換言之,如何根據觀測序列推斷出隱藏的模型狀態?對於一個特殊的隱馬爾科夫模型(HMM)及一個相應的觀察序列,我們常常希望能找到生成此序列最可能的隱藏狀態序列。 ```java 結合我們水滸傳的例子就是,知道門有幾種(隱含狀態數量),每種門是什麼(轉換概率),根據"選門之後看到哪位好漢"的結果(可見狀態鏈),我想知道每次選中的是哪個門(隱含狀態鏈)。 比如連續三次,看到的人分別是:武松,史進,林沖。那麼這三次每次選的是哪個門? ``` 我現在要在給定的觀測序列下找出一條隱狀態序列,條件是這個隱狀態序列的概率是最大的那個。 #### 2.1 Viterbi 演算法 可以使用Viterbi 演算法(Viterbi algorithm)確定(搜尋)已知觀察序列及HMM下最可能的隱藏狀態序列。 維特比演算法致力於尋找一條最佳路徑,以便能最好地解釋觀測到的序列。我們可以通過列出所有可能的隱藏狀態序列並且計算對於每個組合相應的觀察序列的概率來找到最可能的隱藏狀態序列。最可能的隱藏狀態序列是使下面這個概率最大的組合:       Pr(觀察序列|隱藏狀態的組合) 這個思想的基礎是這樣的,如果從p1到pN存在一條最好的路是k,如果這條路k經過了p‘,則p’到pN一定是最優的,如果不是最優的,就存在另外一條路k‘,他的p’到pN更好,那這條路就不是k了,矛盾。所以我們只要找到最大概率的最後一個結點,然後一步一步向前就能求出來最優路徑。 具體在應用中,維特比演算法對於網格中的每一個單元(cell)都計算一個區域性概率,同時包括一個反向指標用來指示最可能的到達該單元的路徑。我們首先定義區域性概率,它是到達網格中的某個特殊的中間狀態時的概率。這些區域性概率與前向演算法中所計算的區域性概率是不同的,因為它們表示的是時刻t時到達某個狀態最可能的路徑的概率,而不是所有路徑概率的總和。當完成整個計算過程後,首先在終止時刻找到最可能的狀態,然後通過反向指標(這個指標指向最優的引發當前狀態的前一時刻的某個狀態)回溯到t=1時刻,這樣回溯路徑上的狀態序列就是最可能的隱藏狀態序列了。 ### 3. 學習問題(Learning) **學習問題**:給定觀測序列,如何調整模型引數使得該序列出現的概率最大?換言之,如何訓練模型使其能最好地描述觀測資料?即根據一個可以觀察到的狀態序列集產生一個隱馬爾科夫模型(**學習**)。 ```java 結合我們水滸傳的例子就是,知道門有幾種(隱含狀態數量),不知道每種門是什麼(轉換概率),觀測到很多次"選門之後看到哪位好漢"的結果(可見狀態鏈),我想反推出每種門是什麼(轉換概率)。 比如連續三次,樑中書看到的人分別是:武松,史進,林沖。而其他什麼資訊都沒有。要建立一個模型,找出各種門之間轉換概率,當然也有這些門外他遇到好漢的概率分佈。 ``` 很多時候我們只有可見結果,不知道HMM模型裡的引數,我們需要從可見結果估計出這些引數,這是建模的一個必要步驟。 這個問題,也是與HMM相關的問題中最難的,根據一個觀察序列(來自於已知的集合),以及與其有關的一個隱藏狀態集,估計一個最合適的隱馬爾科夫模型(HMM),也就是確定對已知序列描述的最合適的(pi,A,B)三元組。 #### 3.1 監督學習演算法——頻數/總數就是概率 首先監督學習演算法,就是資料足夠,然後人工標註好,其實你只需要統計出來各種頻數就可以了。 比如分詞的時候: 統計B到E的頻數,B到M的頻數什麼的都能求出來,轉移矩陣A有了。每個字分別為BEMS的頻數,觀測矩陣B有了 樣本中第一個字為B和S分別的概率。初始概率PI有了。然後就解決問題了,其實分詞就是這樣的,在人工標註好的資料集上統計就好了。 #### 3.2 非監督學習演算法——鮑姆-韋爾奇演算法 沒有標註的情況下,你只有一堆句子(假設句子長短一致,都是T個字),這時候矩陣A和B不能夠直接被(估計)測量,學習這些引數,就要用EM演算法對於HMM引數學習問題的適配版——Baum-Welch演算法。 **引數學習演算法又叫前向後向演算法**。要是計算整個序列的概率,前向就解決了。要是計算整個序列某個子序列出現的概率,那就必須要兩者一起來算了。 ## 0x08 參考程式碼 ### UMDHMM(Hidden Markov Model Toolkit): Hidden Markov Model (HMM) Software: Implementation of Forward-Backward, Viterbi, and Baum-Welch algorithms. 這款屬於輕量級的HMM版本。UMDHMM主頁:http://www.kanungo.com/software/software.html #### **前向演算法程式(forward.c)** ```c /* 函式引數說明:   *phmm:已知的HMM模型;T:觀察符號序列長度;   *O:觀察序列;**alpha:區域性概率;*pprob:最終的觀察概率 */ void Forward(HMM *phmm, int T, int *O, double **alpha, double *pprob) {   int i, j;   /* 狀態索引 */   int t;    /* 時間索引 */   double sum; /*求區域性概率時的中間值 */   /* 1. 初始化:計算t=1時刻所有狀態的區域性概率alpha: */   for (i = 1; i <= phmm->N; i++)     alpha[1][i] = phmm->pi[i]* phmm->B[i][O[1]];      /* 2. 歸納:遞迴計算每個時間點,t=2,... ,T時的區域性概率 */   for (t = 1; t < T; t++) {      for (j = 1; j <= phmm->N; j++) {       sum = 0.0;       for (i = 1; i <= phmm->N; i++)         sum += alpha[t][i]* (phmm->A[i][j]);       alpha[t+1][j] = sum*(phmm->B[j][O[t+1]]);     }   }   /* 3. 終止:觀察序列的概率等於T時刻所有區域性概率之和*/   *pprob = 0.0;   for (i = 1; i <= phmm->N; i++)     *pprob += alpha[T][i]; } ``` #### **維特比演算法程式(viterbi.c)** ```c void Viterbi(HMM *phmm, int T, int *O, double **delta, int **psi,int *q, double *pprob) {   int i, j; /* state indices */   int t; /* time index */   int maxvalind;   double maxval, val;   /* 1. Initialization */   for (i = 1; i <= phmm->N; i++){     delta[1][i] = phmm->pi[i] * (phmm->B[i][O[1]]);     psi[1][i] = 0;   }   /* 2. Recursion */   for (t = 2; t <= T; t++)   {      for (j = 1; j <= phmm->N; j++){       maxval = 0.0;       maxvalind = 1;       for (i = 1; i <= phmm->N; i++) {         val = delta[t-1][i]*(phmm->A[i][j]);         if (val > maxval){           maxval = val;           maxvalind = i;         }       }       delta[t][j] = maxval*(phmm->B[j][O[t]]);       psi[t][j] = maxvalind;     }   }   /* 3. Termination */   *pprob = 0.0;   q[T] = 1;   for (i = 1; i <= phmm->N; i++){     if (delta[T][i] > *pprob){       *pprob = delta[T][i];       q[T] = i;     }   }   /* 4. Path (state sequence) backtracking */   for (t = T - 1; t >= 1; t--)     q[t] = psi[t+1][q[t+1]]; } ``` ## 0x09 參考 [[2] 如何用簡單易懂的例子解釋隱馬爾可夫模型?[Online]](https://www.zhihu.com/question/20962240/answer/33438846) [[3] ”相親記“之從EM演算法到Baum-Welch演算法[Online]](https://blog.csdn.net/firparks/article/details/54934112) [Itenyh版-用HMM做中文分詞一:序]([http://www.52nlp.cn/itenyh%E7%89%88-%E7%94%A8hmm%E5%81%9A%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D%E4%B8%80%EF%BC%9A%E5%BA%8F](http://www.52nlp.cn/itenyh版-用hmm做中文分詞一:序)) [HMM學習最佳範例一:介紹](http://www.52nlp.cn/hmm-learn-best-practices-one-introduction) [條件隨機場的簡單理解](https://blog.csdn.net/weixin_41911765/article/details/82465697) [HMM隱馬爾可夫模型詳解](https://blog.csdn.net/weixin_41911765/article/details/81979773) [**3.二元語法與中文分詞.md**](https://github.com/NLP-LOVE/Introduction-NLP/blob/master/chapter/3.二元語法與中文分詞.md) [”相親記“之從EM演算法到Baum-Welch演算法](https://blog.csdn.net/firparks/article/details/54934112) ([https://github.com/NLP-LOVE/Introduction-NLP/blob/master/chapter/3.%E4%BA%8C%E5%85%83%E8%AF%AD%E6%B3%95%E4%B8%8E%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D.md](https://github.com/NLP-LOVE/Introduction-NLP/blob/master/chapter/3.二元語法與中文分詞.md)) [https://github.com/NLP-LOVE/Introduction-NLP/blob/master/chapter/3.%E4%BA%8C%E5%85%83%E8%AF%AD%E6%B3%95%E4%B8%8E%E4%B8%AD%E6%96%87%E5%88%86%E8%AF%8D.md](https://github.com/NLP-LOVE/Introduction-NLP/blob/master/chapter/3.二元語法與中文分詞.md) [如何輕鬆愉快地理解條件隨機場(CRF)?](https://www.jianshu.com/p/55755fc649b1) [一文讀懂機器學習概率圖模型](https://blog.csdn.net/weixin_40674835/article/details/78782610) [十五、一篇文章讀懂拿了圖靈獎和諾貝爾獎的概率圖模型](https://blog.csdn.net/jiangjingxuan/article/details/54729133) [機器學習 —— 概率圖模型(貝葉斯網路)](https://www.cnblogs.com/ironstark/p/5087081.html) [貝葉斯網路,看完這篇我終於理解了(附程式碼)!](https://zhuanlan.zhihu.com/p/73415944) [概率圖模型理解](https://blog.csdn.net/isMarvellous/article/details/78828566) [概率圖模型體系:HMM、MEMM、CRF](https://zhuanlan.zhihu.com/p/33397147) [HMM演算法學習——自己動手實現一個簡單的HMM分詞(java)](https://www.unclewang.info/learn/machine-learning/745/) [HMM學習最佳範例六:維特比演算法1](http://www.52nlp.cn/hmm-learn-best-practices-six-viterbi-algorithm-1) [wiki上一個比較好的HMM例子](http://www.52nlp.cn/hmm-concrete-example-on-wiki) [https://hunch.net/](https://hunch.net/) [https://eps.leeds.ac.uk/computing](https://eps.leeds.ac.uk/co