Last Updated on 2021-03-30 by Clay
在繁體中文的自然語言處理(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
- https://ckip.iis.sinica.edu.tw/
- https://github.com/ckiplab/ckiptagger
- https://ckip.iis.sinica.edu.tw/service/ckiptagger/
(0, 3, ‘PERSON’, ‘傅達仁’)
(18, 22, ‘DATE’, ’20年前’)
你好 請問要如何把 前面數字刪除 只要 ‘PERSON’, ‘傅達仁’ ‘DATE’, ’20年前’
以下是段範例程式碼:
item = (0, 3, ‘PERSON’, ‘傅達仁’)
new_item = item[2:]
print(new_item)
這是只取 tuple 從序列 2 開始到結束的值,所以你應該能看到 (0, 3) 這樣的位置資訊消失了。
作者您好,我是Macbook M1使用者,在按照作者指示操作後,卻一直跑出restarting kernel…的字樣,想請問該如何解。
此外,如果使用.txt檔案裝進我需要分析的文本,請問該怎麼寫下這份代碼。
有勞解答,非常感謝
(注意:tensorflow >= 1.13.1,必須要 <2。CPU 版本跟 GPU 版本都適用。)
我是直接透過終端機執行pip install tensorflow,不曉得有沒有影響
我沒遇過這個問題,但查了一下後發現網路上有對岸網友表示他是在 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()
Pingback: 自然語言處理, 斷開鎖鏈斷開魂結! » Monosparta