1. 程式人生 > >小白都能看懂的馬爾可夫鏈詳解

小白都能看懂的馬爾可夫鏈詳解

1.什麼是馬爾可夫鏈

在機器學習演算法中,馬爾可夫鏈(Markov chain)是個很重要的概念。馬爾可夫鏈(Markov chain),又稱離散時間馬爾可夫鏈(discrete-time Markov chain),因俄國數學家安德烈·馬爾可夫(俄語:Андрей Андреевич Марков)得名,為狀態空間中經過從一個狀態到另一個狀態的轉換的隨機過程。該過程要求具備“無記憶”的性質:下一狀態的概率分佈只能由當前狀態決定,在時間序列中它前面的事件均與之無關。這種特定型別的“無記憶性”稱作馬爾可夫性質。馬爾科夫鏈作為實際過程的統計模型具有許多應用。
在馬爾可夫鏈的每一步,系統根據概率分佈,可以從一個狀態變到另一個狀態,也可以保持當前狀態。狀態的改變叫做轉移,與不同的狀態改變相關的概率叫做轉移概率。隨機漫步就是馬爾可夫鏈的例子。隨機漫步中每一步的狀態是在圖形中的點,每一步可以移動到任何一個相鄰的點,在這裡移動到每一個點的概率都是相同的(無論之前漫步路徑是如何的)。
(來自參考文獻1)

2.一個經典的馬爾科夫鏈例項

用一句話來概括馬爾科夫鏈的話,那就是某一時刻狀態轉移的概率只依賴於它的前一個狀態。舉個簡單的例子,假如每天的天氣是一個狀態的話,那個今天是不是晴天只依賴於昨天的天氣,而和前天的天氣沒有任何關係。這麼說可能有些不嚴謹,但是這樣做可以大大簡化模型的複雜度,因此馬爾科夫鏈在很多時間序列模型中得到廣泛的應用,比如迴圈神經網路RNN,隱式馬爾科夫模型HMM等。
假設狀態序列為xt2,xt1,xt,xt+1,xt+2,\cdots x_{t-2}, x_{t-1}, x_t, x_{t+1}, x_{t+2}, \cdots

,xt+2,,由馬爾科夫鏈定義可知,時刻xt+1x_{t+1}的狀態只與xtx_t有關,用數學公式來描述就是:
P(xt+1 ,xt2,xt1,xt)=P(xt+1xt)P(x_{t+1} | \cdots, x_{t-2}, x_{t-1}, x_t) = P(x_{t+1}|x_t)

既然某一時刻狀態轉移的概率只依賴前一個狀態,那麼只要求出系統中任意兩個狀態之間的轉移概率,這個馬爾科夫鏈的模型就定了。看一個具體的例子。

在這裡插入圖片描述

這個馬爾科夫鏈是表示股市模型的,共有三種狀態:牛市(Bull market), 熊市(Bear market)和橫盤(Stagnant market)。每一個狀態都以一定的概率轉化到下一個狀態。比如,牛市以0.025的概率轉化到橫盤的狀態。這個狀態概率轉化圖可以以矩陣的形式表示。如果我們定義矩陣陣P某一位置P(i, j)的值為P(j|i),即從狀態i變為狀態j的概率。另外定義牛市、熊市、橫盤的狀態分別為0、1、2,這樣我們得到了馬爾科夫鏈模型的狀態轉移矩陣為:

P=(0.90.0750.0250.150.80.050.250.250.5) P = \left( \begin{array}{ccc} 0.9 & 0.075 & 0.025 \\ 0.15 & 0.8 & 0.05 \\ 0.25 & 0.25 & 0.5 \end{array} \right)
當這個狀態轉移矩陣P確定以後,整個股市模型就已經確定!

3.狀態轉移矩陣

從上面的例子不難看出來,整個馬爾可夫鏈模型的核心是狀態轉移矩陣P。那這個矩陣P有一些什麼有意思的地方呢?接下來再看一下。
以股市模型為例,假設初始狀態為t0=[0.1,0.2,0.7]t_0 = [0.1, 0.2, 0.7],然後算之後的狀態。

def markov():
    init_array = np.array([0.1, 0.2, 0.7])
    transfer_matrix = np.array([[0.9, 0.075, 0.025],
                               [0.15, 0.8, 0.05],
                               [0.25, 0.25, 0.5]])
    restmp = init_array
    for i in range(25):
        res = np.dot(restmp, transfer_matrix)
        print i, "\t", res
        restmp = res

markov()

最終輸出的結果:

0 	[ 0.295   0.3425  0.3625]
1 	[ 0.4075   0.38675  0.20575]
2 	[ 0.4762  0.3914  0.1324]
3 	[ 0.52039   0.381935  0.097675]
4 	[ 0.55006   0.368996  0.080944]
5 	[ 0.5706394  0.3566873  0.0726733]
6 	[ 0.58524688  0.34631612  0.068437  ]
7 	[ 0.59577886  0.33805566  0.06616548]
8 	[ 0.60345069  0.33166931  0.06487999]
9 	[ 0.60907602  0.32681425  0.06410973]
10 	[ 0.61321799  0.32315953  0.06362248]
11 	[ 0.61627574  0.3204246   0.06329967]
12 	[ 0.61853677  0.31838527  0.06307796]
13 	[ 0.62021037  0.31686797  0.06292166]
14 	[ 0.62144995  0.31574057  0.06280949]
15 	[ 0.62236841  0.31490357  0.06272802]
16 	[ 0.62304911  0.31428249  0.0626684 ]
17 	[ 0.62355367  0.31382178  0.06262455]
18 	[ 0.62392771  0.31348008  0.06259221]
19 	[ 0.624205   0.3132267  0.0625683]
20 	[ 0.62441058  0.31303881  0.06255061]
21 	[ 0.624563    0.31289949  0.06253751]
22 	[ 0.624676   0.3127962  0.0625278]
23 	[ 0.62475978  0.31271961  0.06252061]
24 	[ 0.6248219   0.31266282  0.06251528]

從第18次開始,狀態就開始收斂至[0.624,0.312,0.0625][0.624, 0.312, 0.0625]。最終數字上略有不同,只是計算機浮點數運算造成的罷了。

如果我們換一個初始狀態t0t_0,比如[0.2,0.3.0.5][0.2, 0.3. 0.5],繼續執行上面的程式碼,只是將init_array變一下,最後結果為:

0 	[ 0.35  0.38  0.27]
1 	[ 0.4395   0.39775  0.16275]
2 	[ 0.4959   0.39185  0.11225]
3 	[ 0.53315   0.378735  0.088115]
4 	[ 0.558674  0.365003  0.076323]
5 	[ 0.5766378  0.3529837  0.0703785]
6 	[ 0.5895162   0.34322942  0.06725438]
7 	[ 0.59886259  0.33561085  0.06552657]
8 	[ 0.6056996   0.32978501  0.06451539]
9 	[ 0.61072624  0.32538433  0.06388944]
10 	[ 0.61443362  0.32208429  0.06348209]
11 	[ 0.61717343  0.31962047  0.0632061 ]
12 	[ 0.61920068  0.31778591  0.06301341]
13 	[ 0.62070185  0.31642213  0.06287602]
14 	[ 0.62181399  0.31540935  0.06277666]
15 	[ 0.62263816  0.31465769  0.06270415]
16 	[ 0.62324903  0.31410005  0.06265091]
17 	[ 0.62370187  0.31368645  0.06261168]
18 	[ 0.62403757  0.31337972  0.06258271]
19 	[ 0.62428645  0.31315227  0.06256128]
20 	[ 0.62447096  0.31298362  0.06254542]
21 	[ 0.62460776  0.31285857  0.06253366]
22 	[ 0.62470919  0.31276586  0.06252495]
23 	[ 0.62478439  0.31269711  0.0625185 ]
24 	[ 0.62484014  0.31264614  0.06251372]

到第18次的時候,又收斂到了[0.624,0.312,0.0625][0.624, 0.312, 0.0625]!
這個轉移矩陣就厲害了。不管我們的初始狀態是什麼樣子的,只要狀態轉移矩陣不發生變化,當nn \to \infty時,最終狀態始終會收斂到一個固定值。

在矩陣分析,自動控制原理等過程中,經常會提到矩陣的冪次方的性質。我們也看看這個狀態轉移矩陣PP的冪次方有什麼有意思的地方?廢話不多說,直接上程式碼。

def matrixpower():
    transfer_matrix = np.array([[0.9, 0.075, 0.025],
                               [0.15, 0.8, 0.05],
                               [0.25, 0.25, 0.5]])
    restmp = transfer_matrix
    for i in range(25):
        res = np.dot(restmp, transfer_matrix)
        print i, "\t", res
        restmp = res

matrixpower()

程式碼執行的結果:

0 	[[ 0.8275   0.13375  0.03875]
 [ 0.2675   0.66375  0.06875]
 [ 0.3875   0.34375  0.26875]]
1 	[[ 0.7745   0.17875  0.04675]
 [ 0.3575   0.56825  0.07425]
 [ 0.4675   0.37125  0.16125]]
2 	[[ 0.73555   0.212775  0.051675]
 [ 0.42555   0.499975  0.074475]
 [ 0.51675   0.372375  0.110875]]
3 	[[ 0.70683   0.238305  0.054865]
 [ 0.47661   0.450515  0.072875]
 [ 0.54865   0.364375  0.086975]]
4 	[[ 0.685609   0.2573725  0.0570185]
 [ 0.514745   0.4143765  0.0708785]
 [ 0.570185   0.3543925  0.0754225]]
5 	[[ 0.6699086  0.2715733  0.0585181]
 [ 0.5431466  0.3878267  0.0690267]
 [ 0.585181   0.3451335  0.0696855]]
6 	[[ 0.65828326  0.28213131  0.05958543]
 [ 0.56426262  0.36825403  0.06748335]
 [ 0.5958543   0.33741675  0.06672895]]
7 	[[ 0.64967099  0.28997265  0.06035636]
 [ 0.5799453   0.35379376  0.06626094]
 [ 0.60356362  0.33130471  0.06513167]]
8 	[[ 0.64328888  0.29579253  0.06091859]
 [ 0.59158507  0.34309614  0.06531879]
 [ 0.60918588  0.32659396  0.06422016]]
9 	[[ 0.63855852  0.30011034  0.06133114]
 [ 0.60022068  0.33517549  0.06460383]
 [ 0.61331143  0.32301915  0.06366943]]
10 	[[ 0.635052    0.30331295  0.06163505]
 [ 0.60662589  0.3293079   0.06406621]
 [ 0.61635051  0.32033103  0.06331846]]
11 	[[ 0.63245251  0.30568802  0.06185947]
 [ 0.61137604  0.32495981  0.06366415]
 [ 0.61859473  0.31832073  0.06308454]]
12 	[[ 0.63052533  0.30744922  0.06202545]
 [ 0.61489845  0.32173709  0.06336446]
 [ 0.6202545   0.31682232  0.06292318]]
13 	[[ 0.62909654  0.30875514  0.06214832]
 [ 0.61751028  0.31934817  0.06314155]
 [ 0.62148319  0.31570774  0.06280907]]
14 	[[ 0.62803724  0.30972343  0.06223933]
 [ 0.61944687  0.3175772   0.06297594]
 [ 0.6223933   0.3148797   0.062727  ]]
15 	[[ 0.62725186  0.31044137  0.06230677]
 [ 0.62088274  0.31626426  0.062853  ]
 [ 0.62306768  0.31426501  0.06266732]]
16 	[[ 0.62666957  0.31097368  0.06235675]
 [ 0.62194736  0.31529086  0.06276178]
 [ 0.62356749  0.31380891  0.0626236 ]]
17 	[[ 0.62623785  0.31136835  0.0623938 ]
 [ 0.6227367   0.31456919  0.06269412]
 [ 0.62393798  0.31347059  0.06259143]]
18 	[[ 0.62591777  0.31166097  0.06242126]
 [ 0.62332193  0.31403413  0.06264394]
 [ 0.62421263  0.31321968  0.0625677 ]]
19 	[[ 0.62568045  0.31187792  0.06244162]
 [ 0.62375584  0.31363743  0.06260672]
 [ 0.62441624  0.31303361  0.06255015]]
20 	[[ 0.6255045   0.31203878  0.06245672]
 [ 0.62407756  0.31334332  0.06257913]
 [ 0.62456719  0.31289565  0.06253716]]
21 	[[ 0.62537405  0.31215804  0.06246791]
 [ 0.62431608  0.31312525  0.06255867]
 [ 0.62467911  0.31279335  0.06252754]]
22 	[[ 0.62527733  0.31224646  0.06247621]
 [ 0.62449293  0.31296357  0.0625435 ]
 [ 0.62476209  0.3127175   0.06252042]]
23 	[[ 0.62520562  0.31231202  0.06248236]
 [ 0.62462404  0.3128437   0.06253225]
 [ 0.62482361  0.31266126  0.06251514]]
24 	[[ 0.62515245  0.31236063  0.06248692]
 [ 0.62472126  0.31275483  0.06252391]
 [ 0.62486922  0.31261956  0.06251122]]

從第20次開始,結果開始收斂,並且每一行都為[0.625,0.312,0.0625][0.625, 0.312, 0.0625]!

4.馬爾可夫鏈細緻平穩條件

首先,馬爾科夫鏈要能收斂,需要滿足以下條件:
1.可能的狀態數是有限的。
2.狀態間的轉移概率需要固定不變。
3.從任意狀態能夠轉變到任意狀態。
4.不能是簡單的迴圈,例如全是從x到y再從y到x。

以上是馬爾可夫鏈收斂的必要條件。

假設有一個概率的單純形向量v0v_0,例如我們前面的例子
[0.2,0.3.0.5][0.2, 0.3. 0.5]
有一個概率轉移矩陣PP,例如我們前面的例子:
P=(0.90.0750.0250.150.80.050.250.250.5) P = \left( \begin{array}{ccc} 0.9 & 0.075 & 0.025 \\ 0.15 & 0.8 & 0.05 \\ 0.25 & 0.25 & 0.5 \end{array} \right)
其中,v0v_0每個元素的取值範圍為[0,1],並且所有元素的和為1。而PP的每一行也是個概率單純形向量。由前面的例子我們不難看出,當v0v_0PP的n次冪相乘以後,發現得到的向量都會收斂到一個穩定值,而且此穩定值與初始向量v0v_0無關!
那麼所有的轉移矩陣PP都有這種現象嘛?或者說滿足什麼樣的條件的轉移矩陣PP會有這種現象?

細緻平衡條件(Detailed Balance Condition):給定一個馬爾科夫鏈,分佈π\pi和概率轉移矩陣P,如果下面等式成立:
πiPij=πjPji\pi_i P_{ij} = \pi_j P_{ji}
則此馬爾科夫鏈具有一個平穩分佈(Stationary Distribution)。

證明過程比較簡單:
i=1π(i)P(i,j)=i=1π(j)P(j,i)=π(j)i=1P(j,i)=π(j)\sum_{i=1}^{\infty} \pi(i) P(i,j) = \sum_{i=1}^{\infty} \pi(j) P(j,i) = \pi(j) \sum_{i=1}^{\infty} P(j, i) = \pi(j)

上式取jj \to \infty,就可以得到矩陣表示式:
πP=π\pi P = \pi

5.馬爾可夫鏈收斂性質

如果一個非週期的馬爾可夫鏈收斂,有狀態轉移矩陣P,並且任何兩個狀態都是連通的,那麼limnPijnlim_{n \to \infty} P_{ij} ^ n為一定值,且與i無關。
1.
limnPijn=π(j)lim_{n \to \infty} P_{ij} ^ n = \pi (j)

limnPn=(π(1)π(2)π(j)π(1)π(2)π(j)π(1)π(2)π(j)) lim_{n \to \infty} P ^ n = \left( \begin{array}{ccc} \pi(1) & \pi(2) & \cdots & \pi(j) & \cdots \\ \pi(1) & \pi(2) & \cdots & \pi(j) & \cdots \\ \cdots & \cdots & \cdots & \cdots & \cdots \\ \pi(1) & \pi(2) & \cdots & \pi(j) & \cdots \\ \cdots & \cdots & \cdots & \cdots & \cdots \end{array} \right)