jieba中文分詞源碼分析(一)

一、緣由

接觸自然語言處理(NLP)有段時間,理論知識有些瞭解,挺想動手寫些東西,想想開源界關於NLP的東西肯定不少,其中分詞是NLP的基礎,遂在網上找了些資源,其中結巴分詞是國內程序員用python開發的一箇中文分詞模塊, 源碼已託管在github: 源碼地址 ,代碼用python實現,源碼中也有註釋,但一些細節並沒有相應文檔,因此這裏打算對源碼進行分析,一來把知識分享,讓更多的童鞋更快的對源碼有個認識,二來使自己對分詞這一塊有個更深入的理解。

二、中文分詞介紹

  • 爲什麼中文分詞
    1. 詞是最小的能夠獨立活動的有意義的語言成分
    2. 漢語是以字位單位,不像西方語言,詞與詞之間沒有空格之類的標誌指示詞的邊界
    3. 分詞問題爲中文文本處理的基礎性工作,分詞的好壞對後面的中文信息處理其關鍵作用
  • 中文分詞的難點
    1. 分詞規範,詞的定義還不明確 (《統計自然語言處理》宗成慶)
    2. 歧義切分問題,交集型切分問題,多義組合型切分歧義等
      結婚的和尚未結婚的 =>
      結婚/的/和/尚未/結婚/的
      結婚/的/和尚/未/結婚/的
    3. 未登錄詞問題
      有兩種解釋:一是已有的詞表中沒有收錄的詞,二是已有的訓練語料中未曾出現過的詞,第二種含義中未登錄詞又稱OOV(Out of Vocabulary)。對於大規模真實文本來說,未登錄詞對於分詞的精度的影響遠超歧義切分。一些網絡新詞,自造詞一般都屬於這些詞。
  • 漢語分詞方法
    1. 基於字典、詞庫匹配的分詞方法(基於規則)
      基於字符串匹配分詞,機械分詞算法。將待分的字符串與一個充分大的機器詞典中的詞條進行匹配。分爲正向匹配和逆向匹配;最大長度匹配和最小長度匹配;單純分詞和分詞與標註過程相結合的一體化方法。所以常用的有:正向最大匹配,逆向最大匹配,最少切分法。實際應用中,將機械分詞作爲初分手段,利用語言信息提高切分準確率。優先識別具有明顯特徵的詞,以這些詞爲斷點,將原字符串分爲較小字符串再機械匹配,以減少匹配錯誤率,或將分詞與詞類標註結合。
    2. 基於詞頻度統計的分詞方法(基於統計)
      相鄰的字同時出現的次數越多,越有可能構成一個詞語,對語料中的字組頻度進行統計,基於詞的頻度統計的分詞方法是一種全切分方法。jieba是基於統計的分詞方法,jieba分詞采用了動態規劃查找最大概率路徑, 找出基於詞頻的最大切分組合,對於未登錄詞,採用了基於漢字成詞能力的HMM模型,使用了Viterbi算法。
    3. 基於知識理解的分詞方法。
      該方法主要基於句法、語法分析,並結合語義分析,通過對上下文內容所提供信息的分析對詞進行定界,它通常包括三個部分:分詞子系統、句法語義子系統、總控部分。在總控部分的協調下,分詞子系統可以獲得有關詞、句子等的句法和語義信息來對分詞歧義進行判斷。這類方法試圖讓機器具有人類的理解能力,需要使用大量的語言知識和信息。由於漢語語言知識的籠統、複雜性,難以將各種語言信息組織成機器可直接讀取的形式。因此目前基於知識的分詞系統還處在試驗階段。

三、jieba中文分詞介紹

  • 特點
    1. 支持三種分詞模式:
      a. 精確模式,試圖將句子最精確地切開,適合文本分析;
      b. 全模式,把句子中所有的可以成詞的詞語都掃描出來, 速度非常快,但是不能解決歧義;
      c. 搜索引擎模式,在精確模式的基礎上,對長詞再次切分,提高召回率,適合用於搜索引擎分詞。
    2. 支持繁體分詞
    3. 支持自定義詞典
    4. MIT 授權協議
  • 安裝
    全自動安裝:easy_install jieba 或者 pip install jieba 或者把源代碼下載下來直接安裝,解壓後直接運行setup腳本:python setup.py install
  • jieba的主要功能
    詳見這裏 jieba主要功能其中主要包括:分詞;添加自定義詞典(開發者可以指定自己自定義的詞典,以便包含 jieba 詞庫裏沒有的詞);關鍵詞提取;詞性標註;並行分詞;ChineseAnalyzer for Whoosh 搜索引擎等
  • jieba分詞的算法策略
    1. 基於前綴詞典實現高效的詞圖掃描,生成句子中漢字所有可能成詞情況所構成的有向無環圖 (DAG)
    2. 採用了動態規劃查找最大概率路徑, 找出基於詞頻的最大切分組合
    3. 對於未登錄詞,採用了基於漢字成詞能力的 HMM 模型,使用了 Viterbi 算法
  • jieba源碼組織形式
    下面是jieba源碼的樹結構
jieba
|-- Changelog
|-- extra_dict
|   |-- dict.txt.big
|   |-- dict.txt.small
|   |-- idf.txt.big
|   `-- stop_words.txt
|-- jieba
|   |-- analyse
|   |   |-- analyzer.py
|   |   |-- idf.txt
|   |   |-- __init__.py
|   |   |-- textrank.py
|   |   `-- tfidf.py
|   |-- _compat.py
|   |-- dict.txt
|   |-- finalseg
|   |   |-- __init__.py
|   |   |-- prob_emit.p
|   |   |-- prob_emit.py
|   |   |-- prob_start.p
|   |   |-- prob_start.py
|   |   |-- prob_trans.p
|   |   `-- prob_trans.py
|   |-- __init__.py
|   |-- __main__.py
|   `-- posseg
|       |-- char_state_tab.p
|       |-- char_state_tab.py
|       |-- __init__.py
|       |-- prob_emit.p
|       |-- prob_emit.py
|       |-- prob_start.p
|       |-- prob_start.py
|       |-- prob_trans.p
|       |-- prob_trans.py
|       `-- viterbi.py
|-- LICENSE
|-- setup.py
`-- test
    |-- *.py
    |-- parallel
    |   |-- extract_tags.py
    |   `-- test*.py
    `-- userdict.txt

代碼行數統計(沒有統計test文件夾下的代碼):

    256 ./posseg/prob_start.py
   5307 ./posseg/prob_trans.py
    304 ./posseg/__init__.py
  89372 ./posseg/prob_emit.py
  61087 ./posseg/char_state_tab.py
     53 ./posseg/viterbi.py
    578 ./__init__.py
      4 ./finalseg/prob_start.py
      4 ./finalseg/prob_trans.py
    107 ./finalseg/__init__.py
  35226 ./finalseg/prob_emit.py
     31 ./_compat.py
     50 ./__main__.py
    111 ./analyse/tfidf.py
     37 ./analyse/analyzer.py
    104 ./analyse/textrank.py
     18 ./analyse/__init__.py
 192649 總用量

其中prob*.py的文件是作者事先訓練好的模型參數(λ=(A,B,π)),如狀態轉移概率、發射概率等。真正的代碼數也就:304+53+578+107+31+50+111+37+104+18=1393行(不包括test文件中的代碼),當然作者的代碼寫的比較簡潔。

  • jieba分詞模型的參數數據(λ=(A,B,π))是如何生成的?
    即文件finalseg/prob_*.py,中初始化概率,狀態轉移概率,發射概率怎麼算出來的?
    來源主要有兩個: 一個是網上能下載到的1998人民日報的切分語料還有一個msr的切分語料; 另一個是作者自己收集的一些txt小說,用ictclas把他們切分(可能有一定誤差)。 然後用python腳本統計詞頻 具體詳情
    要統計的主要有三個概率表:
    1) 位置轉換概率(狀態轉移概率),即B(開頭),M(中間),E(結尾),S(獨立成詞)四種狀態的轉移概率;
    2) 位置到單字的發射概率,比如P(“和”|M)表示一個詞的中間出現”和”這個字的概率;
    3) 詞語以某種狀態開頭的概率,其實只有兩種,要麼是B,要麼是S。

接下來就具體介紹jieba源碼了,具體源碼見github註釋

參考:

  1. 《 統計自然語言處理》 宗成慶
  2. 《統計學習方法》 李航
  3. http://www.cnblogs.com/flish/archive/2011/08/08/2131031.html
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章