jieba源碼研讀筆記(十二) - 詞性標注(使用DAG有向無環圖+動態規劃)
前言
在前篇中看到了POSTokenizer
的詞性標注核心函數包括:__cut_DAG_NO_HMM
及__cut
,__cut_detail
,__cut_DAG
。
恰如其名,__cut_DAG_NO_HMM
的功能是不使用HMM的詞性標注。
其它三個函數則會在使用HMM的模式中被使用。
本篇介紹的重點是不使用HMM的詞性標注。
__cut_DAG_NO_HMM
函數中用到的re_eng1
己經於jieba源碼研讀筆記(四) - 正則表達式介紹過,它配對的是長度為1的英數字。
def __cut_DAG_NO_HMM(self, sentence):
DAG = self.tokenizer.get_DAG(sentence)
route = {}
self.tokenizer.calc(sentence, DAG, route)
x = 0
N = len(sentence)
buf = ''
while x < N:
y = route[x][1] + 1
l_word = sentence[x:y]
#re_eng1:長度為1的英數字
if re_eng1.match(l_word):
buf += l_word
x = y
else:
if buf:
#buf裡只有與re_eng1配對的字
#所以這裡可以將它的詞性設為英文
yield pair(buf, 'eng')
buf = ''
#如果字典裡沒有l_word,就把它的詞性當成'x'(未知)
yield pair(l_word, self.word_tag_tab.get(l_word, 'x'))
x = y
if buf:
#buf裡只有與re_eng1配對的字
#所以這裡可以將它的詞性設為英文
yield pair(buf, 'eng')
buf = ''
此處代碼與jieba/__init__.py
裡的__cut_DAG_NO_HMM
雷同,可以參考jieba源碼研讀筆記(六) - 分詞之精確模式(使用動態規劃)。
不同之處僅在於:
self.get_DAG
及self.calc
變成self.tokenizer.get_DAG
及self.tokenizer.calc
if re_eng.match(l_word) and len(l_word) == 1:
被改成了if re_eng1.match(l_word)
yield
的東西由一個詞彙變成一個pair
可以從上面的代碼中看出,__cut_DAG_NO_HMM
是以匹配正則表達式re_eng1
及查找字典self.word_tag_tab
並用的方式來標注詞性。
測試:
import jieba.posseg as pseg
for w in pseg._lcut_internal_no_hmm("小明的英文名字是Ming"):
print(w)
"""
小/a #形容詞
明/a #形容詞
的/uj #結構助詞: 的
英文名字/n #名詞
是/v #動詞
Ming/eng #外語
"""
以上詞性解釋參考自彙整中文與英文的詞性標註代號:結巴斷詞器與FastTag / Identify the Part of Speech in Chinese and English。
參考連結
jieba源碼研讀筆記(四) - 正則表達式
jieba源碼研讀筆記(六) - 分詞之精確模式(使用動態規劃)
彙整中文與英文的詞性標註代號:結巴斷詞器與FastTag / Identify the Part of Speech in Chinese and English