#encoding=utf-8
'''b表示詞彙的開始
m表示詞彙的中間
e表示詞彙的尾部
s表示詞彙單獨成詞
'''class
hmm(
object):
def__init__
(self)
: self.states =
['b'
,'m'
,'e'
,'s'
] self.load_para =
false
self.a_dic =
self.b_dic =
self.pai_dic =
defgeneratepropbility
(self,path)
:'''
統計概率,生成π,a,b
'''count_dic =
#統計各個狀態的次數,用於後面的歸一化使用
definit_parameters()
:'''
初始化pai,a,b三個權重矩陣
'''for state in self.states:
self.a_dic[state]
= self.pai_dic[state]
=0.0
self.b_dic[state]
= count_dic[state]=0
defmarklaebl
(word)
:'''
為訓練資料中的每乙個字,根據其所處的位置,打標籤
text是傳入的乙個詞
'''out_text =
if(len(word)==1
):'s')
else
:#將輸入的文字轉換成標籤序列的表示
out_text +=
['b']+
['m']*
(len
(word)-2
)+['e'
]return out_text
init_parameters(
)
line_num =-1
words =
set(
)with
open
(path,
'r',encoding=
'utf-8'
)as f:
data_lines = f.readlines(
)#獲取訓練資料
#對於資料中的每一行進行處理
for line in data_lines:
line_num +=
1 line = line.strip()if
not line:
continue
word_list =
[i for i in line if i !=
" "]
words |
=set
(word_list)
#words中去除了重複的詞彙
linelist = line.split(
) line_state =
for w in linelist:
line_state.extend(marklaebl(w)
)#將每乙個詞彙轉換成標籤 此時的line_state是乙個list,表示乙個句子所有的標籤
assert
len(word_list)
==len
(line_state)
for k,v in
enumerate
(line_state)
: count_dic[v]+=1
#計算各個標籤出現的總數
if k ==0:
self.pai_dic[v]+=1
#計算各個標籤出現在第乙個位置概率
else
: self.a_dic[line_state[k-1]
][v]+=1
#a_dic詞典的第乙個索引是前乙個狀態,v表示當前狀態
#b_dic詞典的第乙個索引是當前的狀態,第二個所有是當前狀態對應的字
self.b_dic[line_state[k]
][word_list[k]
]= \
self.b_dic[line_state[k]
].get(word_list[k],0
)+1.0#轉換成概率
self.pai_dic =
self.a_dic =
for k,v in self.a_dic.items()}
#這裡使用到了加1平滑
self.b_dic =
for k,v in self.b_dic.items()}
defviterbi
(self,text,states,pai,a,b)
:'''
維特比演算法過程
'''v =
path =
for y in states:
#第一步
v[0]
[y]= pai[y]
* b[y]
.get(text[0]
,0)#第乙個引數是時間,第二個引數是對應的狀態
path[y]
=[y]
for t in
range(1
,len
(text)):
#從第二個字的標籤開始迭代
) newpath =
# 檢查b中是否有產生該字的概率
neverseen = text[t]
notin b[
's']
.keys(
)and \
text[t]
notin b[
'm']
.keys(
)and \
text[t]
notin b[
'b']
.keys(
)and \
text[t]
notin b[
'e']
.keys(
)#對於每乙個可能的狀態進行取最大值的操作
for y in states:
#這裡先計算每乙個狀態生成該字的概率pb
pb = b[y]
.get(text[t],0
)ifnot neverseen else
1.0# y0是前乙個時刻的每乙個狀態,取概率的最大值和對應的前乙個時刻的狀態
(prob,state)
=max([
(v[t-1]
[y0]
*a[y0]
.get(y,0)
*pb,y0)
for y0 in states if v[t-1]
[y0]
>0]
) v[t]
[y]= prob
#這裡更新路徑,state是前乙個時刻的狀態,y是當前時刻的狀態
newpath[y]
= path[state]
+[y]
#更新總的路徑
path = newpath
#判斷最後乙個字是單獨成詞還是屬於乙個詞的一部分
if b[
'm']
.get(text[-1
],0)
> b[
's']
.get(text[-1
],0)
:(prob,state)
=max([
(v[len
(text)-1
][y]
,y)for y in
('e'
,'m')]
)else
:(prob,state)
=max([
(v[len
(text)-1
][y]
,y)for y in states]
)return
(prob,path[state]
)def
cut(self,text)
:'''
切分過程
'''#獲取最大最大概率和狀態列表
基於規則的中文分詞
正向最大匹配 maximum match method,mm法 的基本思想為 假定分詞詞典中的最長詞有i個漢字字元,則用被處理文件的當前字串中的前i個字作為匹配字段,查詢字典。若字典中存在這樣的乙個i字詞,則匹配成功,匹配欄位被作為乙個詞切分出來。如果詞典中找不到這樣的乙個i字詞,則匹配失敗,將匹配...
機器學習 HMM 演算法
已知觀測序列o o1,ot 估計模型 a,b 的引數,使得在該模型下觀測序列概率 p o 極大似然估計的方法 樣本中時刻 t 處於狀態 i 時刻 t 1 轉移到狀態 j的頻數ai j,則轉移狀態概率矩陣ai j 的估計a ij a ij j 1na ij樣本中狀態為 j 並觀測為 k的頻數是bj k...
中文分詞 基於字標註法的分詞
中文分詞字標註通常有2 tag,4 tag和6 tag這幾種方法,其中4 tag方法最為常用。標註集是依據漢字 其中也有少量的非漢字字元 在漢語詞中的位置設計的。1.2 tag法 2 tag是一種最簡單的標註方法,標註集合為,其將詞首標記設計為b,而將詞的其他位置標記設計為i。例如詞語 重慶 的標註...