用 JS 做語意分析是不是搞錯了什麼(一):斷詞篇
身為一個 JavaScript 愛好者,實在是不太喜歡大家都在 Python 上做 Machine Learning;恰好近期 Tensorflow 也開始支援 JS,想必會興起一股熱潮吧?
使用 jieba 斷詞
之前在 開發 Chatbot 前的那兩三事(三):中文語意分析、使用分析平臺 有稍微提到語意分析的方式,這篇將會介紹如何用 jieba
(結巴) 套件來斷詞。
我們會使用 npm 上的 nodejieba
套件,雖然這個套件一段時間了,而且還不支援 Promise
等較新的寫法,但仍然是 js 社群中最強的斷詞套件沒有之一。
使用 JS 做語意分析是不是搞錯了什麼
噢不,別再提 Python 了,你知道 JS 跑 jieba
比 Python 快很多嗎?根據 "结巴"(Jieba)中文分词系列性能评测,筆者做了 C++、Go 語言、JS 和 Python 的分析,我不像筆者那麼厲害精通各個語言,所以大家只要知道這個過程中 JS 花了 10 秒、Python 花了快 90 秒(大概是 JS 的九倍),所以 JS 比較厲害就可以了。
事前準備
這篇是後端,用 node.js 開發的文章,你可能需要準備 node.js 環境。如果你不知道要下載哪個版本,就抓 LTS 的版本吧。
安裝 jieba
首先安裝 jieba
套件:
npm install nodejieba
接著在 js 檔案裡引入 jieba
套件:
const nodejieba = require('nodejieba');
這樣就完成了 jieba
的初始化。
由於結巴一開始是為了簡體中文而開發的,故內建的詞庫可能切簡體中文會比較優秀一點。建議可以去找繁體中文詞庫,並用
nodejieba.load()
函式去載入字典檔。
例如將 ldkrsi/jieba-zh_TW 中的 dict.txt 抓下來後,
再透過nodejieba.load({dict: './dict.txt'});
來載入字典。
使用 jieba 斷詞
nodejieba 內建 4 種斷詞模式:
cut
精確模式:試圖將句子最精確地分開,適合文本分析(Contextual Analysis)。cutHMM
精確模式並套用 HMM:使用隱藏式馬可夫鍊(HMM)模型,試圖找出不在字典檔裡面的字。cutAll
全模式:把句子中可以成詞的詞語都掃瞄出來,速度非常快但不能解決歧義。cutForSearch
搜尋引擎模式:在精確模式的基礎下,對長詞再次切分,提高召回率(recall)。
一般的句子都可以用精確模式切開來,例如:
nodejieba.cut('我們不禁哄堂大笑,同樣的一件衣料,每個人卻有不同的感覺。')
會得到:
['我們', '不禁', '哄堂大笑', ',', '同樣', '的', '一', '件', '衣料', ',', '每', '個', '人', '卻', '有', '不同', '的', '感覺', '。' ]
如果要切跟人名有關的東西可以考慮用 cutHMM
,例如這句話「自此以後,又長久沒有看見孔乙己。」用精確模式切出來會是:
[ '自此', '以後', ',', '又', '長久', '沒有', '看見', '孔乙', '己', '。' ]
但用 cutHMM
就能切出:
[ '自此', '以', '後', ',', '又', '長', '久', '沒', '有', '看見', '孔乙己', '。' ]
用 jieba 找出關鍵詞和詞性
jieba
也能透過 tf-idf 的方法找出一段文章中的關鍵詞,例如:
const sentence = '我與父親不相見已有二年餘了,我最不能忘記的是他的背影。那年冬天,祖母死了,父親的差使也交卸了,正是禍不單行的日子,我從北京到徐州,打算跟父親奔喪回家。';
const topN = 5; /* 找出前五個關鍵詞 */
nodejieba.extract(sentence, topN);
會得到:
[ { word: '父親', weight: 35.21761292125063 },
{ word: '交卸', weight: 11.9547675029 },
{ word: '相見', weight: 11.739204307083542 },
{ word: '奔喪', weight: 11.739204307083542 },
{ word: '忘記', weight: 11.739204307083542 } ]
若是要找出詞性的話,也可以把整個句子丟進去,會自動斷詞並標記詞性:
nodejieba.tag('你總要踏上你老子的腳步。');
會得到:
[{ word: '你', tag: 'N' },
{ word: '總要', tag: 'x' },
{ word: '踏上', tag: 'Vt' },
{ word: '你', tag: 'N' },
{ word: '老子', tag: 'N' },
{ word: '的', tag: 'T' },
{ word: '腳步', tag: 'N' },
{ word: '。', tag: 'x' } ]
至於詞性標記是什麼,可以參考這篇 词性标记。
結語
斷詞以後就能拿來做很多應用了,例如斷詞後拿來做文字雲、轉向量做相似度分析等等,有趣的應用未來可以再介紹。
至於 jieba
是不是能夠切得精準?我認為大部分情況還算堪用,如果是比較專業的術語或是不常見的詞,可以考慮加入自訂字典檔,並透過 nodejieba.load({userDict: './xxx.txt'})
來載入。
參考資料
用 JS 做語意分析是不是搞錯了什麼 目錄
- 用 JS 做語意分析是不是搞錯了什麼(一):斷詞篇
- 待續......
其實我還沒想到要寫什麼,歡迎許願 (?