成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

Python中的jieba源碼分析

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

成都創(chuàng)新互聯(lián)公司-專業(yè)網(wǎng)站定制、快速模板網(wǎng)站建設(shè)、高性價比宿州網(wǎng)站開發(fā)、企業(yè)建站全套包干低至880元,成熟完善的模板庫,直接使用。一站式宿州網(wǎng)站制作公司更省心,省錢,快速模板網(wǎng)站建設(shè)找我們,業(yè)務(wù)覆蓋宿州地區(qū)。費用合理售后完善,十載實體公司更值得信賴。

前言

jieba分詞是Python 里面幾個比較流行的中文分詞工具之一。為了理解分詞工具的工作原理,以及實現(xiàn)細(xì)節(jié)對jieba進(jìn)行了詳細(xì)的閱讀。

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

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

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

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

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

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

粗分

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

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

到底有什么區(qū)別: 我寫了個測試:

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。

細(xì)分

對粗分產(chǎn)生的blok ‘a(chǎn)bc’這樣的不能被re.han匹配的會直接作為結(jié)果反回。對于和中文連在一起的會進(jìn)入下一個階段細(xì)分。

DAG構(gòu)建

細(xì)分的第一步是構(gòu)建 DAG 即有向無環(huán)圖。構(gòu)建的核心代碼如下:

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

怎么個意思呢: 舉個例子 我來到北京清華大學(xué) 產(chǎn)生的DAG 結(jié)果如下:

{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 來存儲圖數(shù)據(jù)結(jié)構(gòu)。字典中的key 是沒個字對應(yīng)句子的index,后面的value 是一個list就是可達(dá)的路徑。比如{1:[1,2]}意思就是“來”和“來到”這兩個詞在詞典中存在。其他的類推。

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

最大概率路徑求解

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

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])

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

b = 0.0000001print b**100

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

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

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

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

{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 這個詞就會被分成兩個字。其邏輯就是把多個連續(xù)的單字組合成新的blok 使用HMM來切分。HMM到底怎么切分呢?

HMM

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

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

如果有了上面三個元素一個HMM模型就是定好了。當(dāng)然還有HMM模型有很多假設(shè),此處省略。 jieba 是如何得到這三個變量的了。這就是HMM的學(xué)習(xí)問題 了。在標(biāo)注好的語料之上??梢允褂脴O大似然估計來估計這三個參數(shù)。這里也看到,語料是關(guān)鍵因素,語料的質(zhì)量決定這三個參數(shù)。其實估計的過程不管其中的原理就是一些統(tǒng)計計算。jieba 把這三個元素分別存貯在三個py文件中:

prob_start.py: 初始狀態(tài)概率 prob_trans.py: 狀態(tài)轉(zhuǎn)移 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(jìn).只可能是B,S具體是多少,使用語料中的頻率做估計。

到此,相信大家對“Python中的jieba源碼分析”有了更深的了解,不妨來實際操作一番吧!這里是創(chuàng)新互聯(lián)網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

分享名稱:Python中的jieba源碼分析
地址分享:http://jinyejixie.com/article44/jjspee.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供外貿(mào)建站網(wǎng)站設(shè)計、服務(wù)器托管、網(wǎng)站維護(hù)建站公司、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

外貿(mào)網(wǎng)站建設(shè)
繁峙县| 南靖县| 应城市| 定西市| 临汾市| 青海省| 洮南市| 抚远县| 永川市| 龙游县| 东丰县| 虎林市| 娄烦县| 仪陇县| 安国市| 常德市| 巴彦县| 兴山县| 石首市| 和平县| 甘谷县| 平阴县| 甘洛县| 鞍山市| 临邑县| 衡山县| 华宁县| 屏边| 富锦市| 怀宁县| 鄂州市| 大余县| 莱芜市| 虎林市| 石楼县| 抚宁县| 北川| 银川市| 安宁市| 米脂县| 蚌埠市|