Note: 本文主要修改與擷取了林志傑-如何使用 JIEBA 結巴中文分詞程式的內容。 文字雲的圖像來源為GoatWang-2018 iT 邦幫忙鐵人賽。
對中文的斷詞有興趣強烈建議可以參考:中文斷詞:斷句不要悲劇
本文主要是為了後續介詔word2vec的理論與實作的前置準備。
自然語言處理(Natural Language Processing)的其中一個重要環節就是中文斷詞的處理,比起英文斷詞,中文斷詞在先天上就比較難處理,比如電腦要怎麼知道「全台大停電」要斷詞成「全台 / 大 / 停電」呢?如果是英文「Power outage all over Taiwan」,就可以直接用空白字元來斷成「Power / outage / all / over / Taiwan」,可見中文斷詞真的是一個大問題啊~!
结巴 (jieba) 中文分詞是很好很簡單使用的Python中文分詞函式庫。 它有以下的特色:
jieba中文斷詞所使用的演算法是基於 Trie Tree 結構去生成句子中中文字所有可能成詞的情況,然後使用動態規劃(Dynamic programming)算法來找出最大機率的路徑,這個路徑就是基於詞頻的最大斷詞結果。對於辨識新詞(字典詞庫中不存在的詞)則使用了 HMM 模型(Hidden Markov Model)及 Viterbi 算法來辨識出來。
在中文斷詞-by Mark Chang的分享裡有詳細的解說。
三種分詞模式示範:
# encoding=utf-8
import jieba
seg_list = jieba.cut("我來到新竹清華大學", cut_all=True)
print("全模式: " + "/ ".join(seg_list)) # 全模式
seg_list = jieba.cut("我來到新竹清華大學", cut_all=False)
print("精確模式: " + "/ ".join(seg_list)) # 精確模式
seg_list = jieba.cut("他來到了台北101大樓") # 預設為精確模式
print("精確模式(預設): " +"/ ".join(seg_list))
seg_list = jieba.cut_for_search("Apache Spark是一個開源叢集運算框架,最初是由加州大學柏克萊分校AMPLab所開發。") # 搜索引擎模式
print("搜索引擎模式模式: " +"/ ".join(seg_list))
Building prefix dict from the default dictionary ... Loading model from cache /var/folders/vt/rfsxsh1j2b51dffzl9p5v72ngb1v7q/T/jieba.cache Loading model cost 0.929 seconds. Prefix dict has been built succesfully.
全模式: 我/ 來/ 到/ 新竹/ 清/ 華/ 大/ 學 精確模式: 我來/ 到/ 新竹/ 清華大學 精確模式(預設): 他來/ 到/ 了/ 台北/ 101/ 大樓 搜索引擎模式模式: Apache/ / Spark/ 是/ 一個/ 開源/ 叢集/ 運算/ 框架/ ,/ 最初/ 是/ 由/ 加州/ 大學柏克萊/ 分校/ AMPLab/ 所開發/ 。
據原作者的說法,使用預設詞庫的話,繁體中文的斷詞結果應該會比較差,畢竟原來的詞庫是簡體中文。我們接下來試試看中文歌詞的斷詞結果如何。
現在我們使用回聲樂團 - 座右銘的歌詞作為中文斷詞測試範例,歌詞我們先做成一個純文字檔lyric.txt置放到跟這個jupyter notebook相同的目錄下。
內容如下:
我沒有心
我沒有真實的自我 我只有消瘦的臉孔 所謂軟弱 所謂的順從一向是我 的座右銘
而我
沒有那海洋的寬闊 我只要熱情的撫摸 所謂空洞 所謂不安全感是我 的墓誌銘
而你
是否和我一般怯懦 是否和我一般矯作 和我一般囉唆
而你
是否和我一般退縮 是否和我一般肌迫 一般地困惑
我沒有力
我沒有滿腔的熱火 我只有滿肚的如果 所謂勇氣 所謂的認同感是我 隨便說說
而你
是否和我一般怯懦 是否和我一般矯作 是否對你來說 只是一場遊戲 雖然沒有把握
而你
是否和我一般退縮 是否和我一般肌迫 是否對你來說 只是逼不得已 雖然沒有藉口
import jieba
content = open('lyric.txt', 'rb').read()
seg_list = jieba.cut(content, cut_all=False)
print("精確模式: " + "/ ".join(seg_list)) # 精確模式
精確模式: 我/ 沒/ 有心/ / 我/ 沒/ 有/ 真實/ 的/ 自我/ / 我/ 只有/ 消瘦/ 的/ 臉孔/ / 所謂/ 軟弱/ / 所謂/ 的/ 順/ 從/ 一向/ 是/ 我/ / 的/ 座/ 右銘/ / / 而/ 我/ / 沒有/ 那/ 海洋/ 的/ 寬闊/ / 我/ 只要/ 熱情/ 的/ 撫/ 摸/ / 所謂/ 空洞/ / 所謂/ 不安全感/ 是/ 我/ / 的/ 墓誌/ 銘/ / / 而/ 你/ / 是否/ 和/ 我/ 一般/ 怯懦/ / 是否/ 和/ 我/ 一般/ 矯作/ / 和/ 我/ 一般/ 囉/ 唆/ / / 而/ 你/ / 是否/ 和/ 我/ 一般/ 退縮/ / 是否/ 和/ 我/ 一般/ 肌迫/ / 一般/ 地/ 困惑/ / / 我/ 沒/ 有力/ / 我/ 沒/ 有/ 滿腔/ 的/ 熱火/ / 我/ 只有/ 滿肚/ 的/ 如果/ / 所謂/ 勇氣/ / 所謂/ 的/ 認/ 同感/ 是/ 我/ / 隨便/ 說/ 說/ / / 而/ 你/ / 是否/ 和/ 我/ 一般/ 怯懦/ / 是否/ 和/ 我/ 一般/ 矯作/ / 是否/ 對/ 你/ 來/ 說/ / 只是/ 一場/ 遊戲/ / 雖然/ 沒/ 有把握/ / / 而/ 你/ / 是否/ 和/ 我/ 一般/ 退縮/ / 是否/ 和/ 我/ 一般/ 肌迫/ / 是否/ 對/ 你/ 來/ 說/ / 只是/ 逼不得已/ / 雖然/ 沒有/ 藉口/
我們可以從結果看出斷詞已經開始出了一些問題,比如「座右銘」被斷成了「座 / 右銘」,「墓誌銘」被斷成了「墓誌 / 銘」,這應該就是因為預設詞庫是簡體中文所造成,因此繁體中文的斷詞結果會比較差,還好 jieba 也提供了可以切換詞庫的功能,並提供了一個繁體中文詞庫,所以我們可以使用切換詞庫的功能來改善斷詞結果。
從 https://github.com/fxsjy/jieba/blob/master/extra_dict/dict.txt.big 下載繁體詞庫檔,置放到跟這個jupyter notebook相同的目錄下。
import jieba
# 指定使用繁體詞庫
jieba.set_dictionary('dict.txt.big')
content = open('lyric.txt', 'rb').read()
seg_list = jieba.cut(content, cut_all=False)
print("精確模式: " + "/ ".join(seg_list))
Building prefix dict from /Users/8703147/pythonworks/dict.txt.big ... Loading model from cache /var/folders/vt/rfsxsh1j2b51dffzl9p5v72ngb1v7q/T/jieba.u7693eb24db7dff9a9936cf7ca1f4b9b9.cache Loading model cost 1.590 seconds. Prefix dict has been built succesfully.
精確模式: 我/ 沒有/ 心/ / 我/ 沒有/ 真實/ 的/ 自我/ / 我/ 只有/ 消瘦/ 的/ 臉孔/ / 所謂/ 軟弱/ / 所謂/ 的/ 順從/ 一向/ 是/ 我/ / 的/ 座右銘/ / / 而/ 我/ / 沒有/ 那/ 海洋/ 的/ 寬闊/ / 我/ 只要/ 熱情/ 的/ 撫摸/ / 所謂/ 空洞/ / 所謂/ 不安全感/ 是/ 我/ / 的/ 墓誌銘/ / / 而/ 你/ / 是否/ 和/ 我/ 一般/ 怯懦/ / 是否/ 和/ 我/ 一般/ 矯作/ / 和/ 我/ 一般/ 囉唆/ / / 而/ 你/ / 是否/ 和/ 我/ 一般/ 退縮/ / 是否/ 和/ 我/ 一般/ 肌迫/ / 一般/ 地/ 困惑/ / / 我/ 沒有/ 力/ / 我/ 沒有/ 滿腔/ 的/ 熱火/ / 我/ 只有/ 滿肚/ 的/ 如果/ / 所謂/ 勇氣/ / 所謂/ 的/ 認同感/ 是/ 我/ / 隨便說說/ / / 而/ 你/ / 是否/ 和/ 我/ 一般/ 怯懦/ / 是否/ 和/ 我/ 一般/ 矯作/ / 是否/ 對/ 你/ 來說/ / 只是/ 一場/ 遊戲/ / 雖然/ 沒有/ 把握/ / / 而/ 你/ / 是否/ 和/ 我/ 一般/ 退縮/ / 是否/ 和/ 我/ 一般/ 肌迫/ / 是否/ 對/ 你/ 來說/ / 只是/ 逼不得已/ / 雖然/ 沒有/ 藉口/
我們在程式中多加一行 jieba.set_dictionary('dict.txt.big'),這樣就可以將斷詞詞庫切換到 dic.txt.big 這個檔案。
得到的斷詞結果會是:
我 / 沒有 / 心 / 我 / 沒有 / 真實 / 的 / 自我 / 我 / 只有 / 消瘦 / 的 / 臉孔 / 所謂 / 軟弱 / 所謂 / 的 / 順從 / 一向 / 是 / 我 / 的 / 座右銘 / 而 / 我 / 沒有 / 那 / 海洋 / 的 / 寬闊 / 我 / 只要 / 熱情 / 的 / 撫摸 / 所謂 / 空洞 / 所謂 / 不安全感 / 是 / 我 / 的 / 墓誌銘 / 而 / 你 / 是否 / 和 / 我 / 一般 / 怯懦 / 是否 / 和 / 我 / 一般 / 矯作 / 和 / 我 / 一般 / 囉唆 / 而 / 你 / 是否 / 和 / 我 / 一般 / 退縮 / 是否 / 和 / 我 / 一般 / 肌迫 / 一般 / 地 / 困惑 / 我 / 沒有 / 力 / 我 / 沒有 / 滿腔 / 的 / 熱火 / 我 / 只有 / 滿肚 / 的 / 如果 / 所謂 / 勇氣 / 所謂 / 的 / 認同感 / 是 / 我 / 隨便說說 / 而 / 你 / 是否 / 和 / 我 / 一般 / 怯懦 / 是否 / 和 / 我 / 一般 / 矯作 / 是否 / 對 / 你 / 來說 / 只是 / 一場 / 遊戲 / 雖然 / 沒有 / 把握 / 而 / 你 / 是否 / 和 / 我 / 一般 / 退縮 / 是否 / 和 / 我 / 一般 / 肌迫 / 是否 / 對 / 你
我們可以看到「座右銘」成功斷成「座右銘」了!「墓誌銘」也成功斷成「墓誌銘」了!果然切換成繁體中文詞庫還是有用的!