1. 程式人生 > 程式設計 >Python3爬蟲中關於中文分詞的詳解

Python3爬蟲中關於中文分詞的詳解

原理

中文分詞,即 Chinese Word Segmentation,即將一個漢字序列進行切分,得到一個個單獨的詞。表面上看,分詞其實就是那麼回事,但分詞效果好不好對資訊檢索、實驗結果還是有很大影響的,同時分詞的背後其實是涉及各種各樣的演算法的。

中文分詞與英文分詞有很大的不同,對英文而言,一個單詞就是一個詞,而漢語是以字為基本的書寫單位,詞語之間沒有明顯的區分標記,需要人為切分。根據其特點,可以把分詞演算法分為四大類:

·基於規則的分詞方法

·基於統計的分詞方法

·基於語義的分詞方法

·基於理解的分詞方法

下面我們對這幾種方法分別進行總結。

基於規則的分詞方法

這種方法又叫作機械分詞方法、基於字典的分詞方法,它是按照一定的策略將待分析的漢字串與一個“充分大的”機器詞典中的詞條進行匹配。若在詞典中找到某個字串,則匹配成功。該方法有三個要素,即分詞詞典、文字掃描順序和匹配原則。文字的掃描順序有正向掃描、逆向掃描和雙向掃描。匹配原則主要有最大匹配、最小匹配、逐詞匹配和最佳匹配。

·最大匹配法(MM)。基本思想是:假設自動分詞詞典中的最長詞條所含漢字的個數為 i,則取被處理材料當前字串序列中的前 i 個字元作為匹配欄位,查詢分詞詞典,若詞典中有這樣一個 i 字詞,則匹配成功,匹配欄位作為一個詞被切分出來;若詞典中找不到這樣的一個 i 字詞,則匹配失敗,匹配欄位去掉最後一個漢字,剩下的字元作為新的匹配欄位,再進行匹配,如此進行下去,直到匹配成功為止。統計結果表明,該方法的錯誤率 為 1/169。

·逆向最大匹配法(RMM)。該方法的分詞過程與 MM 法相同,不同的是從句子(或文章)末尾開始處理,每次匹配不成功時去掉的是前面的一個漢字。統計結果表明,該方法的錯誤率為 1/245。

·逐詞遍歷法。把詞典中的詞按照由長到短遞減的順序逐字搜尋整個待處理的材料,一直到把全部的詞切分出來為止。不論分詞詞典多大,被處理的材料多麼小,都得把這個分詞詞典匹配一遍。

·設立切分標誌法。切分標誌有自然和非自然之分。自然切分標誌是指文章中出現的非文字元號,如標點符號等;非自然標誌是利用詞綴和不構成詞的詞(包 括單音詞、複音節詞以及象聲詞等)。設立切分標誌法首先收集眾多的切分標誌,分詞時先找出切分標誌,把句子切分為一些較短的欄位,再用 MM、RMM 或其它的方法進行細加工。這種方法並非真正意義上的分詞方法,只是自動分詞的一種前處理方式而已,它要額外消耗時間掃描切分標誌,增加儲存空間存放那些非 自然切分標誌。

·最佳匹配法(OM)。此法分為正向的最佳匹配法和逆向的最佳匹配法,其出發點是:在詞典中按詞頻的大小順序排列詞條,以求縮短對分詞詞典的檢索時 間,達到最佳效果,從而降低分詞的時間複雜度,加快分詞速度。實質上,這種方法也不是一種純粹意義上的分詞方法,它只是一種對分詞詞典的組織方式。OM 法的分詞詞典每條詞的前面必須有指明長度的資料項,所以其空間複雜度有所增加,對提高分詞精度沒有影響,分詞處理的時間複雜度有所降低。

此種方法優點是簡單,易於實現。但缺點有很多:匹配速度慢;存在交集型和組合型歧義切分問題;詞本身沒有一個標準的定義,沒有統一標準的詞集;不同詞典產生的歧義也不同;缺乏自學習的智慧性。

基於統計的分詞方法

該方法的主要思想:詞是穩定的組合,因此在上下文中,相鄰的字同時出現的次數越多,就越有可能構成一個詞。因此字與字相鄰出現的概率或頻率能較好地反映成詞的可信度。可以對訓練文字中相鄰出現的各個字的組合的頻度進行統計,計算它們之間的互現資訊。互現資訊體現了漢字之間結合關係的緊密程度。當緊密程 度高於某一個閾值時,便可以認為此字組可能構成了一個詞。該方法又稱為無字典分詞。

該方法所應用的主要的統計模型有:N 元文法模型(N-gram)、隱馬爾可夫模型(Hiden Markov Model,HMM)、最大熵模型(ME)、條件隨機場模型(Conditional Random Fields,CRF)等。

在實際應用中此類分詞演算法一般是將其與基於詞典的分詞方法結合起來,既發揮匹配分詞切分速度快、效率高的特點,又利用了無詞典分詞結合上下文識別生詞、自動消除歧義的優點。

基於語義的分詞方法

語義分詞法引入了語義分析,對自然語言自身的語言資訊進行更多的處理,如擴充轉移網路法、知識分詞語義分析法、鄰接約束法、綜合匹配法、字尾分詞法、特徵詞庫法、矩陣約束法、語法分析法等。

·擴充轉移網路法。該方法以有限狀態機概念為基礎。有限狀態機只能識別正則語言,對有限狀態機作的第一次擴充使其具有遞迴能力,形成遞迴轉移網路 (RTN)。在RTN 中,弧線上的標誌不僅可以是終極符(語言中的單詞)或非終極符(詞類),還可以呼叫另外的子網路名字分非終極符(如字或字串的成詞條件)。這樣,計算機在 執行某個子網路時,就可以呼叫另外的子網路,還可以遞迴呼叫。詞法擴充轉移網路的使用, 使分詞處理和語言理解的句法處理階段互動成為可能,並且有效地解決了漢語分詞的歧義。

·矩陣約束法。其基本思想是:先建立一個語法約束矩陣和一個語義約束矩陣, 其中元素分別表明具有某詞性的詞和具有另一詞性的詞相鄰是否符合語法規則, 屬於某語義類的詞和屬於另一詞義類的詞相鄰是否符合邏輯,機器在切分時以之約束分詞結果。

基於理解的分詞方法

基於理解的分詞方法是通過讓計算機模擬人對句子的理解,達到識別詞的效果。其基本思想就是在分詞的同時進行句法、語義分析,利用句法資訊和語義資訊來處理歧義現象。它通常包括三個部分:分詞子系統、句法語義子系統、總控部分。在總控部分的協調下,分詞子系統可以獲得有關詞、句子等的句法和語義資訊來對分詞歧義進行判斷,即它模擬了人對句子的理解過程。這種分詞方法需要使用大量的語言知識和資訊。目前基於理解的分詞方法主要有專家系統分詞法和神經網路分詞法等。

·專家系統分詞法。從專家系統角度把分詞的知識(包括常識性分詞知識與消除歧義切分的啟發性知識即歧義切分規則)從實現分詞過程的推理機中獨立出來,使知識庫的維護與推理機的實現互不干擾,從而使知識庫易於維護和管理。它還具有發現交集歧義欄位和多義組合歧義欄位的能力和一定的自學習功能。

·神經網路分詞法。該方法是模擬人腦並行,分佈處理和建立數值計算模型工作的。它將分詞知識所分散隱式的方法存入神經網路內部,通過自學習和訓練修改內部權值,以達到正確的分詞結果,最後給出神經網路自動分詞結果,如使用 LSTM、GRU 等神經網路模型等。

·神經網路專家系統整合式分詞法。該方法首先啟動神經網路進行分詞,當神經網路對新出現的詞不能給出準確切分時,啟用專家系統進行分析判斷,依據知識庫進行推理,得出初步分析,並啟動學習機制對神經網路進行訓練。該方法可以較充分發揮神經網路與專家系統二者優勢,進一步提高分詞效率。

以上便是對分詞演算法的基本介紹,接下來我們再介紹幾個比較實用的分詞 Python 庫及它們的使用方法。

分詞工具

在這裡介紹幾個比較有代表性的支援分詞的 Python 庫,主要有:

1. jieba

專用於分詞的 Python 庫,GitHub:https://github.com/fxsjy/jieba,分詞效果較好。

支援三種分詞模式:

·精確模式,試圖將句子最精確地切開,適合文字分析。

·全模式,將句子中所有的可能成詞的詞語都掃描出來,速度非常快,但是不能解決歧義。

·搜尋引擎模式:在精確模式的基礎上,對長詞再次切分,提高召回率,適用於搜尋引擎分詞。

另外 jieba 支援繁體分詞,支援自定義詞典。

其使用的演算法是基於統計的分詞方法,主要有如下幾種:

·基於字首詞典實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖 (DAG);

·採用了動態規劃查詢最大概率路徑,找出基於詞頻的最大切分組合;

·對於未登入詞,採用了基於漢字成詞能力的 HMM 模型,使用了 Viterbi 演算法。

精確模式分詞

首先我們來看下精確模式分詞,使用 lcut() 方法,類似 cut() 方法,其引數和 cut() 是一致的,只不過返回結果是列表而不是生成器,預設使用精確模式,程式碼如下:

importjieba
string='這個把手該換了,我不喜歡日本和服,別把手放在我的肩膀上,工信處女幹事每月經過下屬科室都要親口交代24口
交換機等技術性器件的安裝工作'
result=jieba.lcut(string)
print(len(result),'/'.join(result))

結果:

38這個/把手/該換/了/,/我/不/喜歡/日本/和服/,/別/把手/放在/我/的/肩膀/上/,/工信處/女幹事/每月/經過/下屬/科室
/都/要/親口/交代/24/口/交換機/等/技術性/器件/的/安裝/工作

可見分詞效果還是不錯的。

全模式分詞

使用全模式分詞需要新增 cut_all 引數,將其設定為 True,程式碼如下:

result=jieba.lcut(string,cut_all=True)
print(len(result),'/'.join(result))

結果如下:

51這個/把手/該換/了///我/不/喜歡/日本/和服///別/把手/放在/我/的/肩膀/上///工信處/處女/女幹事/幹事/每月/月經
/經過/下屬/科室/都/要/親口/口交/交代/24/口交/交換/交換機/換機/等/技術/技術性/性器/器件/的/安裝/安裝工/裝工/工作

搜尋引擎模式分詞

使用搜索引擎模式分詞需要呼叫 cut_for_search() 方法,程式碼如下:

result=jieba.lcut_for_search(string)
print(len(result),'/'.join(result))

結果如下:

42這個/把手/該換/了/,/我/不/喜歡/日本/和服/,/別/把手/放在/我/的/肩膀/上/,/工信處/幹事/女幹事/每月/經過/下屬
/科室/都/要/親口/交代/24/口/交換/換機/交換機/等/技術/技術性/器件/的/安裝/工作

另外可以加入自定義詞典,如我們想把 日本和服 作為一個整體,可以把它新增到詞典中,程式碼如下:

jieba.add_word('日本和服')
result=jieba.lcut(string)
print(len(result),'/'.join(result))

結果如下:

37這個/把手/該換/了/,/我/不/喜歡/日本和服/,/別/把手/放在/我/的/肩膀/上/,/工信處/女幹事/每月/經過/下屬/科室
/都/要/親口/交代/24/口/交換機/等/技術性/器件/的/安裝/工作

可以看到切分結果中,日本和服 四個字就作為一個整體出現在結果中了,分詞數量比精確模式少了一個。

詞性標註

另外 jieba 還支援詞性標註,可以輸出分詞後每個詞的詞性,例項如下:

words=pseg.lcut(string)
print(list(map(lambdax:list(x),words)))

執行結果:

[['這個','r'],['把手','v'],['該',['換',['了','ul'],[',','x'],['我',['不','d'],['喜歡',['日本和服',['別',['放在',['的','uj'],['肩膀','n'],['上','f'],['工信處',['女幹事',['每月',['經過','p'],['下屬',['科室',['都',['要',['親口',['交代',['24','m'],['口',['交換機',['等','u'],['技術性',['器件',['安裝',['工作','vn']]

關於詞性的說明可以參考:https://gist.github.com/luw2007/6016931。

2. SnowNLP

SnowNLP: Simplified Chinese Text Processing,可以方便的處理中文文字內容,是受到了 TextBlob 的啟發而寫的,由於現在大部分的自然語言處理庫基本都是針對英文的,於是寫了一個方便處理中文的類庫,並且和 TextBlob 不同的是,這裡沒有用 NLTK,所有的演算法都是自己實現的,並且自帶了一些訓練好的字典。GitHub地址:https://github.com/isnowfy/snownlp。

分詞

這裡的分詞是基於 Character-Based Generative Model 來實現的,論文地址:http://aclweb.org/anthology//Y/Y09/Y09-2047.pdf,我們還是以上面的例子說明,相關使用說明如下:

fromsnownlpimportSnowNLP
string='這個把手該換了,我不喜歡日本和服,別把手放在我的肩膀上,工信處女幹事每月經過下屬科室都要親口交代24口
交換機等技術性器件的安裝工作'
s=SnowNLP(string)
result=s.words
print(len(result),'/'.join(result))

執行結果:

40這個/把手/該/換/了/,/我/不/喜歡/日本/和/服/,/別把手/放在/我/的/肩膀/上/,/工/信處女/幹事/每月/經過/下屬/科室
/都/要/親口/交代/24/口/交換機/等/技術性/器件/的/安裝/工作

經過觀察,可以發現分詞效果其實不怎麼理想,和服 被分開了,工信處 也被分開了,女幹事 也被分開了。

另外 SnowNLP 還支援很多功能,例如詞性標註(HMM)、情感分析、拼音轉換(Trie樹)、關鍵詞和摘要生成(TextRank)。

我們簡單看一個例項:

print('Tags:',list(s.tags))
print('Sentiments:',s.sentiments)
print('Pinyin:',s.pinyin)

執行結果:

Tags:[('這個','r'),('把手','Ng'),('該',('換','v'),('了','y'),(',','w'),('我',('不','d'),('喜歡',('日本','ns'),('和','c'),('服',('別把手','ad'),('放在',('的','u'),('肩膀','n'),('上','f'),('工','j'),('信處女',('幹事',('每月',('經過','p'),('下屬',('科室',('都',('要',('親口',('交代',('24','m'),('口','q'),('交換機',('等',('技術性',('器件',('安裝','vn'),('工作','vn')]
Sentiments:0.015678817603646866
Pinyin:['zhe','ge','ba','shou','gai','huan','liao',',','wo','bu','xi','ri','ben','he','fu','bie','fang','zai','de','jian','bang','shang','gong','xin','chu','nv','gan','shi','mei','yue','jing','guo','xia','shu','ke','dou','yao','qin','kou','jiao','dai','24','ji','deng','xing','qi','an','zhuang','zuo']

3. THULAC

THULAC(THU Lexical Analyzer for Chinese)由清華大學自然語言處理與社會人文計算實驗室研製推出的一套中文詞法分析工具包,GitHub 連結:https://github.com/thunlp/THULAC-Python,具有中文分詞和詞性標註功能。THULAC具有如下幾個特點:

能力強。利用整合的目前世界上規模最大的人工分詞和詞性標註中文語料庫(約含5800萬字)訓練而成,模型標註能力強大。

準確率高。該工具包在標準資料集Chinese Treebank(CTB5)上分詞的F1值可達97.3%,詞性標註的F1值可達到92.9%,與該資料集上最好方法效果相當。

速度較快。同時進行分詞和詞性標註速度為300KB/s,每秒可處理約15萬字。只進行分詞速度可達到1.3MB/s。

我們用一個例項看一下分詞效果:

importthulac
string='這個把手該換了,我不喜歡日本和服,別把手放在我的肩膀上,工信處女幹事每月經過下屬科室都要親口交代24口
交換機等技術性器件的安裝工作'
t=thulac.thulac()
result=t.cut(string)
print(result)

執行結果:

[['這個','w'],['日本','ns'],['和服',['別把手',['放',['在',['女','a'],['幹事','q'],'v']]

4. NLPIR

NLPIR 分詞系統,前身為2000年釋出的 ICTCLAS 詞法分析系統,GitHub 連結:https://github.com/NLPIR-team/NLPIR,是由北京理工大學張華平博士研發的中文分詞系統,經過十餘年的不斷完善,擁有豐富的功能和強大的效能。NLPIR是一整套對原始文字集進行處理和加工的軟體,提供了中介軟體處理效果的視覺化展示,也可以作為小規模資料的處理加工工具。主要功能包括:中文分詞,詞性標註,命名實體識別,使用者詞典、新詞發現與關鍵詞提取等功能。另外對於分詞功能,它有 Python 實現的版本,GitHub 連結:https://github.com/tsroten/pynlpir。

使用方法如下:

importpynlpir
pynlpir.open()
string='這個把手該換了,我不喜歡日本和服,別把手放在我的肩膀上,工信處女幹事每月經過下屬科室都要親口交代24口
交換機等技術性器件的安裝工作'
result=pynlpir.segment(string)
print(result)

執行結果如下:

[('這個','pronoun'),('把','preposition'),('手','noun'),'verb'),'modalparticle'),'punctuationmark'),'adverb'),'conjunction'),('別',('放',('在','particle'),'nounoflocality'),('信',('處女','numeral'),'classifier'),'verb')]

這裡 把手 和 和服 也被分開了。

5. NLTK

NLTK,Natural Language Toolkit,是一個自然語言處理的包工具,各種多種 NLP 處理相關功能,GitHub 連結:https://github.com/nltk/nltk。

但是 NLTK 對於中文分詞是不支援的,示例如下:

fromnltkimportword_tokenize
string='這個把手該換了,我不喜歡日本和服,別把手放在我的肩膀上,工信處女幹事每月經過下屬科室都要親口交代24口
交換機等技術性器件的安裝工作'
result=word_tokenize(string)
print(result)

結果:

['這個把手該換了,我不喜歡日本和服,別把手放在我的肩膀上,工信處女幹事每月經過下屬科室都要親口交代24口交換機等
技術性器件的安裝工作']

如果要用中文分詞的話,可以使用 FoolNLTK,它使用 Bi-LSTM 訓練而成,包含分詞、詞性標註、實體識別等功能,同時支援自定義詞典,可以訓練自己的模型,可以進行批量處理。

使用方法如下:

importfool
string='這個把手該換了,我不喜歡日本和服,別把手放在我的肩膀上,工信處女幹事每月經過下屬科室都要親口交代24口交換機
等技術性器件的安裝工作'
result=fool.cut(string)
print(result)

執行結果:

[['這個','把手','該','換','了','我','不','喜歡','日本','和服','別','把','手','放','在','的','肩膀','上','工信處','女','幹事','每月','經過','下屬','科室','都','要','親','口','交代','交換機','等','技術性','器件','安裝','工作']]

可以看到這個分詞效果還是不錯的。

另外還可以進行詞性標註,實體識別:

result=fool.pos_cut(string)
print(result)
_,ners=fool.analysis(string)
print(ners)

執行結果:

[[('這個','wd'),'vi'),('和服','pba'),'ude'),('工信處',('女','b'),('親','a'),'udeng'),'n')]]
[[(12,15,'location','日本')]]

6. LTP

語言技術平臺(Language Technology Platform,LTP)是哈工大社會計算與資訊檢索研究中心歷時十年開發的一整套中文語言處理系統。LTP制定了基於XML的語言處理結果表示,並在此基礎上提供了一整套自底向上的豐富而且高效的中文語言處理模組(包括詞法、句法、語義等6項中文處理核心技術),以及基於動態連結庫(Dynamic Link Library,DLL)的應用程式介面、視覺化工具,並且能夠以網路服務(Web Service)的形式進行使用。

LTP 有 Python 版本,GitHub地址:https://github.com/HIT-SCIR/pyltp,另外執行的時候需要下載模型,模型還比較大,下載地址:http://ltp.ai/download.html。

示例程式碼如下:

frompyltpimportSegmentor
string='這個把手該換了,我不喜歡日本和服,別把手放在我的肩膀上,工信處女幹事每月經過下屬科室都要親口交代24口交換機
等技術性器件的安裝工作'
segmentor=Segmentor()
segmentor.load('./cws.model')
result=list(segmentor.segment(string))
segmentor.release()
print(result)

執行結果:

41這個/把手/該/換/了/,/我/不/喜歡/日本/和服/,/別/把/手/放在/我/的/肩膀/上/,/工信/處女/幹事/每月/經過/下屬/科室
/都/要/親口/交代/24/口/交換機/等/技術性/器件/的/安裝/工作

可以發現 工信處、女幹事 沒有正確分開。

以上便是一些分詞庫的基本使用,個人比較推薦的有 jieba、THULAC、FoolNLTK。

以上就是Python3爬蟲中關於中文分詞的詳解的詳細內容,更多關於Python3爬蟲中文分詞的資料請關注我們其它相關文章!