一、简介
同义词挖掘一般有三种思路,借助已有知识库,上下文相关性,文本相似度。
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