點擊上方藍色字體,關注AI小白入門喲
跟着博主的腳步,每天進步一點點
本文介紹了隱馬爾可夫模型,首先介紹了隱馬爾科夫模型定義,核心思想是引入了隱狀態序列(引入隱狀態是所有隱因子模型最巧妙的地方,如:隱因子分解,LDA),然後介紹了隱馬爾科夫模型要解決的三個問題,1)在參數已知的情況下計算可觀測序列的總概率,2)在給出觀測序列數據時學習模型的參數,3)在參數已知的情況下通過維特比解碼預測出所有產生可觀測序列中概率最大的一條不可觀測序列,即序列標註問題。
作者 | 文傑
編輯 | yuquanle
隱馬爾可夫模型
A、隱馬爾科夫模型定義
隱馬爾科夫模型是一種時序的概率模型,描述由一個隱的馬爾科夫鏈隨機生成的不可觀察的隱狀態序列,在每一個隱狀態下隨機產生觀察值構成一個可觀測的隨機序列。其中關鍵是狀態序列是滿足馬爾科夫性質的,且可觀測序列是由隱藏的狀態序列以一定的概率隨機生成。
在自然語言中文分詞中,由於自然語言是有明顯的上下文關係的,即當前字與其前後出現的字都是有關係的。爲了表示前一個字對當前字的影響,我們用一個隱狀態來表示前的語義狀態,用在前一個狀態下轉移到發射出當前字的隱狀態的概率表示前一個字對當前字的影響。整個來說就是把上下文字對字的影響轉化成狀態對狀態的影響。而用發射概率來表示狀態到字的關係。值得注意的是隱馬爾可夫模型中:
即與之間獨立作用。
隱馬爾科夫模型由狀態集,觀測集,初始狀態轉移概率,狀態轉移概率,以及發射概率確定。
形式化定義爲:
所有可能的隱藏狀態集Q,所有可能的觀察值集V,其中是可能的狀態數,是可能的觀察數。
假設是長度爲的隱狀態序列,是其對應的觀測值序列。
是狀態轉移概率矩陣:
其中,表示第時刻在狀態下轉移到第時刻狀態的概率。
是發射概率矩陣,在隱狀態確定之後發射出觀測狀態的概率:
其中:
表示在狀態下發射出的概率。
是初始狀態的概率分佈:
其中,表示在時刻狀態爲的概率。
由此,馬爾科夫模型定義完成。至於爲何這樣定義,隱狀態的意義是什麼,就是模型的價值所在,如何理解隱狀態也是一種個人體會。
有了隱馬爾科夫模型,接下來看隱馬爾科夫模型能做什麼?
1、給定一個確定的隱馬爾科夫模型(參數確定)和觀察序列,計算在該參數下觀察序列的輸出概率 。
概率計算,由於觀測序列的產生於隱狀態是相關的,所以需要從隱狀態的轉移概率入手,通過發射概率間接的轉化到觀察序列。一般情況下該觀測序列對應的隱狀態序列有多個,把所有隱狀態可能的序列結合觀察序列求概率,再求和。
2、學習問題,已知觀察序列,估計模型參數,使得在該模型下觀測序列的概率最大。
學習問題,假設在不知道模型參數的情況下,而我們有大量的觀察序列,那麼這些大量的觀察序列一定不是偶然是這樣,而不是那樣的。從概率的角度來講,是這樣,而不是那樣的原因就是,是這樣的概率大於是那樣的概率。如果有大量的觀察序列,那麼其中必然隱藏了模型的信息。
3、預測問題,已知模型的參數和觀察序列O,求解一條使得該觀測序列概率最大的隱狀態序列 。這樣概率計算類似,只需要求最大的即可。
好了,對應上面的三個問題,分別有三個算法求解對應的問題。
概率計算-前向後向算法
參數學習-最大似然估計(有監督),Baum-Walch(無監督)
預測-Viterbi算法
B、概率計算(觀察序列的概率)
給定一個確定的隱馬爾科夫模型(參數確定)和觀察序列,計算在該參數下觀察序列的輸出概率 。最直接的方法是計算所有可能的概率,即:
其中,這個狀態我們是看不見的,且沒個時刻的取值都有中,由於隱狀態與觀察狀態無關,其概率爲:
由於的取值有種,但序列前後有一個相同的狀態,所以整個的複雜度是。
而在參數和隱狀態都確定的條件下,產生觀察序列的概率爲:
即整個時刻的發射概率的乘積。
因此在給定參數的條件下,產生觀察序列的概率爲:
算法的複雜度爲。之所以算法的複雜度高是分別計算和,而忽略了序列之間的遞推關係。
下面介紹隱馬爾可夫概率計算問題中的前向-後向算法
前向概率:在給定模型的參數和觀察序列下,表示時刻的前向概率(從時刻到時刻觀察序列):
由前向遞推關係等於在所有可能的前一狀態轉移到當前狀態(同時t時刻發射出觀測值)的概率之和:
因此前向算法計算如下:
初值:
前向遞推:
求和:
後向概率:在給定模型的參數和觀察序列下,表示時刻的後向概率(從時刻到時刻觀察序列,):
值得注意的是,後向概率表示序列從時刻到時刻的概率,所以
由後向遞推關係等於所有可能的後一狀態逆轉移到當前狀態(同時時刻發射出觀測值)的概率之和
因此後向算法計算如下:
1)初值:
2)反向遞推:
3)求和:
前向後向算法:
由上面的前向後向算法,固定時刻的狀態,由前向後向算法有:
C、參數估計
一般來講,隱馬爾可夫的參數估計問題分爲兩種,一種是有監督,一種是無監督的。有監督意味着給定的訓練集中觀測序列和隱狀態序列,此時對應的參數估計問題就可以直接採用最大似然估計;無監督意味着給定的訓練集中只有觀測序列,此時需要採用EM算法思想,先假設參數,通過期望最大化來獲得隱狀態序列(硬劃分隱狀態序列對應到值,軟化分隱狀態序列對應到概率),然後根據隱狀態序列來更新參數,不斷迭代至收斂。
有監督(最大似然估計):
轉移概率表示從狀態轉移到狀態的概率:
其中分子表示從狀態轉移到狀態的次數,分母表示從狀態轉移到任意狀態的次數。
發射概率表示在狀態下發射出觀測值的概率:
其中分子表示在狀態下發射出觀測值的次數,分母表示在狀態下發射出任意狀態的次數。
初始狀態轉移概率爲樣本中初始狀態的概率:
其中分子表示初始狀態是的次數,分母表示所有初始狀態出現的次數。
無監督(Baum-Welch):
隱馬爾可夫模型中隱狀態其實是一個隱變量,EM算法這類含有隱變量模型的通用求解算法,思路是初始化一個隱變量的概率分佈,E步:期望最大化來更新樣本的隱變量(值,概率),M步:在隱變量確定的條件下更新隱變量的概率。
D、狀態預測
已知模型的參數和觀察序列O,求解一條使得該觀測序列概率最大的隱狀態序列 。這樣概率計算類似,只需要求最大的即可。
維特比算法:維特比算法是一種動態規劃算法來求解概率最大路徑,也是一種求解最優路徑問題。而最優路徑中總存在這樣一個特性:如果最優路徑時刻通過結點,那麼最優路徑中從結點到最終結點的部分路徑是所有可能從到路徑中最優的(同時從到的路徑也是最優的)。依據這一特性,我們可以從開始遞推計算時刻下狀態爲的各種路徑的最大概率,直至時刻狀態爲的最大概率。同時在遞推的過程中,我們用一個變量來計住到達最優路徑的上一個結點的狀態。這樣我們就首先確定了時刻的狀態值。然後,根據到達該狀態的上一個結點狀態來遞推到。
因此,我們需要引入兩個變量,從時刻到時刻狀態爲的最優路徑的概率值,並以此來遞推下一時刻狀態爲的最優路徑,即
同時爲了記住到達該路徑的上一節點的狀態,定義如下變量:
有了上面的兩個變量,我們就可以獲得隱狀態的最優路徑:
1)初始化
2)遞推,對
3)終止
4)最優路徑回溯,
求得最優路徑。
其中值得注意的是,是無用的,在前向遞推到時刻獲得最大概率的同時也獲得了最優的最終狀態,回溯的過程只需要從開始,不需要任何計算,因爲中保存了到達當前最優路徑狀態的上一狀態。
代碼實戰
A、隱馬爾可夫模型
/**
HMM模型中三個基本問題,概率計算問題,學習參數問題,預測問題。
針對這三個問題有HMM模型中的
1 前向後向算法
2 Baum-Welch算法
3 Veiterbi算法
下面的程序是上面三個算法的實現,考慮到用於分詞,所以設計成讀取文件的形式
但實際上中文分詞算法中的學習參數問題並不採用Baum-Welch算法,而是採用監督學習算法中的極大似然估計,
所以Baum-Welch算法中讀取的文件只是一個極少詞的文件,用EM算法求解學習參數。
所以在學習參數問題上寫了兩種學習算法,一Baum-Welch算法,二 極大似然估計
並採用統計學習方法一書中的例子進行驗證Veiterbi算法的正確性。
最後在另外一個文件中實現極大似然的HMM模型的中文分詞
測試只考慮一個樣本
**/
/**
統計學習方法p186例題測試VTB算法正確性
把Ntest文件中的字典長度看作觀察序列可能值,上下文看作觀察序列
隱藏狀態在參數STATE設置,在字構詞分詞中STATE=4,測試本例時修改爲STATE=3
**/
void init_test()
{
double A[STATE][STATE]= {0.5,0.2,0.3,
0.3,0.5,0.2,
0.2,0.3,0.5
};
double B[STATE][2]= {0.5,0.5,
0.4,0.6,
0.7,0.3
};
double pi[STATE]= {0.2,0.4,0.4};
int i,j;
for(i=0; i<STATE; i++)
{
for(j=0; j<STATE; j++)
{
hmm_pra.a[i][j]=A[i][j];
}
}
for(i=0; i<STATE; i++)
{
for(j=0; j<hmm_pra.len; j++)
{
hmm_pra.b[i][j]=B[i][j];
}
}
for(i=0; i<STATE; i++)
{
hmm_pra.pi[i]=pi[i];
}
}
int HMM()
{
DataStr data;
LoadDataStr(data,"data\\Ntest.txt");//加載訓練集,亦爲測試集,只考慮了一個樣本
createOset(data);//建立詞典
init_test();
cout<<"-------------forwardBack-----------------"<<endl;
forwardBack(data);
cout<<"-------------Baum_Weach-----------------"<<endl;
Baum_Weach(data);
cout<<"-------------Viterbi-----------------"<<endl;
init_test();
Viterbi_O(data);
return 0;
}
The End
爲了方便交流學習,備註:暱稱-學校(公司)-方向,進入DL&NLP交流羣。
方向有很多:機器學習、深度學習,python,情感分析、意見挖掘、句法分析、機器翻譯、人機對話、知識圖譜、語音識別等。
記得備註呦
▼
往期精彩回顧
▼
長按二維碼關注
AI小白入門
ID:StudyForAI
學習AI學習ai(愛)
期待與您的相遇~
你點的每個在看,我都認真當成了喜歡