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

image

題圖:by Lucas Davies

一、前言

分詞,我想是大多數(shù)大前端開發(fā)人員,都不會接觸到的一個概念。這個不影響我們了解它,畢竟我們要多方向發(fā)展。今天就來簡單介紹一些分詞,我盡量用簡介的語言來描述這個概念,并且最后再提供一個解決方案,希望對你有幫助。

分詞簡單來講就是把一句話,按照詞義,切分成一個個單獨的詞。這么說可能沒什么感覺,先看看它適用的場景。分詞是文本挖掘的基礎,通常會用于自然語言處理、分詞搜索、推薦等等領域。

二、分詞的原理和算法

2.1 什么是分詞

先理解一下分詞的概念。

分詞就是將連續(xù)的字序列按照一定的規(guī)范重新組合成詞序列的過程。在英文中,單詞之間會以空格作為分割符,將詞與詞之間進行分割,但是對于中文,沒有一個顯式的分割符。

正是因為缺乏這種顯式的分割符,導致我們對中文中的詞,進行分割的時候會出現(xiàn)很多的偏差。

2.2 分詞的算法

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

  • 基于字符串匹配的分詞算法
  • 基于理解的分詞算法
  • 基于統(tǒng)計的分詞算法

1. 基于字符串匹配的分詞算法

這種分詞方法,又叫機械分詞算法,它會提前維護一個大的字典,然后將句子和字典中的詞進行匹配,若匹配成功,則可以進行分詞處理

當然,它實際上會更復雜一些,因為當字典足夠大的時候,就又涉及到不同的匹配算法,這里就不展開講了。通常會基于 Trie 樹結構,來實現(xiàn)高效的詞圖掃描。

2. 基于理解的分詞算法

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

它通常會包含三部分:分詞子系統(tǒng)、句法語義子系統(tǒng)、總控部分。在總控部分的協(xié)調(diào)下,分詞子系統(tǒng)可以獲得有關詞、句子等的句法和語義信息,來對分詞歧義進行判斷,即它模擬了人對句子的理解過程。由于漢語語言知識的籠統(tǒng)、復雜性,難以將各種語言信息組織成機器可直接讀取的形式,因此目前基于理解的分詞系統(tǒng)還處在試驗階段。

3. 基于統(tǒng)計的分詞算法

給出大量已經(jīng)分詞的文本,利用統(tǒng)計機器學習模型學習詞語切分的規(guī)律(稱為訓練),從而實現(xiàn)對未知文本的切分。

隨著大規(guī)模語料庫的建立,統(tǒng)計機器學習方法的研究和發(fā)展,基于統(tǒng)計的中文分詞方法漸漸成為了主流方法。

2.3 分詞的訴求

雖然分詞的算法,講解起來很簡單,但是從現(xiàn)有的經(jīng)驗來看,幾乎是不存在通用且效果非常好的分詞系統(tǒng)。

每個領域,都有其獨特的詞匯,這很難通過有限的訓練數(shù)據(jù),捕捉到所有的語言特征。例如:通過人民日報訓練的分詞系統(tǒng),在網(wǎng)絡玄幻小說上,分詞的效果就不會好。

這是必然的,在分詞系統(tǒng)中,沒有銀彈。

不同的場景,對分詞的要求也差異很大,通??梢詮膬蓚€維度進行區(qū)分:分詞速度、分詞準確性。

例如分詞搜索,對速度要求就高于準確性的要求。而一些問答系統(tǒng)中,則需要對文本實現(xiàn)較深的理解,要求準確性高于速度要求。

不同的領域,不同的使用場景,對分詞的要求是不同的,所以我們不能片面的去理解分詞的準確率。并且隨著新詞的增加,訓練數(shù)據(jù)的變化,分詞的準確率也是在波動的。這也是為什么,現(xiàn)在吹噓分詞準確率的公司越來越少的原因。

2.4 分詞的解決方案

分詞是可以解決實際問題的功能,經(jīng)過這么長時間的反復迭代更新,市面上一家產(chǎn)生了一批有特色的分詞系統(tǒng)。例如:IK、Jieba、Ansj、Hanlp、Stanford分詞 等等。

有興趣可以一個個了解,接下來就其中的一個開源庫 Jieba,進行講解。

三、jieba

3.1 jieba 的優(yōu)點

jieba 是開源的,號稱是 Python 中,最好的中文分詞組件。并且是基于 MIT 的協(xié)議,使用起來無后顧之憂。

jieba 使用起來也非常的簡單,幾行代碼就可以實現(xiàn)分詞調(diào)用和詞性標注,而且速度還不錯。

它內(nèi)部維護了一個詞典,是根據(jù)人民日報分析獲得,在超出詞典之外的新詞,會基于 HMM 模型進行識別。

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

在分詞的速度上,精確模式能達到 400KB/s,全模式下能達到 1.5MB/s。同時除了 Python 版本之外,還有不同的人基于 Python 版的 jieba ,擴展出多種語言實現(xiàn),包括: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("他來到了網(wǎng)易杭研大廈")  # 默認是精確模式
print(", ".join(seg_list))

seg_list = jieba.cut_for_search("小明碩士畢業(yè)于中國科學院計算所,后在日本京都大學深造")  # 搜索引擎模式
print(", ".join(seg_list))

輸出的結果:

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

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

【新詞識別】:他, 來到, 了, 網(wǎng)易, 杭研, 大廈    (此處,“杭研”并沒有在詞典中,但是也被Viterbi算法識別出來了)

【搜索引擎模式】: 小明, 碩士, 畢業(yè), 于, 中國, 科學, 學院, 科學院, 中國科學院, 計算, 計算所, 后, 在, 日本, 京都, 大學, 日本京都大學, 深造

前面也提到,jieba 自身維護了一個詞組的字典,如果自身需求上有專有名詞需要拆分,還可以通過 jieba.Tokenizer(dictionary=DEFAULT_DICT) 自定義一個字典信息。

3.2 jieba 的分詞算法

匹配的算法,說起來就復雜了,這里就簡單介紹一下 jiaba 分詞匹配的原理。

首先,jieba 分詞已經(jīng)自帶了一個 dict.txt 的詞典,里面有 2w 多個詞條,包括出現(xiàn)的次數(shù)和詞性,這是作者自己基于人民日報為主的資料,訓練的出來的。

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

其次,在需要對句子進行分詞的時候,再根據(jù)前面生成的 Trie 數(shù),生成有向無環(huán)圖(DAG),這一步的意義在于,消除分詞中的歧義,提高切分準確度,找出這句話中,所有可能的詞。

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

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

HMM 模型中,將中文詞匯按照 BEMS 四個狀態(tài)來標記, B 是開始 begin 位置, E 是 end, 是結束位置, M 是 middle, 是中間位置, S 是 singgle, 單獨成詞的位置, 沒有前, 也沒有后. 也就是說, 他采用了狀態(tài)為(B,E,M,S)這四種狀態(tài)來標記中文詞語, 比如北京可以標注為 BE, 即 北/B 京/E, 表示北是開始位置, 京是結束位置, 中華民族可以標注為 BMME , 就是開始, 中間, 中間, 結束.

作者通過對大量語料的訓練,得到了 finalseg 目錄下的訓練結果,有興趣可以自行研究。

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

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

這就是 jieba 分詞的執(zhí)行過程。

四、jieba(Java or Android)

4.1 Java 版的 jieba

jieba 發(fā)展到現(xiàn)在,已經(jīng)支持眾多的版本。Java 版并非原作者開發(fā),而是 hanban 參考原作者的分詞原理,進行開發(fā)的。

不過 Java 版并沒有原版 Python 版本那么強大,做了部分閹割,例如關鍵詞提取就沒有實現(xiàn)。

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

1. 引入依賴(穩(wěn)定版)

<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++。", "我不喜歡日本和服。", "雷猴回歸人間。",
                      "工信處女干事每月經(jīng)過下屬科室都要親口交代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

測試結果還算理想,單線程,對測試文本逐行分詞,并循環(huán)調(diào)用上萬次的效率分析。

循環(huán)調(diào)用一萬次
第一次測試結果:
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

循環(huán)調(diào)用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
統(tǒng)計結果:詞典加載時間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 的體積,這沒有什么很好的規(guī)避方法。而且因為設備的配置,還會影響到分詞的效率。

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

jieba(java) 使用 maven 管理,所以需要 Gradle 簡單配置一下,讓其支持。

1. 配置 build.gradle

repositories {
    google()
    jcenter()
    mavenCentral()
}

2. 引入依賴

api 'com.huaban:jieba-analysis:1.0.2'

引入之后,使用細節(jié)就沒什么好說的了,和 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


聯(lián)機圓桌」??推薦我的知識星球,一年 50 個優(yōu)質(zhì)問題,上桌聯(lián)機學習。

公眾號后臺回復成長『成長』,將會得到我準備的學習資料,也能回復『加群』,一起學習進步;你還能回復『提問』,向我發(fā)起提問。

推薦閱讀:

寫作是核心競爭力 | Google 工程師解密“猜畫小歌” | 圖解:HTTP 范圍請求 | Android P 適配經(jīng)驗 | 技術創(chuàng)業(yè)選擇清單 | HTTP傳輸編碼 | 什么正在消耗你? | HTTP 內(nèi)容編碼 | 圖解 HTTP 緩存 | 聊聊 HTTP 的 Cookie | 輔助模式實戰(zhàn) | Accessibility 輔助模式 | 小程序 Flex 布局 | 好的 PR 讓你更靠譜 | 密碼管理之道

image
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 常用概念: 自然語言處理(NLP) 數(shù)據(jù)挖掘 推薦算法 用戶畫像 知識圖譜 信息檢索 文本分類 常用技術: 詞級別...
    御風之星閱讀 10,027評論 1 25
  • 轉自 進擊的Coder 公眾號 原理 中文分詞,即 Chinese Word Segmentation,即將一個漢...
    Epiphron閱讀 11,760評論 2 56
  • jieba分詞,學習,為了全面了解該模塊,,預設學習路線:官方文檔——優(yōu)秀博客文章——實踐學習 官方文檔部分 (文...
    竹林徒兒閱讀 4,492評論 1 12
  • 這些年風風雨雨的,道路也是崎嶇。有你陪伴,再苦也不覺得累。而且爬上山頂后看到的風景是最美的。 你的善良溫婉讓我心暖...
    中通快遞_5a11閱讀 196評論 0 0
  • 2、傍晚和好友相約去泡溫泉,感覺到她是一個與我心靈相通的人,與她聊天能感覺到能量的流動,又一次證明同頻相吸! 3、...

友情鏈接更多精彩內(nèi)容