Skip to content

[NLP][Python] 透過 ckiptagger 來使用繁體中文斷詞的最佳工具 CKIP

在繁體中文的自然語言處理(NLP)當中,CKIP 無疑是斷詞最精準、最負盛名的工具。這項工具是由台灣中研院資訊所、語言所於民國 75 年成立的中文語言言小組所開發,也在多個中文斷詞的比賽當中得過獎項。

之前由於 CKIP 一直沒有開源,導致需要前往官方的 Demo 網站試用( https://ckip.iis.sinica.edu.tw/demo/ ),或者是寄信取得授權,可以使用下載版的 CKIP 一個月,看是要直接使用 bat 檔,或是使用 Python 另外調用。

所幸,在前不久(2019/09/04),CKIP 終於開放了原始碼,程式也已經放上了 Github: https://github.com/ckiplab/ckiptagger

今天,我就來簡單介紹一下該如何使用這套開源的工具吧。


前置作業

要使用 CKIP (CkipTagger) ,這套工具,首先你需要有至少為 3.6 版的 Python,以及 tensorflow、gdown 等等套件。

(注意:tensorflow >= 1.13.1,必須要 <2。CPU 版本跟 GPU 版本都適用。)

我們可能需要安裝這些套件:

pip3 install ckiptagger
pip3 install tensorflow
pip3 install gdown

其中,gdown 是一個我們平常比較少用的套件,其功能為從 google drive 上載下模型。

都裝好之後,我們開啟一個 Python 檔,在裡面寫下:

# -*- coding: utf-8 -*-
from ckiptagger import data_utils
data_utils.download_data_gdown("./")


這會自動開始下載模型 data.zip 到我們當前目錄底下。
下載好之後,我們就可以把這些指令刪掉了。

以下開始介紹該怎麼使用斷詞、詞性標記(POS)、命名實體識別(NER)。


斷詞、POS、NER

請原諒我這三種不同的 NLP 任務一起講,因為程式實在很短,加上 CKIP 的 NER 需要 POS 產生的結果。這點倒是跟處理英文語料的 NLTK 很像。

# -*- coding: utf-8 -*-
from ckiptagger import WS, POS, NER

text = '傅達仁今將執行安樂死,卻突然爆出自己20年前遭緯來體育台封殺,他不懂自己哪裡得罪到電視台。'
ws = WS("./data")
pos = POS("./data")
ner = NER("./data")

ws_results = ws([text])
pos_results = pos(ws_results)
ner_results = ner(ws_results, pos_results)

print(ws_results)
print(pos_results)
for name in ner_results[0]:
    print(name)


Output:

[['傅達仁', '今', '將', '執行', '安樂死', ',', '卻', '突然', '爆出', '自己', '20', '年', '前', '遭', '緯來', '體育台', '封殺', ',', '他', '不', '懂', '自己', '哪裡', '得罪到', '電視台', '。']]
[['Nb', 'VJ', 'Na', 'Nd', 'D', 'VC', 'VA', 'D', 'VH', 'VH', 'COMMACATEGORY', 'D', 'D', 'VH', 'VH', 'VC', 'P', 'Nh', 'Neu', 'Neu', 'Nf', 'Ng', 'P', 'Na', 'VA', 'Na', 'VC', 'Nc', 'VC', 'VC', 'COMMACATEGORY', 'Nh', 'D', 'VK', 'P', 'Nh', 'Nep', 'Ncd', 'VJ', 'Na', 'P', 'Na', 'P', 'Nc', 'PERIODCATEGORY']]
(0, 3, 'PERSON', '傅達仁')
(18, 22, 'DATE', '20年前')

首先我們需要在程式中匯入 WS、POS、NER,這分別是斷詞、詞性標記、命名實體識別的三個工具。

我進行的句子為 Github 所給的範例。我本來想要用自己找的新聞,可惜發現其 NER 的效果並不好,故還是用回了 Github 給的範例。

緊接著,我們將三份工具的模型路徑指向我們剛才下載的 data.zip:

ws = WS("./data")
pos = POS("./data")
ner = NER("./data")


然後我們就可以使用這三種工具分析我們的文本了。

ws_results = ws([text])
pos_results = pos(ws_results)
ner_results = ner(ws_results, pos_results)


切記!ner() 需要接受兩個參數,一個是我們的文本斷詞結果,另一個是 POS 的結果。

我們可以看到以下輸出的結果:

[['傅達仁', '今', '將', '執行', '安樂死', ',', '卻', '突然', '爆出', '自己', '20', '年', '前', '遭', '緯來', '體育台', '封殺', ',', '他', '不', '懂', '自己', '哪裡', '得罪到', '電視台', '。']]
[['Nb', 'VJ', 'Na', 'Nd', 'D', 'VC', 'VA', 'D', 'VH', 'VH', 'COMMACATEGORY', 'D', 'D', 'VH', 'VH', 'VC', 'P', 'Nh', 'Neu', 'Neu', 'Nf', 'Ng', 'P', 'Na', 'VA', 'Na', 'VC', 'Nc', 'VC', 'VC', 'COMMACATEGORY', 'Nh', 'D', 'VK', 'P', 'Nh', 'Nep', 'Ncd', 'VJ', 'Na', 'P', 'Na', 'P', 'Nc', 'PERIODCATEGORY']]
(0, 3, 'PERSON', '傅達仁')
(18, 22, 'DATE', '20年前')

第一列為斷詞的結果。
第二列為 POS 的詞性。詞性表也許可以參考中研院自己的整理: http://ckipsvr.iis.sinica.edu.tw/cat.htm

第三列為 NER 的結果,我們可以看到分別抓出了『傅達仁』這個『人物』,以及『20年前』這個『時間』。

大家也可以盡量去使用 CKIP,享受最精準的斷詞結果!


感想

我很高興看到 CKIP 開源了,目前正在計畫有空的時候好好閱讀它的原始碼。但說真的,我目前只有使用 tensorflow 的 CPU 版本,不得不說這玩意兒還挺慢的,或許我該找一天測試看看 GPU 版本是不是比較好用、比較快。(通常都是。)

另外,另要挑毛病的話就是 NER 挑出的名詞其實我是有點錯愕的。常常會只有人物的姓氏被挑出來,而名字沒有。我猜想也許我該研究一下能不能加詞典,增進它斷詞的結果。畢竟 NER 看起來效果不夠好多半是因為斷詞沒有把人物名字完全斷對。

另外,聽說 Linux 系統上可以試用 ckipnlp 這個工具,裡面甚至有包含句法結構的 parser 功能,也許我也該找一天來好好測試。

期待 CKIP 變得更好!


References


Read More

Tags:

6 thoughts on “[NLP][Python] 透過 ckiptagger 來使用繁體中文斷詞的最佳工具 CKIP”

  1. (0, 3, ‘PERSON’, ‘傅達仁’)
    (18, 22, ‘DATE’, ’20年前’)
    你好 請問要如何把 前面數字刪除 只要 ‘PERSON’, ‘傅達仁’ ‘DATE’, ’20年前’

    1. 以下是段範例程式碼:

      item = (0, 3, ‘PERSON’, ‘傅達仁’)
      new_item = item[2:]
      print(new_item)

      這是只取 tuple 從序列 2 開始到結束的值,所以你應該能看到 (0, 3) 這樣的位置資訊消失了。

  2. 作者您好,我是Macbook M1使用者,在按照作者指示操作後,卻一直跑出restarting kernel…的字樣,想請問該如何解。
    此外,如果使用.txt檔案裝進我需要分析的文本,請問該怎麼寫下這份代碼。
    有勞解答,非常感謝

    1. (注意:tensorflow >= 1.13.1,必須要 <2。CPU 版本跟 GPU 版本都適用。)

      我是直接透過終端機執行pip install tensorflow,不曉得有沒有影響

    2. 我沒遇過這個問題,但查了一下後發現網路上有對岸網友表示他是在 Jupyter Notebook 上跑程式時遇到這個問題,調整了 tensorflow 版本後才能正常運作。
      可以使用 pip list 來確認當前安裝的套件版本,安裝時也可以指定版本安裝。
      假設你希望安裝 1.13.1 版,可以使用 pip install tensorflow==1.13.1 這樣的指令來安裝。

      至於該如何裝進分析的文本到 .txt 檔…… 這個,由於我不清楚你打算如何處理斷句,所以也只能大概說明一下。
      基本上就是將你想要分析的文本放在 txt 檔,假設叫做 data.txt。
      然後將我程式碼中的:

      text = '傅達仁今將執行安樂死,卻突然爆出自己20年前遭緯來體育台封殺,他不懂自己哪裡得罪到電視台。'

      更改為:

      text = open("data.txt", "r", encoding="utf-8").read()

  3. Pingback: 自然語言處理, 斷開鎖鏈斷開魂結! » Monosparta

Leave a Reply