# 同义词工具

## 引入

同义词工具在NLP一般在数据预处理, 或者**数据增强**时使用, 词用同义词代替, 可以增加可用于训练的语料, 也能增强模型的鲁棒性.

目前我找到的可用来做同义词替换的方法工具有以下几个.

## 同义词词林

哈工大的同义词词林(扩展版)是一个同义词词典, 以`.txt`文件的形式记录. 文件中数据的格式如下:

```
Aa01A01= 人 士 人物 人士 人氏 人选
Aa01A02= 人类 生人 全人类
Aa01A03= 人手 人员 人口 人丁 口 食指
Aa01A04= 劳力 劳动力 工作者
Aa01A05= 匹夫 个人
Aa01A06= 家伙 东西 货色 厮 崽子 兔崽子 狗崽子 小子 杂种 畜生 混蛋 王八蛋 竖子 鼠辈 小崽子
Aa01A07= 者 手 匠 客 主 子 家 夫 翁 汉 员 分子 鬼 货 棍 徒
Aa01A08= 每人 各人 每位
Aa01A09= 该人 此人
Aa01B01= 人民 民 国民 公民 平民 黎民 庶 庶民 老百姓 苍生 生灵 生人 布衣 白丁 赤子 氓 群氓 黔首 黎民百姓 庶人 百姓 全民 全员 萌
```

每行代表一组同义词, 两两之间做同义词, 可以相互替换. 但除了同义词, 还包含在句子中作用近似, 但直观来看词义不同的词:

```
Ad02B03# 西人 意大利人 缅甸人 西方人 阿拉伯人 日本人 美国人 犹太人 捷克人 芬兰人 德国人 比利时人 ...
Ae02A21# 机工 铣工 刨工 锻工 铸工 钳工 电工 焊工 装配工 保全工 电焊工 ...
```

上面一组其实都是代表外国人的词汇, 只是国家的区别, 在句子中都扮演着同样的角色, 在很多情况下都是可以作为`同义词`替换的(除了一些推导或信息抽取的任务吧).

可以看到每行的开始都有一串编码, 编码的意义参考[同义替换：哈工大同义词词林扩展版](https://blog.csdn.net/sinat_33741547/article/details/80016713). 这里关注编码的最后一个字符. 观察上面两大组可以看到他们的编码结尾分别是`=`和`#`, 这分别代表着`相等`和`同类`的意思, 在整理同义词典时, 选择使用. 编码的详情意义参考上面的链接.

整个文件共包含17817组同义词汇, 每组包含的词的数量不同, 也会出现同一个词汇被包含在不同组中, 显然是一词多义的原因. 在使用处理时, 需要注意这一点.

如何使用, 这里有使用的例子, 其中包含代码, 可以参考:

* [NLP数据预处理——同义词替换程序](https://blog.csdn.net/hfutdog/article/details/81107170)
* \[]

其中使用到了哈工大的`pyplt`, 是一款提供了分词, 词性标注, NER等功能的工具, 官方文档为: [使用 pyltp](https://pyltp.readthedocs.io/zh_CN/latest/api.html)

## Synonyms

**Synonyms**是一个专门做**中文近义词**的Python工具包. 与词林使用字典记录固定的近似词不同, Synonyms在得到某个词的相似时, 是通过word2vec中的词向量计算得到的, 利用了上下文中词之间的关系, 根据词向量的距离得到的.

这种方法有以下缺点:

* 得到的词有可能不是词义相近的严格意义的近义词, 而是经常以成对出现在上下文窗口中的单词, 统计上有着密切的关系. 例如:

  ```python
    synonyms.nearby("人脸")
  ```

  得到的结果为:

  ```
    (['人脸', '图片', '通过观察', '几何图形', '图象', '放大镜', '面孔', '貌似', '奇特', '十分相似'],
    [1.0,
    0.5972838,
    0.56848586,
    0.5318347,
    0.52534395,
    0.52400935,
    0.52310055,
    0.50064117,
    0.4851142,
    0.39761642])
  ```

  可以看到这里得到的词汇都不是近义词, 而是经常在同一个上下文窗口中成对出现的组合.

所幸, 由于synonyms计算近义词是通过词向量的距离得到的, 而且求近义词的方法`nearby`也返回了结果中每个单词的相似度衡量. 我们可以简单地通过阈值, 做进一步的筛选. 例如上式中最大的近义词`图片`对应的相似度为`0.597`, 可以认为太低, 从而人脸没有近义词.

```python
synonyms.nearby("问题")
```

```
(['问题', '难题', '原因', '疑虑', '情况', '缺陷', '疑问', '关键问题', '解决办法', '弊端'],
 [1.0,
  0.74893767,
  0.688038,
  0.6788217,
  0.6591137,
  0.65887266,
  0.6470331,
  0.63049304,
  0.62929237,
  0.62681234])
```

`问题`的近义词列表返回的结果, 相似度就高出不少.

总之, 在使用时, 如果想要比较高质量的近义词, 阈值设置高一点. 低阈值会引入更多的近义词词汇, 用来做数据增强时, 可能会提高模型的鲁棒性, 但也可能引入过多的噪声, 造成模型无法收敛或质量较差.

总结就是, `synonyms`包使用`synonyms.nearby(WORD)`方法获取近义词, 返回的是一个二元list, 形式为`[[nearby_words], [nearby_words_score]]`, 每个list的长度都为10. `nearby_words`是近义词列表, `nearby_words_score`是对应的每个近义词的相似度, 越高越好.

因为是使用word2vec, 所以本身是有一个字典的, 输入只能是字典中的单词, 才能转换为词向量, 进而才能得到与其他单词的距离, 产生近义词列表. 如果输入的单词是**OOV**, 则没有近义词列表, 返回`([], [])`.

项目地址为: [huyingxi/Synonyms](https://github.com/huyingxi/Synonyms).

**另外需要注意的是**, 由于使用的是word2vec, 所以一些开源的训练好的word2vec文件也是可以使用的. 更换模型的方法参考项目主页. 推荐使用[腾讯AI Lab的word2vec embedding](https://ai.tencent.com/ailab/nlp/embedding.html).

详细的使用方法参考项目的主页说明, 也可以参考[Synonyms: 中文近义词工具包](http://www.52nlp.cn/synonyms-%E4%B8%AD%E6%96%87%E8%BF%91%E4%B9%89%E8%AF%8D%E5%B7%A5%E5%85%B7%E5%8C%85).


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://blessbingo.gitbook.io/garnet/zi-ran-yu-yan-chu-li/gong-ju-shi-yong/tong-yi-ci-gong-ju.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
