1.什么是HMM?
隱馬爾科夫鏈(HMM)是一個五元組:
- 隱狀態集合 ;
- 觀測狀態集合;
- 狀態概率轉移矩陣;
- 觀察狀態概率矩陣;
- 初始狀態概率分布;
2.HMM有兩個假設:
- 齊次馬爾可夫鏈假設:任意時刻的隱藏狀態只依賴與前一時刻的隱藏狀態。
- 觀測獨立性假設:任意時刻的觀察狀態,只依賴與當前時刻的隱藏狀態。
3.HMM可以解決3類基本問題:
- 評估觀察序列的概率。
- 學習模型參數。即給定觀察序列,估計模型的參數,是觀察序列出現的概率最大。
- 預測問題。即給定觀察序列和模型,求最有可能出現的對應狀態序列。
4.中文分詞
<1>抽象出五元組
- StatusSet。狀態集合為{B, M, E, S}.其中B表示詞首,M表示詞中間,E表示詞尾,S表示單字成詞。
- ObservedSet。觀察狀態集合就是所有的漢字,甚至包括標點符號組成的集合。
- TransProbMatrix。狀態轉移概率矩陣,就是{B, M, E, S} X {B, M, E, S}的一個4X4矩陣。
- EmitProbMatrix。觀察矩陣的每個元素都是一個條件概率,代表P(Observed[i]|Status[j])。
- InitStatus。初始狀態概率分布表示句子的第一個字屬於{B,E,M,S}這四種狀態的概率。
<2>模型訓練
A_dic = {} #狀態轉移概率矩陣
B_dic = {} #觀察概率矩陣
Count_dic = {} #記錄每一個狀態出現的次數
Pi_dic = {} #記錄了每一行第一個狀態出現的次數
word_set = set() #存放所有出現的字(包括數字,標點符號等)
state_list = ['B','M','E','S']
line_num #記錄樣本行數
按行遍歷訓練樣本:
(1) 獲取每行樣本對應的字符列表 word_list 以及狀態列表 line_state;
(2)記錄字符集合 word_set 以及行數 line_num;
(3)記錄每行第一個狀態出現的次數 Pi_dic[line_state[0]]+=1;
(4)記錄第 i-1 到 第 i 個狀態轉移的次數 A_dic[line_state[i-1]][line_state[i]]+=1;
(5)記錄每個狀態出現的次數 count_dic[line_state[i]]+=1;
(6)記錄每個狀態對應的發射概率 B_dic[line_state[i]][word_list[i]]+=1;
(7)統計概率
Pi_dic[state] = pi_dic[state] / line_num
A_dic[state1][state2] = A_dic[state1][state2] / count_dic[state1]
B_dic[state][word] = B_dic[state][word] / count_dic[state]
<3>利用Viterbi算法進行分詞
1 #obs:待分詞的字符串 2 #states:狀態列表('B','M','E','S') 3 #start_p:初始概率分布 4 #trans_p:轉移概率矩陣 5 #emit_p: 發射概率矩陣 6 def viterbi(obs, states, start_p, trans_p, emit_p): #維特比算法 7 V = [{}]#每個字對應一個字典,構成一個字典列表。字典格式:{‘B’:val,'M':val,'E':val,'S':val},val表示概率。字典表示當前字符對應的狀態概率 8 path = {}#以狀態y結尾的路徑如:{‘B’:['S','B'],'M':['B','M'],'E':['B','E'],'S':['S','S']} 9 for y in states: #字符串的第0個位置。初始值 10 V[0][y] = start_p[y] * emit_p[y].get(obs[0],0) #初始概率*發射概率。在位置0,以y狀態為末尾的狀態序列的最大概率 11 path[y] = [y]# 12 for t in range(1,len(obs)):#遍歷字符串后面的字符 13 V.append({}) 14 newpath = {} 15 for y in states: #從y0 -> y狀態的遞歸,y表示當前時刻的狀態,y0表示前一個時刻的狀態。 16 #prob對應狀態的最大概率,state對應最大概率下上一時刻的狀態。 17 #(prob, state) = max([(V[t-1][y0] * trans_p[y0].get(y,0) * emit_p[y].get(obs[t],0) ,y0) for y0 in states if V[t-1][y0]>0]) 18 (prob, state) = max([(V[t-1][y0] * trans_p[y0].get(y,0) * emit_p[y].get(obs[t],0) ,y0) for y0 in states]) 19 20 V[t][y] =prob 21 newpath[y] = path[state] + [y]#以狀態y結尾的路徑如:{‘B’:['S','B'],'M':['B','M'],'E':['B','E'],'S':['S','S']} 22 path = newpath #記錄狀態序列 23 (prob, state) = max([(V[len(obs) - 1][y], y) for y in states]) #在最后一個位置,以y狀態為末尾的狀態序列的最大概率 24 return (prob, path[state]) #返回概率和狀態序列
