馬爾科夫鏈模型
介紹
馬爾科夫模型是一個用於預測的統計模型,在人口,股票等問題上有很多應用。
馬爾科夫過程是一個離散隨機過程,在這個過程中,過去的信息對於預測將來是無關的。即只與當前狀態有關。(一階模型,也有N階馬爾科夫模型,表示當前狀態僅與之前的N個狀態有關,跟再前面的無關。)
時間和狀態都是離散的馬爾科夫過程,稱爲馬爾科夫鏈,記爲:
這樣,我們根據上面介紹的,可以得出:
對於有N個狀態的一階馬爾科夫模型,每個狀態可以轉移到另一個狀態(包括自己),則共有N^2次狀態轉移,可以用狀態轉移矩陣表示。
Pij = P(Xn + 1 = i | Xn = j),其中Pij表示系統在時刻t處於狀態j,在下一時刻t+l處於狀態i的概率。
例如:一段文字中名詞、動詞、形容詞出現的情況可以用有3個狀態的y一階馬爾科夫模型M表示。狀態s1:名詞,狀態s2:動詞,狀態s3:形容詞。已知狀態轉移矩陣A,則狀態序列O=“名動形名”
馬爾科夫過程定義了以下三個部分:狀態,初始向量,狀態轉移矩陣。
隱形馬爾科夫模型
隱形馬爾科夫模型(HMM)是一個用來描述含有隱含未知參數的馬爾可夫過程的統計模型。其難點是從可觀察的參數中確定該過程的隱含參數。然後利用這些參數來作進一步的分析。
隱性馬爾科夫模型由初始概率分佈,狀態轉移概率分佈以及觀測概率分佈確定。
隱性馬爾科夫模型作了兩個基本假設:
1 齊次馬爾科夫假設,即假設因此的馬爾科夫鏈在任意時刻t的狀態只依賴於其前一時刻的狀態,與其他時刻的狀態以及觀測無關。
2 觀測獨立性假設,即假設任意時刻的觀測只依賴於該時刻的馬爾科夫鏈的狀態,與其他觀測以及狀態無關。
HMM是馬爾科夫鏈中的一種,只是它的狀態不能直接被觀察到,但是可以通過觀察向量間接的反映出來,即每一個觀察向量由一個具有相應概率密度分佈的狀態序列產生,又由於每一個狀態也是隨機分佈的,所以HMM是一個雙重隨機過程。
某地只有兩種天氣:雨天和晴天。某人只做3件事:散步,購物,打掃衛生。
做什麼事,跟天氣很有關係。
你知道這個地區的總的天氣趨勢,並且平時知道某人會做的事情。就是說這個隱馬爾可夫模型的參數是已知的.
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},
}<br>
emission_probability = {
Rainy : {walk: 0.1, shop: 0.4, clean: 0.5},
Sunny : {walk: 0.6, shop: 0.3, clean: 0.1},
}
可以觀察到的狀態序列和隱藏的狀態序列是概率相關的。隱藏的狀態和可觀察到的狀態之間有一種概率上的關係,也就是說某種隱藏狀態 H 被認爲是某個可以觀察的狀態 O1 是有概率的,假設爲 P(O1 | H)。如果可以觀察的狀態有3種,那麼很顯然 P(O1 | H)+P(O2 | H)+ P(O3 | H) = 1。
HMM是語音識別,人體行爲識別,文字識別等領域應用非常廣泛。
HMM的3個基本問題:
1 概率計算問題:根據模型計算制定序列O出現的概率。
2 學習問題:根據已知觀測序列,估計模型的參數,使得在該模型觀測序列概率最大。
3 預測問題:根據給定觀測序列,求最有可能的對應的狀態序列。
之前在交大做的情感計算就是上面第3個問題。
已知模型參數,計算某一特定輸出序列的概率.通常使用forward算法解決.
已知模型參數,尋找最可能的能產生某一特定輸出序列的隱含狀態的序列.通常使用Viterbi算法解決.
已知輸出序列,尋找最可能的狀態轉移以及輸出概率.通常使用Baum-Welch算法以及Reversed Viterbi算法解決.
預測算法:
1 近似算法:在每個t時刻,選擇最有可能出現的狀態i,從而得到一個狀態序列,將它作爲預測的結果。
這樣做的缺點就是不能保證序列整體是最有可能的狀態序列。
2 維特比算法:實際上是動態規劃來解決預測模型。
根據動態規劃原理,最優路徑具有這樣的特性:若是最優路徑在時刻t通過節點i(t),那麼這一路徑從節點i(t)到終點i(T)的部分路徑,對於所有節點i(t)到終點i(T)的路徑必須是最優的。
從終點i(T)開始,由後向前逐步求得節點,得到最優路徑。這就是維特比算法。
算法實踐,實現單詞聯想
思路
- 對於給定訓練文本,用分詞器將每句話分爲一個列表
W={w1,w2,.........wn} - 對於連續的兩個
wi 以及wi+1 ,將前一個wi 作爲字典的key,字典的value作爲一個list(因爲要存儲一定數量的後續word) 對於聯想,隨機產生前綴單詞,然後在字典中查找該單詞的value(這裏爲list),然後隨機產生一個序號作爲後一個詞語或文字。
ps:這裏想法很簡單,並沒有去統計頻率。可以從以下方面去改進:
- 對於每句話的文字列表,將前一個詞語
wi 與後一個詞語wi+1 寫成w_i w_i+1 1
,處理完之後再來統計w_i w_i+1
的頻率(類似於mapreduce
) - 考慮
P(wn|wn+1)
- 對於每句話的文字列表,將前一個詞語
實現及運行
訓練文本: 最近的新聞
運行結果:
Viterbi算法
前面簡單介紹了一下該算法,這裏就不多贅述了。
輸入
- 觀測空間
O={o1,o2.....,on} - 狀態序列
S={S1,S2.....,Sk} - 初始狀態
Π={π1,π2.....,πk} - 觀察序列
Y={y1,y2.....,yT} - 狀態轉移矩陣A (K*K),
Aij 存儲狀態從si 到sj 的概率 - 矩陣B,存儲觀察的概率從Si到Oj。
輸出
- 最可能的隱藏狀態
X={x1,x2,.......,xN}
示例
參考https://en.wikipedia.org/wiki/Viterbi_algorithm
由於wiki中已經用Python實現了該算法,下面用java試着去實現以下
1.輸入數據
//觀測狀態
int [] obs = new int[]{Feel.Normal.ordinal(),
Feel.Cold.ordinal(),
Feel.Dizzy.ordinal()};
//隱藏的狀態
int [] states = new int[]{BodyState.Healthy.ordinal(),
BodyState.Fever.ordinal()};
//初始概率
double[] start_p = new double[]{0.6,0.4};
//狀態轉換矩陣
double[][] trans_p = {{0.7,0.3},{0.4,0.6}};
//每種狀態對應的各種觀測概率
double[][] emit_p = {{0.5,0.4,0.1},{0.1,0.3,0.6}};
2.狀態轉換圖
3.僞代碼
4.算法實現
protected int[] getViterbiPath()
{
double[][] V = new double[obs.length][states.length];
int[][] path = new int[states.length][obs.length];
for (int y : states)
{
V[0][y] = start_p[y] * emit_p[y][obs[0]];
path[y][0] = y;
}
for (int t = 1; t < obs.length; ++t)
{
int[][] newpath = new int[states.length][obs.length];
for (int y : states)
{
double prob = -1;
int state;
for (int y0 : states)
{
double nprob = V[t - 1][y0] * trans_p[y0][y] * emit_p[y][obs[t]];
if (nprob > prob)
{
prob = nprob;
state = y0;
// 記錄最大概率
V[t][y] = prob;
// 記錄路徑
System.arraycopy(path[state], 0, newpath[y], 0, t);
newpath[y][t] = y;
}
}
}
path = newpath;
}
double prob = -1;
int state = 0;
for (int y : states)
{
if (V[obs.length - 1][y] > prob)
{
prob = V[obs.length - 1][y];
state = y;
}
}
return path[state];
}
5.運行結果
對於給定的觀察序列: normal cold dizzy
運行結果爲: