一、簡介
同義詞挖掘一般有三種思路,藉助已有知識庫,上下文相關性,文本相似度。
1.1 知識庫
可以藉助已有知識庫得到需要同義詞,比如說《哈工大信息檢索研究室同義詞詞林擴展版》和 HowNet,其中《詞林》文件數據如下。
Aa01A01= 人 士 人物 人士 人氏 人選
Aa01A02= 人類 生人 全人類
Aa01A03= 人手 人員 人口 人丁 口 食指
Aa01A04= 勞力 勞動力 工作者
Aa01A05= 匹夫 個人
Aa01A06= 傢伙 東西 貨色 廝 崽子 兔崽子 狗崽子 小子 雜種 畜生 混蛋 王八蛋 豎子 鼠輩 小崽子
Aa01A07= 者 手 匠 客 主 子 家 夫 翁 漢 員 分子 鬼 貨 棍 徒
Aa01A08= 每人 各人 每位
Aa01A09= 該人 此人
以上兩個知識庫是人工編輯的,畢竟數量有限,我們還可以藉助衆包知識庫百科詞條獲取同義詞,比如百度百科,如下圖所示,在百度百科搜索“鳳梨”,我們可以看到在返回頁面結果中的 info box中有一個屬性爲“別稱”,別稱中就是鳳梨的同義詞。除此之外,在百科詞條的開頭描述中,有如下描述“又稱”、“俗稱”也是同義詞,我們可以利用爬蟲把這些詞爬下來。
百度搜索和谷歌搜索等搜索工具一般都有重定向頁,這也可以幫助我們去挖掘同義詞。
使用知識庫挖掘同義詞的優點是簡單易得,而且準確率也高,缺點就是知識庫覆蓋率有限,不是每個細分領域都有。對於金融、醫療、娛樂等領域都需要各自的知識庫。
1.2 上下文相關性
利用上下文相關性挖掘同義詞也比較好理解,如果兩個詞的上下文越相似的話,那麼這兩個詞是同義詞的概率就越大。使用詞向量挖掘同義詞是比較常見的做法,比如使用word2vector訓練得到詞向量,然後再計算餘弦相似度,取最相似的top k個詞,就得到了同義詞。
word2vector是無監督學習,而且本質上來說它是一個語言模型,詞向量只是它的副產品,並不是直接用來挖掘同義詞。有篇paper發明了弱監督的同義詞挖掘模型DPE,也取得了不錯的效果。DPE模型流程如下圖,一共分爲兩個階段,第一階段跟word2vector差不多,也是訓練詞向量,只不過DPE是一種graph embedding的思路,首先從語料中構建語義共現網絡,然後通過對網絡的邊採樣訓練詞向量。第二階段通過弱監督訓練一個打分函數,對輸入的一對詞判斷屬於同義詞的概率。感興趣的可以看看這篇paper 論文鏈接
基於上下文相關性的同義詞挖掘方法的優點是能夠在語料中挖掘大量的同義詞,缺點是訓練時間長,而且挖掘的同義詞很多都不是真正意義上的同義詞需要人工篩選。這種方法對於詞頻較高的詞效果較好。
1.3 文本相似度
對於這一對同義詞“阿里巴巴網絡技術有限公司”和“阿里巴巴網絡公司”直接去計算上下文相似度可能不太有效,那一種直觀的方法是直接計算這兩個詞的文本相似度,比如使用編輯距離(Levenshtein distance)或者 LCS(longest common subsequence),如果兩個詞的文本相似度大於閾值的話我們就認爲他們是同義詞的關係。在這裏推薦一個計算文本相似度的Java開源項目,基本上文本相似度算法應有盡有。[ 文本相似度算法 ]
基於文本相似度同義詞挖掘方法的優點是計算簡單,不同於word2vector,這種方法不需要使用很大的語料,只要這個詞出現過一次就可以發現同義詞關係。這種方法的缺點是有時候不太靠譜,會挖掘出很多錯誤的同義詞,尤其是當兩個詞比較短的情況下,比如“周杰倫”和“周杰”,就可能會被認爲是同義詞。所以這種方法適用於一些較長的文本,特別是專業詞彙,術語。
二、同義詞挖掘的算法實現
github地址:https://github.com/tigerchen52/synonym_detection
在這個github項目中實現了4種同義詞挖掘的方法:
- 百度百科同義詞
- word2vector
- 語義共現網絡的節點相似度
- Levenshtein距離
覺的有用同學記得點star~~
2.1 百度百科同義詞
代碼示例(synonym_detection/source/main.py)
def baike_invoke():
import baike_crawler_model
print(baike_crawler_model.baike_search(('鳳梨', '001')))
if __name__ == '__main__':
baike_invoke()
輸出
['菠蘿皮', '地菠蘿', '菠蘿', '草菠蘿']
2.2 word2vector
在這裏使用《三體》小說作爲訓練語料,使用以下10個詞作爲輸入,從語料中挖掘這10個詞的同義詞。後面幾個方法使用相同的輸入。
1|海王星
2|女孩
3|椅子
4|海軍
5|陣列
6|變化
7|程心
8|火焰
9|天空
10|建造
代碼示例
python synonym_detect -corpus_path ../input/三體.txt -input_word_path ../temp/input_word.txt -process_number 2 if_use_w2v_model True
參數
- -corpus_path 爲語料文件,使用三體小說作爲訓練語料
- -input_word_path 輸入詞表,對詞表中的詞進行同義詞挖掘。文件中每行以“|”作爲分隔符,第一列是id,第二列是輸入詞
- -process_number 2 進程數量
- -if_use_w2v_model True 使用word2vector模型
- 默認返回top 5個同義詞
輸出
1 海王星 海王星|土星|天王星|背面|金星
3 椅子 椅子|辦公桌|地板|地毯|鐵鍬
2 女孩 女孩|中年人|女孩兒|女子|淚光
9 天空 天空|晨光|夜空|暮色|漆黑
4 海軍 海軍|軍種|服役|事務性|政工
6 變化 變化|隱隱約約|異常|微妙|所致
5 陣列 陣列|矩形|一千公里|環|標示出
7 程心 程心|AA|艾|當程心|曹彬
8 火焰 火焰|暗紅|山脈|灼熱|變幻
10 建造 建造|天梯|最小|準|航空母艦
2.2 語義共現網絡的節點相似度
語義共現網絡本質是根據上下文構建的圖,圖中的節點是詞,邊是這個詞的上下文相關詞。對於語義共現網絡的兩個節點,如果這兩個節點的共同鄰居節點越多,說明這兩個詞的上下文越相似,是同義詞的概率越大。例如,對於《三體》小說中的兩個詞“海王星”和“天王星”,在《三體》語義共現網絡中,“海王星”和“天王星”的鄰居節點相似度很高,則說明兩個詞是同義詞的可能性很高。如下圖所示:
代碼示例
python synonym_detect -corpus_path ../input/三體.txt -input_word_path ../temp/input_word.txt -process_number 2 -if_use_sn_model True
輸出
5 陣列 陣列|矩形|隊列|星體|量子
9 天空 天空|中|夜空|太陽|消失
4 海軍 海軍|航空兵|服役|空軍|失敗主義
10 建造 建造|製造|加速器|飛船|太陽系
3 椅子 椅子|桌子|坐下|沙發|檯球桌
1 海王星 海王星|天王星|土星|衛星|羣落
7 程心 程心|AA|中|羅輯|說
8 火焰 火焰|光芒|光點|推進器|雪峯
2 女孩 女孩|接待|衝何|請雲|女士
6 變化 變化|發生|意味着|恢復|中
可以看出基於語義共現網絡得到的同義詞與word2vector結果類似,甚至在某些詞上效果更好。
2.4 Levenshtein距離
代碼示例
python synonym_detect -corpus_path ../input/三體.txt -input_word_path ../temp/input_word.txt -process_number 2 -if_use_leven_model True
輸出
1 海王星 海王星|冥王星|天王星|星|王
7 程心 程心|請程心|帶程心|連程心|從程心
6 變化 變化|變化很大|動態變化|發生變化|化
3 椅子 椅子|子|筐子|村子|棒子
2 女孩 女孩|女孩兒|女孩子|小女孩|女
10 建造 建造|建造成|造|建|建到
5 陣列 陣列|列|陣|歷列|列爲
9 天空 天空|海闊天空|空|天|天馬行空
8 火焰 火焰|火|焰|火星|野火
4 海軍 海軍|於海軍|陸海空軍|海|海軍軍官
2.5 DPE模型
undo