如今大部分的分詞工具已經作到了準確率高、粒度細,可是對於一些新詞(new word)卻不能作到很好地識別,好比:python
快的打車優惠券
英雄聯盟怎麼不能夠打排位git
「快的」、「英雄聯盟」應該被做爲一個詞,卻被切成了兩個詞,失去了原有的語義。未登陸詞(out-of-vocabulary, OOV)籠統地之未在詞典中出現的詞,序列標註方法HMM與CRF能夠根據上下文很好地識別未登陸詞,可是這種模型缺少領域自適應能力 [1]:github
模型對訓練語料所在領域的語言現象處理可能表現出較好的性能,但一旦超出領域範圍或測試集與訓練樣本有較大差別,模型性能將大幅度降低。例如,在標註的大規模《人民日報》分詞語料上訓練出來的漢語詞語自動切分模型的準確率可達96%左右,甚至更高,但在微博等非規範文本基礎上訓練出的分詞性能至少要低5個百分點左右。在LDC漢語樹庫上訓練出來的句法分析系統準確率可達86%左右,但在非規範網絡文本上的分析準確率只有60%左右(宗成慶 2013)。統計模型對領域自適應能力的缺少嚴重製約了該方法的應用。算法
所以,對於「快的」、「英雄聯盟」這樣最近纔出來的詞未能識別。咱們定義新詞爲具備基本詞彙所沒有的新形式、新語義的詞語。新詞能夠視做一種特殊的未登陸詞;從分詞的角度來看,新詞通常表現爲細粒度切分後相鄰詞的組合。網絡
Matrix67提出了一種基於信息熵的新詞發現算法[2],成詞的標準有兩個:app
所謂內部凝固度,用來衡量詞搭配(collocation)是否合理。好比,對於「的電影」、「電影院」這兩個搭配,直觀上講「電影院」更爲合理,即「電影」和「院」凝固得更緊一些。在計算語言學中,PMI (Pointwise mutual information)被用來度量詞搭配與關聯性,定義以下:工具
\[ pmi(x,y) = \log \frac{P(x,y)}{P(x)P(y)} \]性能
若PMI高,即兩個詞共現(co-occurrence)的頻率遠大於兩個詞自由拼接的乘積機率,則說明這兩個詞搭配更爲合理一些。針對一個詞有多種搭配組合,好比「電影院」能夠由「電影」+「院」構成,也能夠由「電」+「影院」構成,Matrix67取其全部pmi最小值(去掉log)做爲內部凝固度:測試
\[ solid(c_1^m) = \min \frac{P(c_1^m)}{\prod P(c_i^j)} = \frac{P(c_1^m)}{\max \prod P(c_i^j)} \]ui
其中,\(c_1^m=c_1c_2\cdots c_m\)表示長度爲\(m\)的字符串,\(P(c_1^m)\)表示詞\(c_1^m\)的頻率。
光看文本片斷內部的凝合程度還不夠,咱們還須要從總體來看它在外部的表現。考慮「被子」和「輩子」這兩個片斷。咱們能夠說「買被子」、「蓋被子」、「進被子」、「好被子」、「這被子」等,在「被子」前面加各類字;但「輩子」的用法卻很是固定,除了「一生」、「這輩子」、「上輩子」、「下輩子」,基本上「輩子」前面不能加別的字了。「輩子」這個文本片斷左邊能夠出現的字太有限,以致於直覺上咱們可能會認爲,「輩子」並不單獨成詞,真正成詞的實際上是「一生」、「這輩子」之類的總體。
因此,Matrix67提出了自由運用程度,用以衡量一個詞的左鄰字與右鄰字的豐富程度。正好信息熵能夠完美地詮釋了這種豐富程度,熵越大則豐富程度越高。「被子」和「輩子」這兩個片斷的左鄰字熵le
與右鄰字熵re
分別以下:
le(被子) = 3.67453 re(被子) = 3.8740 le(輩子) = 1.25963 re(輩子) = 4.11644
能夠看出,「被子」的左鄰字熵與右鄰字熵都較高,而「輩子」的左鄰字熵較小,即左鄰字很是貧乏。所以,「被子」較「輩子」更有可能成詞。自由運用程度的定義以下:
\[ free(c_1^m) = \min \{ le(c_1^m), \ re(c_1^m) \} \]
給頻數、內部凝固度與自由運用程度設定一個閾值,提取出來符合閾值的候選詞,去掉詞典中存在的詞即爲新詞了。知乎在作反做弊挖掘新詞時,也是採用的這個方法,聽說取得了比較好的效果;具體細節參看專欄文章《反做弊基於左右信息熵和互信息的新詞挖掘》。該新詞發現算法已經有Java版實現dict_build,還有Python版實現ChineseWordSegmentation。
爲了評估該算法的效果,我採用的策略以下:首先用dict_build對語料進行統計分析獲得一批候選詞,而後使用Jieba對語料進行分詞獲得詞表,最從候選詞中篩出不在分詞詞表的做爲新詞,並按dict_build的成詞機率進行排序。
import codecs import jieba seg_words = set() candidate_words = [] with codecs.open(data_path, 'rb', 'utf-8') as fr: for line in fr.readlines(): strs = line.strip().split('\t') if len(strs) == 5: candidate_words.append([strs[0], float(strs[4])]) candidate_words.sort(key=lambda t: t[1], reverse=True) with codecs.open(file_path, 'rb', 'utf-8') as fr: for content in fr.readlines(): words = jieba.cut(content.strip()) for word in words: seg_words.add(''.join(word)) for wf in candidate_words: if wf[0] not in seg_words: print(wf)
《西遊記》的Top 32新詞以下:
睜睛 我徒弟 我師弟 老爺們 金光寺 金頭揭諦 金聖娘娘 攙着
扯着 拖着 敲着 揪着 躧着 我師父 老師父 坐着
又遇 又吩咐 那袈裟 捧着 又到 打到 抱着 請師父
八戒沙僧 請唐僧 擡頭見 又來 我佛如來 跳起來 走未來 請如來
採用京東商品標題的語料,Top 36新詞以下:
粗跟短靴 粗跟女靴 粗跟過膝靴 歐式客廳 歐式餐廳 歐式臥室 歐美女靴 踩腳褲
踩腳打底褲 阿羅褲 踩腳保暖褲 踩腳一體褲 韓版休閒褲 韓版小腳褲 唐裝男褲 歐式田園
韓式田園 戚風蛋糕 韓版鬆糕 剃鬚刀片 雙層玻璃杯 雙貔貅 雙層水杯 陸戰靴
抽紙盒 抽象客廳 錢貔貅 遮光臥室 遮光客廳 遮肚罩衫 白酒杯 白雪公主裙
紫砂杯 紫砂茶杯 紫砂品茗杯 紫砂杯茶杯
觀察分析兩組發掘的新詞,總結以下:
整體上來看,基於統計的新詞發現算法是很強的baseline,具備普適性——對於不一樣領域的語料,可以發掘出咱們想要的新詞;可是同時也帶來不少髒詞。
[1] 宗成慶, 《語言戰略研究》∣ 宗成慶:中文信息處理研究現狀分析.
[2] Matrix67, 互聯網時代的社會語言學:基於SNS的文本數據挖掘.