【一】詞性標註python
詞性標註分爲2部分,首先是分詞,而後基於分詞結果作詞性標註。正則表達式
【二】jieba的詞性標註代碼流程詳解算法
1. 代碼位置函數
jieba/posseg/_init_.pythis
2. 流程分析code
def cut(sentence, HMM=True): """ Global `cut` function that supports parallel processing. Note that this only works using dt, custom POSTokenizer instances are not supported. """ global dt # 該pool 默認爲None if jieba.pool is None: # 調用POSTokenizer的cut接口進行詞性標註 for w in dt.cut(sentence, HMM=HMM): yield w else: parts = strdecode(sentence).splitlines(True) if HMM: result = jieba.pool.map(_lcut_internal, parts) else: result = jieba.pool.map(_lcut_internal_no_hmm, parts) for r in result: for w in r: yield w
能夠看出,對於未登陸詞,採用HMM模型進行分詞與詞性標註。接口
def __cut_internal(self, sentence, HMM=True): # 詞典加載 self.makesure_userdict_loaded() sentence = strdecode(sentence) # 中文正則表達式匹配 blocks = re_han_internal.split(sentence) # 設置分詞函數 if HMM: cut_blk = self.__cut_DAG else: cut_blk = self.__cut_DAG_NO_HMM for blk in blocks: # 若是是中文,則調用分詞接口進行分詞與詞性標註 if re_han_internal.match(blk): for word in cut_blk(blk): yield word else: tmp = re_skip_internal.split(blk) for x in tmp: if re_skip_internal.match(x): yield pair(x, 'x') else: for xx in x: # 若是是數字,則使用m標註詞性,因爲number的n和u已經用於其餘詞性,所以使用m if re_num.match(xx): yield pair(xx, 'm') # 若是是英文,標註爲eng elif re_eng.match(x): yield pair(xx, 'eng') # 不然,一概標註爲x else: yield pair(xx, 'x')
# 對於未位登陸詞,採用HMM模型進行詞性標註 def __cut_detail(self, sentence): blocks = re_han_detail.split(sentence) for blk in blocks: if re_han_detail.match(blk): # 使用HMM模型進行詞性標註 for word in self.__cut(blk): yield word else: tmp = re_skip_detail.split(blk) for x in tmp: if x: if re_num.match(x): yield pair(x, 'm') elif re_eng.match(x): yield pair(x, 'eng') else: yield pair(x, 'x')
def __cut(self, sentence): # 使用viterbi算法進行狀態序列求解,這裏的狀態序列包含2部分 # 一是:詞的位置,而是詞性。因爲一詞多性,所以須要計算出該詞機率最大的詞性 prob, pos_list = viterbi( sentence, char_state_tab_P, start_P, trans_P, emit_P) begin, nexti = 0, 0 for i, char in enumerate(sentence): pos = pos_list[i][0] if pos == 'B': begin = i elif pos == 'E': yield pair(sentence[begin:i + 1], pos_list[i][1]) nexti = i + 1 elif pos == 'S': yield pair(char, pos_list[i][1]) nexti = i + 1 if nexti < len(sentence): yield pair(sentence[nexti:], pos_list[nexti][1])
這裏,依舊使用viterbi算法進行狀態序列求解。這裏就不分析了,算法流程和前面的未登陸詞的分詞一致。只是強調一點,這裏的狀態序列包含兩部分:一是:字的位置,即BMES,而是詞對應的詞性,如 :n,a等ip
【三】總結it
jieba整體而言,包含以下三個功能:分詞、詞性標註、關鍵字提取。使用的都是傳統的方法,如基於詞典前綴的匹配、基於HMM模型對未登陸詞進行分割與詞性標註、基於TF-IDF和TextRank進行關鍵字提取。這三大功能,全都離不開jieba基於語料庫統計出來的詞典,包括詞頻、詞性、HMM模型參數(狀態轉移機率矩陣、發射機率矩陣、初始狀態機率向量)。io
要想使用jieba獲得好的分詞效果,須要替換本身的詞典,訓練本身的HMM參數,而這些,基本都是基於語料庫統計獲得的。