文章目录
安装
1 | pip install jionlp |
该如何使用呢?可以参考 Github 以下项目
https://github.com/dongrixinyu/JioNLPgithub.com/dongrixinyu/JioNLP
操作说明
其中包含了回译、邻近汉字换位、同音词替换、随机增删字符等方法。具体使用样例如下:
1 | >>> import jionlp as jio |
数据增强方法对比
- 文本数据增强的两个前提:
- 1、不干扰模型标签:文本增强后的语义不干扰模型训练,不会导致样本标签失效;如 “这个小吃真好吃。=> 正面情绪” 增强为 “这个小吃真不好吃。=> 正面情绪”,随机加字影响到了标签的正确性。
- 2、人可理解:增强后文本,依然保持可读性,达到人可以理解文本的含义;如 “这个小吃真好吃。” 增强为 “斯口吃真好吃。”,其中 “这个” 替换为 “斯”,“小吃” 替换为 “口吃”,已经完全令人无法理解,模型训练也已偏离。此问题在 同义词替换上非常频繁与普遍。
| 方法 | 任务类型 | 效果 |
|---|---|---|
| 回译 | 文本分类、序列标注、匹配、文本生成 | 基于机翻效果决定,目前对新闻通用领域效果较好,专项领域视语料决定。长短文本均适合 |
| 邻近汉字换位 | 文本分类、匹配 | 汉字换位会影响具体实体的含义,在实体含义并不影响整体语义情况下适用。换位汉字占比不宜过大 |
| 同音词替换 | 文本分类、匹配 | 同音词替换会对局部语义产生影响,造成误差,但对整体语义理解并无干扰。替换词汇的占比不宜过大 |
| 随机增删符号 | 文本分类、匹配 | 在文本中随机增删不影响语义的额外非中文符号。增加比例不宜过大,若某类字符(数字、字母)对语义有影响,则应该规避此类字符 |
| NER 实体替换 | 文本分类、匹配、序列标注 | 在文本中随机替换不影响语义的实体。如人名、地名、机构等实体 |
| 同义词替换 | - | 造成语言连贯性差,语义完全被曲解的概率非常大。此种方法作废,本工具包不支持。具体解释见 jio.random_add_delete.__doc__ |
| 语言模型预测 | 分类、匹配、文本生成 | 利用大型的语言模型如 bert 等,预测句子中空缺的词汇。此种方法依赖大型的语言模型参数,本工具暂不支持 |
回译数据增强
1 BackTranslation
2 BaiduApi
3 XunfeiApi
4 GoogleApi
5 TecentApi
6 YoudaoApi
7 YoudaoFreeApi
给定一段文本,利用各类大厂公开的免费 api,对文本数据做增强。用户可在各大厂的云平台上自行申请密钥,填在接口的参数中。 各厂申请 API 地址如下:
- 百度 BaiduApi
- 有道 YoudaoApi
- 腾讯 TecentApi
- 讯飞 XunfeiApi
- 请注意:样例中的 api 参数并非全都可用,请注册账号在各个厂官网申请自己的 api 参数
1 | >>> import jionlp as jio |
-
原理简述:利用公开的大厂 API 对文本数据做回译增强,即完成从 中文 -> 外文 -> 中文 的翻译过程。
-
该框架考虑了对各 API 的语言种类支持问题;两次调用之间的等待时间问题;等待超时问题;支持在 API 接口中输入多个密钥(appkey_obj)。
-
每一个 API 类提供了初始化
lang_pool参数,用于指定翻译的语种。基于此种考虑:某些小语种的模型效果并不如英语理想,如上例 “饿了么” 句子的翻译,小语种的翻译质量不如英汉互译。 -
该接口框架包括了常用的若干 API(BaiduApi、XunfeiApi、GoogleApi、TecentApi、YoudaoApi、YoudaoFreeApi),也支持
自定义训练的模型 API 接口
。具体见下。
- 自定义 API 接口接收一个 str 格式文本输入,输出对应的 str 格式翻译文本;
- 自定义 API 须指定文本的源语言和目标翻译语言,如 (zh, en) 和 (en, zh);
- 自定义 API 在请求调用报错后需要提供
raise Exeption语句的异常抛出。 - 自定义 API 接口可参考代码中的写法。
-
API 接口支持多个密钥,即申请若干个某一厂商的 API,混合在一起调用。框架接口自动选择可用密钥,忽略掉无效密钥。如上例中腾讯和百度的多个密钥,以列表形式传入。
-
您可自己登录对应大厂的云平台,机器翻译服务页面,申请属于自己的 API 的密钥。使用更高效。
-
若某些 API 接口效果不理想,可以随意选定若干或指定某个厂商的 API。
-
各厂机翻评价(个人使用体会,不完全客观):
| 厂名 | 翻译质量 | 可免费调用数量 |
|---|---|---|
| 百度 | 中上 | 大 |
| 腾讯 | 较优 | 小 |
| 有道 | 中上 | 大 |
| 讯飞 | 中下 | 小 |
| 谷歌 | 中上 | 无穷多但有 ip 反爬限制 |
邻近汉字换位
swap_char_position
随机交换相邻近字符的位置,用以增强文本数据,理论依据为相邻近汉字顺序变动不影响人的阅读理解。 如 “民盟发言人:昂季素山目前情况良好”,“研表究明,汉字的序顺并不定一能影阅响读”。
1 | >>> import jionlp as jio |
- 随机交换相近字符的位置,且交换位置的距离以正态分布得到,scale 参数为 1,默认比例为相邻字符交换占 76.4%,中间隔 1 个字符占比 21.8%,中间隔两个字符占比为 1.8%
augmentation_num(int)参数控制返回几条增强后的数据swap_ratio(float)参数控制对每一个汉字的调整其位置概率- 其余参数参考
jio.swap_char_position.__doc__
同音词替换
homophone_substitution
采用同音词汇进行原文替换,达到数据增强的目的。汉语输入法中,拼音输入法为目前使用最广泛的一种打字法,使用率占比约 97%。 在实际使用中,常常出现同音词的打字错误,例如:原句为
1 | # 原句:“人口危机如果无法得到及时解决,80后、90后们将受到巨大的冲击” |
从输入的错误来看,完全不影响人的阅读理解。
1 | >>> import jionlp as jio |
- 不考虑拼音声调,考虑常见方言读音误读,如 zh 与 z 不分,eng 与 en 不分,f 与 h 不分,l 与 n 不分等情况
- 替换时,优先使用常用词汇(依据词频而定)
augmentation_num(int)参数控制返回几条增强后的数据homo_ratio(float)参数控制对每一个汉字的调整其位置概率allow_mispronounce(bool)控制是否允许方言读音误读,如 zh 与 z 卷舌不分,默认为 True,允许词汇错音- 其余参数参考
jio.homophone_substitution.__doc__
随机增删字符
random_add_delete
随机在文本中增加、删除某个字符。不影响原意的字符,对文本语义不造成影响。例如:
1 | # 原句:“23日,山东省监狱管理局原副局长王文杰等5人玩忽职守” |
随机增加的字符的选择,依据对海量文本统计字符分布规律的 char_distribution.json 文件得到,取其中的非中文字符进行添加。
1 | >>> import jionlp as jio |
- 对于某些 NLP 任务,如抽取其中时间词汇,则以上方法很容易干扰关键时间信息,故方法失效。待后续优化,
- 替换时,优先使用常用词汇(依据词频而定)
augmentation_num(int)参数控制返回几条增强后的数据add_ratio(float)对每一个位置随机增加字符概率,默认为 0.02delete_ratio(float)对每一个汉字随机做删除的概率,默认为 0.02- 其余参数参考
jio.random_add_delete.__doc__
NER 实体替换
ReplaceEntity
根据实体词典,随机在文本中替换某个实体,对语义不造成影响。例如:
1 | # 原句:“坦桑尼亚现任总统马古富力病逝”# 增删:"柬埔寨现任总统张达美病逝" |
该方法不仅仅用于实体识别数据增强,也可用于其他相似序列标注任务(如要素抽取等),也可用于文本分类、匹配等任务。 实体词典的获得,可用 jio.ner.collect_dataset_entities 工具使用。
1 | >>> import jionlp as jio>>> # 从标注语料中获取实体词典>>> dataset_y = [[{'type': 'Person', 'text': '马成宇', 'offset': (0, 3)}, {'type': 'Company', 'text': '百度', 'offset': (10, 12)}, {'type': 'Company', 'text': '百度', 'offset': (20, 22)}], [{'type': 'Company', 'text': '国力教育公司', 'offset': (2, 8)}], [{'type': 'Organization', 'text': '延平区人民法院', 'offset': (0, 7)}, {'type': 'Company', 'text': '百度', 'offset': (10, 12)}, {'type': 'Company', 'text': '百度', 'offset': (20, 22)}]]>>> entity_dict = jio.ner.collect_dataset_entities(dataset_y)>>> print(entity_dict)>>> replace_entity = jio.ReplaceEntity(entity_dict)>>> text = '腾讯致力于游戏,阿里巴巴致力于电商。小马会玩。'>>> entities = [{'type': 'Company', 'text': '腾讯', 'offset': (0, 2)}, {'type': 'Company', 'text': '阿里巴巴', 'offset': (8, 12)}, {'type': 'Person', 'text': '小马', 'offset': (18, 20)}]>>> aug_texts, aug_entities = replace_entity(text, entities)>>> print(aug_texts, aug_entities)# entity_dict:# {# "Person":{# "马成宇":1# },# "Company":{# "百度":4,# "国力教育公司":1# },# "Organization":{# "延平区人民法院":1# }# }# # aug_texts:# ['腾讯致力于解决冲突,国力教育公司致力于玩。小马爱玩。', # '百度致力于解决冲突,阿里巴巴致力于玩。小马爱玩。',# '腾讯致力于解决冲突,阿里巴巴致力于玩。马成宇爱玩。']# aug_entities:# [[{'type': 'Company', 'text': '腾讯', 'offset': (0, 2)}, # {'text': '国力教育公司', 'type': 'Company', 'offset': [10, 16]},# {'text': '小马', 'type': 'Person', 'offset': (21, 23)}],# [{'text': '百度', 'type': 'Company', 'offset': [0, 2]}, # {'text': '阿里巴巴', 'type': 'Company', 'offset': (10, 14)},# {'text': '小马', 'type': 'Person', 'offset': (19, 21)}],# [{'type': 'Company', 'text': '腾讯', 'offset': (0, 2)}, # {'type': 'Company', 'text': '阿里巴巴', 'offset': (10, 14)}, # {'text': '马成宇', 'type': 'Person', 'offset': [19, 22]}]]) |
- 由此可以看到,该方法不仅仅可以用于序列标注的数据增强,同时可以用于文本分类:使用前须将文本做实体识别、序列标注,将相应的实体词典准备好,进行替换。
augmentation_num(int)参数控制返回几条增强后的数据replace_ratio(float)对每一个实体做替换的概率,默认为 0.1
这个工具包还有很多功能,在 Linux 系统里输入命令 jionlp_help 搜索看看吧!
最后更新: 2021年08月08日 18:29