HMM隱馬爾可夫模型來龍去脈(一)


目錄

隱馬爾可夫模型HMM學習導航

  一、認識貝葉斯網絡

    1、概念原理介紹

    2、舉例解析

  二、馬爾可夫模型

    1、概念原理介紹

    2、舉例解析

  三、隱馬爾可夫模型

    1、概念原理介紹

    2、舉例解析

  四、隱馬爾可夫模型簡單實現

  五、完整代碼

  六、結語


隱馬爾可夫模型HMM學習導航

NLP學習記錄,這一章從概率圖模型開始,學習常見的圖模型具體的原理以及實現算法,包括了有向圖模型:貝葉斯網絡(BN)、(隱)馬爾可夫模型(MM/HMM),無向圖模型:馬爾可夫網絡(MN)、條件隨機場(CRF)。學習前提條件需要一定的概率論與數理統計知識,里面許多方法都是概率統計知識。

圖模型框架:

一、認識貝葉斯網絡

1、概念原理介紹

貝葉斯網絡是一種基於概率推理的數學模型,屬於有向無環圖,理論基礎就是我們熟悉的貝葉斯公式

formula  

公式中,事件Bi的概率為P(Bi),事件Bi已發生條件下事件A的概率為P(A│Bi),事件A發生條件下事件Bi的概率為P(Bi│A),公式分母就是全概率公式。

構造貝葉斯網絡任務復雜,包括表示、推斷、學習三個方面的問題。這里就簡單介紹。

  1. 表示:某個隨機變量集合\large x=\{X_1,... ,X_n\}上聯合概率分布P,貝葉斯網絡的表示就是在隨機變量僅有兩種取值的簡單情況下,對 \large 2^n 種不同取值的聯合概率分布進行說明,可以看出,這是計算量巨大的任務。
  2. 推斷:貝葉斯網絡是變量及其關系的完整模型,可以從觀察到或已知的變量推斷另一些變量的變化,這種根據已知的證據計算變量的后驗分布稱為概率推理。
  3. 學習:指的是BN中參數的學習,目的是決定變量之間的關聯量化關系(依存強度估計)。參數學習方法包括:最大似然估計法、最大后驗概率法、期望最大化法和貝葉斯估計法(使用最多)。

2、舉例解析

從前面一片理論介紹和概念中,似乎很不直觀,還沒理解貝葉斯網絡到底是什么,現在我們通過簡單例子更加直觀深刻地去認識。

假設一篇關於南海島嶼的新聞(News),新聞里可能包含關於介紹南海島嶼歷史的內容(History),還有介紹旅游風光的內容(Sightseeing)。現在對此構造建立一個簡單的貝葉斯網絡。

現在用N、H、S表示這3個事件,每個事件存在兩種可能,記為T(包含/是)、F(不包含/不是),通過假設概率建模:

New
T F
0.2 0.8
  Sightseeing
News T F
F 0.4 0.6
T 0.1 0.9
    History
Sightseeing News T F
F F 0.5 0.5
F T 0.3 0.7
T F 0.8 0.2
T T 0.4 0.6

一個簡單的貝葉斯網絡:

上面表格枚舉了所有可能的情況概率分布,現在根據表格內容和建立的BN圖關系,三個事件的聯合概率:

即 \large P(H,S,N)=P(H|S,N)\times P(S|N)\times P(N) .

給出一個問題:如果一篇新聞中含有南海島嶼歷史相關的內容,那么該新聞是關於南海新聞的可能性是多少呢?

顯然,模型能夠解決這個問題,根據題意我們得出,就是計算 H=T的情況下 N=T 的條件概率 \large P(N=T|H=T)

進一步求解得到

\large P(N=T|H=T)=\frac{P(N=T,H=T)}{P(H=T)}= \frac{\sum_{S\in {T,F}}P(H=T,S,N=T)}{\sum_{N,S\in {T,F}}P(H=T,S,N)}

現在直接代入表格的數據,按H,S,N順序,分子為TTT+TFT,分母TTT+TFT+TTF+TFF. 由此計算得到:

\large \frac{0.4\times 0.1\times 0.2+0.3\times 0.9\times 0.2}{0.4\times 0.1\times 0.2+0.3\times 0.9\times 0.2+0.8\times0.4\times0.8+0.5\times0.6\times0.8} =  \large 11.11\% .

二、馬爾可夫模型

1、概念原理介紹

馬爾可夫模型是一個可見的過程,隱馬爾可夫模型則是將隨機事件的狀態轉移過程屏蔽,所以學習馬爾可夫模型作為前提。

馬爾可夫模型(Markov Model)描述了一種隨機函數,是隨着時間不斷變化的過程。換言之,我們觀察到每個隨機變量序列並不是相互獨立的,而是依賴於其前面序列的狀態。

2、舉例解析

假設系統有N個狀態S=\{s_1,s_2,...,s_N\}, 一個隨機序列Q=\{q_1,q_2,...,q_N\}, t 時刻狀態q_t=s_j,那它的概率如何計算呢?

計算t時刻狀態的概率需要給出前面t-1個狀態的關系,概率表示為:

P(q_t=s_j|q_{t-1}=s_i,q_{t-2}=s_k,......) ,相當於求解條件概率。

對於馬爾可夫模型來說,有這樣的特定條件,系統t時刻的狀態只與其在時間t-1狀態相關,所以表示為如下,稱為一階馬爾可夫鏈。

P(q_t=s_j|q_{t-1}=s_i,q_{t-2}=s_k,......)=P(q_t=s_j|q_{t-1}=s_i).

進而由上面的是公式得到一個隨機過程表示,構成狀態轉移矩陣。

P(q_t=s_j|q_{t-1}=s_i)=a_{ij}(1\leq i,j\leq N), 滿足a_{ij}\geqslant 0,\sum_{j=1}^{N}a_{ij}=1 . 可見N個狀態可以構成N*N個狀態轉移概率。


下面用更加直觀例子解析馬爾可夫模型。

假設一段文字中有三類詞性:名詞、動詞、形容詞。這三類詞性的出現可以表示為馬爾可夫模型的三個狀態,描述為:

狀態a:名詞

狀態b:動詞

狀態c:形容詞

假設轉移矩陣如下:

A=[a_{ij}]=\begin{bmatrix} 0.3 &0.5 &0.2 \\ 0.5 &0.3& 0.2 \\ 0.4 &0.2 &0.4 \end{bmatrix}

各狀態關系,每個狀態所有發射弧概率之和為1

根據此模型M,計算某個句子序列詞性出現順序 O = "名動形名"的概率:

P(O|M)=P(a,b,c,a|M)=P(a)\times P(b|a)\times P(c|b)\times P(a|c) = 1\times a_{12} \times a_{23} \times a_{31} =0.5 \times 0.2\times 0.4=0.04

三、隱馬爾可夫模型

1、概念原理介紹

在前面馬爾可夫模型,每個狀態都是可見的。而隱馬爾可夫模型,就是將這狀態序列隱蔽,變為狀態轉移過程不可見。HMM是一個雙重隨機過程。它用來描述一個含有隱含未知參數的馬爾可夫過程。其難點是從可觀察的參數中確定該過程的隱含參數。

2、舉例解析

一個暗室里面有N個口袋,每個口袋有M個不同顏色小球。這個過程包括實驗者和觀察者。實驗者每次根據某個概率分布隨機選取一個口袋,再根據某個概率分布從這個口袋中取出一個小球,並向觀察者展示該球的顏色。

我們理解一下這個過程,觀察者只能知道每次取出球的顏色序列,而不知是從哪個口袋取出的,這個口袋序列的狀態轉移只有暗室里的實驗者知道。所以,觀察者的任務就是根據可觀察序列(球顏色序列)來推斷出隱藏的轉移過程。

由此,總結出一個HMM有以下組成:

  1. 模型狀態數目N(如例子中的口袋數量)
  2. 每個狀態可能輸出的不同符號數目M(一個口袋不同顏色球的數目)
  3. 狀態轉移矩陣A={a_{ij}} (a_{ij}是實驗者從一口袋 i 轉向口袋 j 的概率)。P(q_t=s_j|q_{t-1}=s_i)=a_{ij}(1\leq i,j\leq N)a_{ij}\geqslant 0,\sum_{j=1}^{N}a_{ij}=1
  4. 觀察到符號的概率(符號發射概率)分布矩陣B={b_{j}(k)} (表示實驗者從第j個袋取出第k種顏色的球)。
  5. 初始狀態概率分布π。

四、隱馬爾可夫模型簡單實現

初始化狀態數目n和樣本數量,得到初始概率:

import numpy as np
from hmmlearn import hmm
import matplotlib.pyplot as plt
import matplotlib as mpl
from sklearn.metrics.pairwise import pairwise_distances_argmin
 
np.random.seed(28)
n = 5  # 隱狀態數目
n_samples = 500  # 樣本數量
pi = np.random.rand(n)
pi /= pi.sum()
print('初始概率:')
print(pi)

計算轉移矩陣:

A = np.random.rand(n, n)
mask = np.zeros((n, n), dtype=np.bool)
mask[0][1] = mask[0][4] = True
mask[1][0] = mask[1][2] = True
mask[2][1] = mask[2][3] = True
mask[3][2] = mask[3][4] = True
mask[4][0] = mask[4][3] = True
A[mask] = 0
for i in range(n):
    A[i] /= A[i].sum()
print('轉移概率:')
print(A)

給定均值和方差:

# 給定均值
means = np.array(((30, 30, 30), (0, 50, 20), (-25, 30, 10),
                  (-15, 0, 25), (15, 0, 40)), dtype=np.float)
for i in range(n):
    means[i, :] /= np.sqrt(np.sum(means ** 2, axis=1))[i]
covars = np.empty((n, 3, 3))
for i in range(n):
    covars[i] = np.diag(np.random.rand(3) * 0.02 + 0.001) 

產生模擬數據、模型構建及估計參數:

# 產生對應的模擬數據
model = hmm.GaussianHMM(n_components=n, covariance_type='full')
model.startprob_ = pi
model.transmat_ = A
model.means_ = means
model.covars_ = covars
sample, labels = model.sample(n_samples=n_samples, random_state=0)

# 模型構建及估計參數
model = hmm.GaussianHMM(n_components=n, n_iter=10)
model.fit(sample)
y = model.predict(sample)
np.set_printoptions(suppress=True)
# print('##估計初始概率:')
# print(model.startprob_)
# print('##估計轉移概率:')
# print(model.transmat_)
# print('##估計均值:\n')
# print(model.means_)
# print('##估計方差:\n')
# print(model.covars_)

根據類別信息更改順序:

# 根據類別信息更改順序
order = pairwise_distances_argmin(means, model.means_, metric='euclidean')
# print(order)
pi_hat = model.startprob_[order]
A_hat = model.transmat_[order]
A_hat = A_hat[:, order]
means_hat = model.means_[order]
covars_hat = model.covars_[order]
change = np.empty((n, n_samples), dtype=np.bool)
for i in range(n):
    change[i] = y == order[i]
for i in range(n):
    y[change[i]] = i
acc = np.mean(labels == y) * 100
print('准確率:%.2f%%' % acc)

3D畫圖分類結果:

mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
fig = plt.figure(figsize=(8, 8), facecolor='w')
ax = fig.add_subplot(111, projection='3d')  #
colors = plt.cm.Spectral(np.linspace(0, 1, n))
ax.scatter(sample[:, 0], sample[:, 1], sample[:, 2], s=50, c=labels,
           cmap=plt.cm.Spectral, marker='o', label=u'觀測值', depthshade=True)
plt.plot(sample[:, 0], sample[:, 1], sample[:, 2], lw=0.1, color='#A07070')
colors = plt.cm.Spectral(np.linspace(0, 1, n))
ax.scatter(means[:, 0], means[:, 1], means[:, 2], s=300, c=colors,
           edgecolor='r', linewidths=1, marker='*', label=u'中心')
 
x_min, y_min, z_min = sample.min(axis=0)
x_max, y_max, z_max = sample.max(axis=0)
x_min, x_max = expand(x_min, x_max)
y_min, y_max = expand(y_min, y_max)
z_min, z_max = expand(z_min, z_max)
ax.set_xlim((x_min, x_max))
ax.set_ylim((y_min, y_max))
ax.set_zlim((z_min, z_max))
plt.legend(loc='upper left')
plt.grid(True)
plt.title(u'GMHMM參數估計和類別判定', fontsize=12)
plt.show()
View Code

五、完整代碼

import numpy as np
from hmmlearn import hmm
import matplotlib.pyplot as plt
import matplotlib as mpl
from mpl_toolkits.mplot3d import Axes3D
from sklearn.metrics.pairwise import pairwise_distances_argmin
 
 
def expand(a, b):
    return 1.05 * a - 0.05 * b, 1.05 * b - 0.05 * a
 
 
np.random.seed(28)
n = 5  # 隱狀態數目
n_samples = 500  # 樣本數量
pi = np.random.rand(n)
pi /= pi.sum()
# print('初始概率:')
# print(pi)
 
A = np.random.rand(n, n)
mask = np.zeros((n, n), dtype=np.bool)
mask[0][1] = mask[0][4] = True
mask[1][0] = mask[1][2] = True
mask[2][1] = mask[2][3] = True
mask[3][2] = mask[3][4] = True
mask[4][0] = mask[4][3] = True
A[mask] = 0
for i in range(n):
    A[i] /= A[i].sum()
# print('轉移概率:')
# print(A)
 
# 給定均值
means = np.array(((30, 30, 30), (0, 50, 20), (-25, 30, 10),
                  (-15, 0, 25), (15, 0, 40)), dtype=np.float)
for i in range(n):
    means[i, :] /= np.sqrt(np.sum(means ** 2, axis=1))[i]
# print(means)
 
# 給定方差
covars = np.empty((n, 3, 3))
for i in range(n):
    covars[i] = np.diag(np.random.rand(3) * 0.02 + 0.001)  # np.random.rand ∈[0,1)
# print(covars)
 
# 產生對應的模擬數據
model = hmm.GaussianHMM(n_components=n, covariance_type='full')
model.startprob_ = pi
model.transmat_ = A
model.means_ = means
model.covars_ = covars
sample, labels = model.sample(n_samples=n_samples, random_state=0)
 
# 模型構建及估計參數
model = hmm.GaussianHMM(n_components=n, n_iter=10)
model.fit(sample)
y = model.predict(sample)
np.set_printoptions(suppress=True)
 
# 根據類別信息更改順序
order = pairwise_distances_argmin(means, model.means_, metric='euclidean')
# print(order)
pi_hat = model.startprob_[order]
A_hat = model.transmat_[order]
A_hat = A_hat[:, order]
means_hat = model.means_[order]
covars_hat = model.covars_[order]
change = np.empty((n, n_samples), dtype=np.bool)
for i in range(n):
    change[i] = y == order[i]
for i in range(n):
    y[change[i]] = i
acc = np.mean(labels == y) * 100
print('准確率:%.2f%%' % acc)
 
mpl.rcParams['font.sans-serif'] = [u'SimHei']
mpl.rcParams['axes.unicode_minus'] = False
fig = plt.figure(figsize=(8, 8), facecolor='w')
ax = fig.add_subplot(111, projection='3d')  #
colors = plt.cm.Spectral(np.linspace(0, 1, n))
ax.scatter(sample[:, 0], sample[:, 1], sample[:, 2], s=50, c=labels,
           cmap=plt.cm.Spectral, marker='o', label=u'觀測值', depthshade=True)
plt.plot(sample[:, 0], sample[:, 1], sample[:, 2], lw=0.1, color='#A07070')
colors = plt.cm.Spectral(np.linspace(0, 1, n))
ax.scatter(means[:, 0], means[:, 1], means[:, 2], s=300, c=colors,
           edgecolor='r', linewidths=1, marker='*', label=u'中心')
 
x_min, y_min, z_min = sample.min(axis=0)
x_max, y_max, z_max = sample.max(axis=0)
x_min, x_max = expand(x_min, x_max)
y_min, y_max = expand(y_min, y_max)
z_min, z_max = expand(z_min, z_max)
ax.set_xlim((x_min, x_max))
ax.set_ylim((y_min, y_max))
ax.set_zlim((z_min, z_max))
plt.legend(loc='upper left')
plt.grid(True)
plt.title(u'GMHMM參數估計和類別判定', fontsize=12)
plt.show()
View Code

六、結語

通過這篇學習記錄,我們初步認識了HMM隱馬爾可夫模型的具體內部邏輯,另外舉例解析和最后python簡單實現一個例子,更直觀的去理解什么是HMM,它是如何工作的。到這里可能覺得代碼實現還有部分陌生的方法,因為HMM是一個比較復雜的任務,除了本文簡單入門,HMM還需要解決三個基本問題,認真閱讀的朋友會看到在代碼中有所體現:估計問題、序列問題和訓練問題(參數估計)。

這些問題等待接下來學習之后再來具體介紹,期待下一篇更核心的內容解析。

參考資料:《統計自然語言處理》、https//www.jianshu.com/p/083c8dfb9f0a

我的博客園:https://www.cnblogs.com/chenzhenhong/p/13537680.html

我的CSDN: https://blog.csdn.net/Charzous/article/details/108111860

 


 

版權聲明:本文為博主原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接和本聲明。
本文鏈接:https://blog.csdn.net/Charzous/article/details/108111860

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM