中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Python中的jieba源碼分析

發布時間:2021-09-01 14:23:03 來源:億速云 閱讀:175 作者:chen 欄目:編程語言

本篇內容主要講解“Python中的jieba源碼分析”,感興趣的朋友不妨來看看。本文介紹的方法操作簡單快捷,實用性強。下面就讓小編來帶大家學習“Python中的jieba源碼分析”吧!

前言

jieba分詞是Python 里面幾個比較流行的中文分詞工具之一。為了理解分詞工具的工作原理,以及實現細節對jieba進行了詳細的閱讀。

讀代碼之前,我有幾個問題是這樣的:

分詞工具的實現都有哪幾個步驟?
結巴分詞的文檔說是使用了HMM模型,但是HMM 模型是如何運用在分詞工具中的?,以及模型是如何產生的?
幾乎所有的分詞工具都支持用戶添加詞庫,但是用戶詞庫到底在分詞過程中扮演什么角色?
簡介

jieba 分詞支持三種分詞模式,官方文檔給出了如下的Example

import jieba
 
seg_list = jieba.cut("我來到北京清華大學", cut_all=True)
print("Full Mode: " + "/ ".join(seg_list))  # 全模式
 seg_list = jieba.cut("我來到北京清華大學", cut_all=False)
print("Default Mode: " + "/ ".join(seg_list))  # 精確模式
 seg_list = jieba.cut("他來到了網易杭研大廈")  # 默認是精確模式print(", ".join(seg_list))
 
seg_list = jieba.cut_for_search("小明碩士畢業于中國科學院計算所,后在日本京都大學深造")  # 搜索引擎模式print(", ".join(seg_list))

考慮到文章篇幅的限制,我會詳細解讀默認模式也就是jieba.cut方法的所有實現。 閱讀過程中會涉及一些算法原理,本文不做詳細解釋。

首先使用概率無向圖,獲得最大概率路徑.概率無向圖的構建完全依賴于字典,最大概率路徑求解也是依賴字典中的詞頻。 最后使用HMM模型來解決未登錄詞(Out Of Vocabulary) ,所以在整個過程如果沒有模型也是可以的,只要你有一個很好的詞典。最大概率路徑的求解還有很多方法,記得HanLP的求解就有實現最短路徑。

粗分

首先會使用正則將文本切分,正則什么樣?就跟現則的是默認模式還是全模式。正則如下:

re_han_default = re.compile("([\u4E00-\u9FD5a-zA-Z0-9+#&\._]+)", re.U)
re_han_cut_all = re.compile("([\u4E00-\u9FD5]+)", re.U)

到底有什么區別: 我寫了個測試:

test_str = u'我在重慶abc,他也在重慶? 1234你在重慶嗎'print (re_han_default.split(test_str))print (re_han_cut_all.split(test_str))

輸出:

['', '我在重慶abc', ',', '他也在重慶', '? ', '1234你在重慶嗎', '']
['', '我在重慶', 'abc,', '他也在重慶', '? 1234', '你在重慶嗎', '']

上面輸出的list 里面每一個被成為block。

細分

對粗分產生的blok ‘abc’這樣的不能被re.han匹配的會直接作為結果反回。對于和中文連在一起的會進入下一個階段細分。

DAG構建

細分的第一步是構建 DAG 即有向無環圖。構建的核心代碼如下:

def get_DAG(self, sentence):        self.check_initialized() # 初始化,加載詞典
        DAG = {}
        N = len(sentence)        for k in xrange(N):
            tmplist = []
            i = k
            frag = sentence[k]            while i < N and frag in self.FREQ:
                if self.FREQ[frag]:
                    tmplist.append(i)
                i += 1
                frag = sentence[k:i + 1]            if not tmplist:
                tmplist.append(k)
            DAG[k] = tmplist        return DAG

怎么個意思呢: 舉個例子 我來到北京清華大學 產生的DAG 結果如下:

{0: [0], 1: [1, 2], 2: [2], 3: [3, 4], 4: [4], 5: [5, 6, 8], 6: [6, 7], 7: [7, 8], 8: [8]}

使用dict 來存儲圖數據結構。字典中的key 是沒個字對應句子的index,后面的value 是一個list就是可達的路徑。比如{1:[1,2]}意思就是“來”和“來到”這兩個詞在詞典中存在。其他的類推。

圖的產生依賴于self.FREQ這個變量,這是存儲字典的,其結構是詞做key ,詞出現次數做value 的dict. 所以詞典的好壞對分詞結果會有很大的影響。如果根本不存在的路徑給連上了,應該連上的沒有連上。后面的HMM模型也是沒辦法解決的后者,當然最大概率路徑會解決部分第一個問題,但是都是有限的。所以詞典是相當關鍵的。

最大概率路徑求解

有了上面的DAG 下面求是求解最大概率路徑。這個問題有很多中方法,jieba 使用的是動態規劃。先不解釋動態規劃是什么,直接看代碼,

def calc(self, sentence, DAG, route):
        N = len(sentence)
        route[N] = (0, 0)
        logtotal = log(self.total)        for idx in xrange(N - 1, -1, -1):
            route[idx] = max((log(self.FREQ.get(sentence[idx:x + 1]) or 1) -
                              logtotal + route[x + 1][0], x) for x in DAG[idx])

真個過程就上面幾行。關鍵就在max 那一句。這個問題不在這里展開。但是有個小的技巧說下:在對很小的數據進行操作的時候,Python 也是可能向下溢出的,什么意思看下面的例子:

b = 0.0000001print b**100

結果會打印0.0 所有有個方法就是取log 。這個方法在很多地方都是有用的。 上面還用到了連個tuple比較這一技巧。

求解的結果如果分詞時候參數設置的不適用HMM模型,到這里就結束了。求解結果部分如下:key 同樣是對應的index.第二個就代表的是來到這個詞。

{0: (-32.587853155857076, 0), 1: (-27.379629658355885, 2),}
未登錄詞

上面的最大概率在一定程度上解決了歧義問題,但是在分詞里面還有另外一個問題未登錄詞問題也叫OOV(Out Of Vocabulary). jieba 使用HMM來識別未登錄詞。 比如: “我來到譽存科技” 這句話,產生的最大概率路徑是

{0: (-42.29693140266269, 0), 1: (-37.0887079051615, 2), 2: (-33.93639839927486, 2), 3: (-28.257272562332492, 3), 4: (-17.872975353951055, 4), 5: (-8.250710549196151, 6), 6: (-10.881580216048834, 6), 7: (0, 0)}

看到3,和4 都是獨立的詞,如果不使用HMM 這個詞就會被分成兩個字。其邏輯就是把多個連續的單字組合成新的blok 使用HMM來切分。HMM到底怎么切分呢?

HMM

HMM 隱馬模型的定義自己可以去查,就算查完你也不一定能說清楚到底在分詞的時候怎么使用的,但是不查絕對不知道。 在分詞之前語料會被標注,標注的方式有很多中。其中比較多的是BMES對應的是B(begin)詞的開頭,M(Middle)詞的中間,E(End)詞的結束,S(Single)單個的詞 HMM有幾個概念,和分詞這個具體問題的對應關系如下:

狀態序列(state sequence):BMES 這些狀態
觀測序列(observation sequence):就是看到的需要分詞的句子,所有的字組成一個序列。
現在的問題就是一直觀測序列求狀態序列。但是第一部我們需要建立HMM模型。 HMM 有三個基本組成: 初始概率狀態概率分布A 狀態轉移矩陣pi 觀測概率分布B

如果有了上面三個元素一個HMM模型就是定好了。當然還有HMM模型有很多假設,此處省略。 jieba 是如何得到這三個變量的了。這就是HMM的學習問題 了。在標注好的語料之上。可以使用極大似然估計來估計這三個參數。這里也看到,語料是關鍵因素,語料的質量決定這三個參數。其實估計的過程不管其中的原理就是一些統計計算。jieba 把這三個元素分別存貯在三個py文件中:

prob_start.py: 初始狀態概率 prob_trans.py: 狀態轉移 prob_emit.py: 觀測概率分布

看看 prob_start:

P={'B': -0.26268660809250016, 'E': -3.14e+100, 'M': -3.14e+100, 'S': -1.4652633398537678}

-3.14e+100表示的是無窮小。意思就是第一個字不可能是E,或者M.只可能是B,S具體是多少,使用語料中的頻率做估計。

到此,相信大家對“Python中的jieba源碼分析”有了更深的了解,不妨來實際操作一番吧!這里是億速云網站,更多相關內容可以進入相關頻道進行查詢,關注我們,繼續學習!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

磴口县| 临邑县| 辽中县| 周宁县| 固原市| 石城县| 宜都市| 彩票| 浦城县| 郓城县| 汝城县| 綦江县| 易门县| 荔浦县| 麟游县| 海口市| 菏泽市| 施甸县| 五原县| 广水市| 五寨县| 阳原县| 阜城县| 体育| 来凤县| 甘孜县| 濮阳市| 长阳| 顺昌县| 广丰县| 斗六市| 嘉义县| 普格县| 神木县| 秦安县| 波密县| 镇巴县| 芜湖市| 黎川县| 麦盖提县| 洛南县|