分詞,難在哪裏?科普+解決方案!

題圖:by Lucas Davies前端

1、前言

分詞,我想是大多數大前端開發人員,都不會接觸到的一個概念。這個不影響咱們瞭解它,畢竟咱們要多方向發展。今天就來簡單介紹一些分詞,我儘可能用簡介的語言來描述這個概念,而且最後再提供一個解決方案,但願對你有幫助。java

分詞簡單來說就是把一句話,按照詞義,切分紅一個個單獨的詞。這麼說可能沒什麼感受,先看看它適用的場景。分詞是文本挖掘的基礎,一般會用於天然語言處理、分詞搜索、推薦等等領域。python

2、分詞的原理和算法

2.1 什麼是分詞

先理解一下分詞的概念。nginx

分詞就是將連續的字序列按照必定的規範從新組合成詞序列的過程。在英文中,單詞之間會以空格做爲分割符,將詞與詞之間進行分割,可是對於中文,沒有一個顯式的分割符。git

正是由於缺少這種顯式的分割符,致使咱們對中文中的詞,進行分割的時候會出現不少的誤差。github

2.2 分詞的算法

中文分詞有難度,不過也有成熟的解決方案。現有的分詞算法,大概可分爲三類:算法

  • 基於字符串匹配的分詞算法
  • 基於理解的分詞算法
  • 基於統計的分詞算法

1. 基於字符串匹配的分詞算法小程序

這種分詞方法,又叫機械分詞算法,它會提早維護一個大的字典,而後將句子和字典中的詞進行匹配,若匹配成功,則能夠進行分詞處理api

固然,它實際上會更復雜一些,由於當字典足夠大的時候,就又涉及到不一樣的匹配算法,這裏就不展開講了。一般會基於 Trie 樹結構,來實現高效的詞圖掃描。緩存

2. 基於理解的分詞算法

這種分詞方法,經過讓計算機,模擬人對句子的理解,達到識別詞組的效果。其基本思想是在分詞的同事進行句法、語義的分析,利用句法和語義信息來處理歧義現象

它一般會包含三部分:分詞子系統、句法語義子系統、總控部分。在總控部分的協調下,分詞子系統能夠得到有關詞、句子等的句法和語義信息,來對分詞歧義進行判斷,即它模擬了人對句子的理解過程。因爲漢語語言知識的籠統、複雜性,難以將各類語言信息組織成機器可直接讀取的形式,所以目前基於理解的分詞系統還處在試驗階段。

3. 基於統計的分詞算法

給出大量已經分詞的文本,利用統計機器學習模型學習詞語切分的規律(稱爲訓練),從而實現對未知文本的切分。

隨着大規模語料庫的創建,統計機器學習方法的研究和發展,基於統計的中文分詞方法漸漸成爲了主流方法。

2.3 分詞的訴求

雖然分詞的算法,講解起來很簡單,可是從現有的經驗來看,幾乎是不存在通用且效果很是好的分詞系統。

每一個領域,都有其獨特的詞彙,這很難經過有限的訓練數據,捕捉到全部的語言特徵。例如:經過人民日報訓練的分詞系統,在網絡玄幻小說上,分詞的效果就不會好。

這是必然的,在分詞系統中,沒有銀彈。

不一樣的場景,對分詞的要求也差別很大,一般能夠從兩個維度進行區分:分詞速度、分詞準確性

例如分詞搜索,對速度要求就高於準確性的要求。而一些問答系統中,則須要對文本實現較深的理解,要求準確性高於速度要求。

不一樣的領域,不一樣的使用場景,對分詞的要求是不一樣的,因此咱們不能片面的去理解分詞的準確率。而且隨着新詞的增長,訓練數據的變化,分詞的準確率也是在波動的。這也是爲何,如今吹噓分詞準確率的公司愈來愈少的緣由。

2.4 分詞的解決方案

分詞是能夠解決實際問題的功能,通過這麼長時間的反覆迭代更新,市面上一家產生了一批有特點的分詞系統。例如:IK、Jieba、Ansj、Hanlp、Stanford分詞 等等。

有興趣能夠一個個瞭解,接下來就其中的一個開源庫 Jieba,進行講解。

3、jieba

3.1 jieba 的優勢

jieba 是開源的,號稱是 Python 中,最好的中文分詞組件。而且是基於 MIT 的協議,使用起來無後顧之憂。

jieba 使用起來也很是的簡單,幾行代碼就能夠實現分詞調用和詞性標註,並且速度還不錯。

它內部維護了一個詞典,是根據人民日報分析得到,在超出詞典以外的新詞,會基於 HMM 模型進行識別。

它提供三種分詞模式:精準模式、全模式、搜索模式。全模式是找到全部可能的詞語,搜索模式是在精確模式的基礎上對長詞進行切分,提升分割率。

在分詞的速度上,精確模式能達到 400KB/s,全模式下能達到 1.5MB/s。同時除了 Python 版本以外,還有不一樣的人基於 Python 版的 jieba ,擴展出多種語言實現,包括:JavaScript、Java、Golang、R、PHP 等。

jieba 的使用

jieba 的代碼對 Python 2/3 均兼容,在使用以前,須要經過命令 pip install jieba 或者 pip3 install jieba 進行安裝。

具體 Api,就不展開講了,有興趣能夠去查看 Github 上的文檔(文末有地址)。

這裏提供一個簡單的代碼示例,來感覺一下 jieba 的方便與強大。

# encoding=utf-8
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))
複製代碼

輸出的結果:

【全模式】: 我/ 來到/ 北京/ 清華/ 清華大學/ 華大/ 大學

【精確模式】: 我/ 來到/ 北京/ 清華大學

【新詞識別】:他, 來到, 了, 網易, 杭研, 大廈    (此處,「杭研」並無在詞典中,可是也被Viterbi算法識別出來了)

【搜索引擎模式】: 小明, 碩士, 畢業, 於, 中國, 科學, 學院, 科學院, 中國科學院, 計算, 計算所, 後, 在, 日本, 京都, 大學, 日本京都大學, 深造
複製代碼

前面也提到,jieba 自身維護了一個詞組的字典,若是自身需求上有專有名詞須要拆分,還能夠經過 jieba.Tokenizer(dictionary=DEFAULT_DICT) 自定義一個字典信息。

3.2 jieba 的分詞算法

匹配的算法,提及來就複雜了,這裏就簡單介紹一下 jiaba 分詞匹配的原理。

首先,jieba 分詞已經自帶了一個 dict.txt 的詞典,裏面有 2w 多個詞條,包括出現的次數和詞性,這是做者本身基於人民日報爲主的資料,訓練的出來的。

jieba 會先將這個詞典中的數據,放到一個 Trie 樹中,Trie 樹是有名的前綴樹,當一個詞語的前面幾個字同樣的時候,就標識他們具備相同的前綴,就可使用 Trie 數來存儲,具備查找速度快的優點。

其次,在須要對句子進行分詞的時候,再根據前面生成的 Trie 數,生成有向無環圖(DAG),這一步的意義在於,消除分詞中的歧義,提升切分準確度,找出這句話中,全部可能的詞。

到這一步,基本上就完成了,全部字典中記錄的詞,進行分詞的過程。

可是若是你把 dict.txt 這個字典刪除,jieba 依然能夠進行分詞,只是拆分出來的詞,大部分的長度爲 2。這是由於,對於未在字典中收錄的詞,基於隱馬爾科夫模型(HMM)來預測分詞,使用的是 Viterbi 算法。

HMM 模型中,將中文詞彙按照 BEMS 四個狀態來標記, B 是開始 begin 位置, E 是 end, 是結束位置, M 是 middle, 是中間位置, S 是 singgle, 單獨成詞的位置, 沒有前, 也沒有後. 也就是說, 他採用了狀態爲(B,E,M,S)這四種狀態來標記中文詞語, 好比北京能夠標註爲 BE, 即 北/B 京/E, 表示北是開始位置, 京是結束位置, 中華民族能夠標註爲 BMME , 就是開始, 中間, 中間, 結束.

做者經過對大量語料的訓練,獲得了 finalseg 目錄下的訓練結果,有興趣能夠自行研究。

到這裏基本上就清晰了,jieba 分詞的過程主要有如下三步:

  1. 加載 dict.txt 字典,生成 Trie 樹。
  2. 對待分詞的句子,經過 Trie 樹,生成 DAG 圖,匹配出全部可能的詞。
  3. 再使用 HMM 模型,將字典中未收錄的詞,匹配出來。

這就是 jieba 分詞的執行過程。

4、jieba(Java or Android)

4.1 Java 版的 jieba

jieba 發展到如今,已經支持衆多的版本。Java 版並不是原做者開發,而是 hanban 參考原做者的分詞原理,進行開發的。

不過 Java 版並無原版 Python 版本那麼強大,作了部分閹割,例如關鍵詞提取就沒有實現。

有興趣能夠直接去看 Github : https://github.com/huaban/jieba-analysis/

1. 引入依賴(穩定版)

<dependency>
  <groupId>com.huaban</groupId>
  <artifactId>jieba-analysis</artifactId>
  <version>1.0.2</version>
</dependency>
複製代碼

2. 如何使用

@Test
public void testDemo() {
    JiebaSegmenter segmenter = new JiebaSegmenter();
    String[] sentences =
        new String[] {"這是一個伸手不見五指的黑夜。我叫孫悟空,我愛北京,我愛Python和C++。""我不喜歡日本和服。""雷猴迴歸人間。",
                      "工信處女幹事每個月通過下屬科室都要親口交代24口交換機等技術性器件的安裝工做""結果婚的和還沒有結過婚的"};
    for (String sentence : sentences) {
        System.out.println(segmenter.process(sentence, SegMode.INDEX).toString());
    }
}
複製代碼

3. 性能評估

做者在測試機上進行測試,配置爲:

Processor 2 Intel(R) Pentium(R) CPU G620 @ 2.60GHz
Memory:8GB
複製代碼

測試結果還算理想,單線程,對測試文本逐行分詞,並循環調用上萬次的效率分析。

循環調用一萬次
第一次測試結果:
time elapsed:12373, rate:2486.986533kb/s, words:917319.94/s
第二次測試結果:
time elapsed:12284, rate:2505.005241kb/s, words:923966.10/s
第三次測試結果:
time elapsed:12336, rate:2494.445880kb/s, words:920071.30/s

循環調用2萬次
第一次測試結果:
time elapsed:22237, rate:2767.593144kb/s, words:1020821.12/s
第二次測試結果:
time elapsed:22435, rate:2743.167762kb/s, words:1011811.87/s
第三次測試結果:
time elapsed:22102, rate:2784.497726kb/s, words:1027056.34/s
統計結果:詞典加載時間1.8s左右,分詞效率每秒2Mb多,近100萬詞。

2 Processor Intel(R) Core(TM) i3-2100 CPU @ 3.10GHz
12G 測試效果
time elapsed:19597, rate:3140.428063kb/s, words:1158340.52/s
time elapsed:20122, rate:3058.491639kb/s, words:1128118.44/s
複製代碼

4.2 在 Android 下使用 jieba

jieba(Java)版本,自己也是自帶詞典的,因此在 Android 下引入,會增大 Apk 的體積,這沒有什麼很好的規避方法。並且由於設備的配置,還會影響到分詞的效率。

不過若是非要使用在 Android 設備上,例如對搜索詞進行一個預處理,也是能夠的。

jieba(java) 使用 maven 管理,因此須要 Gradle 簡單配置一下,讓其支持。

1. 配置 build.gradle

repositories {
    google()
    jcenter()
    mavenCentral()
}
複製代碼

2. 引入依賴

api 'com.huaban:jieba-analysis:1.0.2'
複製代碼

引入以後,使用細節就沒什麼好說的了,和 Java 版本無差異。

參考:

https://github.com/fxsjy/jieba

https://github.com/huaban/jieba-analysis/

https://blog.csdn.net/John_xyz/article/details/54645527

http://www.infoq.com/cn/articles/nlp-word-segmentation


公衆號後臺回覆成長『成長』,將會獲得我準備的學習資料,也能回覆『加羣』,一塊兒學習進步;你還能回覆『提問』,向我發起提問。

推薦閱讀:

寫做是核心競爭力 | Google 工程師解密「猜畫小歌」 | 圖解:HTTP 範圍請求 | Android P 適配經驗 | 技術創業選擇清單 | HTTP傳輸編碼 | 什麼正在消耗你? | HTTP 內容編碼 | 圖解 HTTP 緩存 | 聊聊 HTTP 的 Cookie | 輔助模式實戰 | Accessibility 輔助模式 | 小程序 Flex 佈局 | 好的 PR 讓你更靠譜 | 密碼管理之道

相關文章
相關標籤/搜索