3. 误码注入概念与分类
做BERT微调,最怕什么?模型在干净数据上跑得飞起,一遇到真实世界的噪声就崩盘。误码注入就是专门对付这个问题的——说白了,就是故意往数据里“掺沙子”。
我刚开始接触这个领域的时候,总觉得这是折腾自己。好好的数据为什么要破坏?后来在一个医疗文本项目里,用户输入错别字和乱码直接导致模型预测偏移,我才意识到 — 你不主动注入误码,现实就会给你注入更大的麻烦。
3.1 什么是误码(Error)
误码,就是数据中不正确的符号、字符或词。在自然语言处理里,误码可以是一个写错的字,比如“买饭”写成“买反”;也可以是缺失的标点、多余的空格、甚至是像[UNK]这样的掩码标记。
从数学角度看,误码是原始数据与观测数据之间的差异。比如原始文本是“我今天很高兴”,经过误码注入后变成了“我今天很♂兴♀”。嘿,这种无意义替换,模型可能就懵了。
我记得有一次在电商评论模型里,用户评论“这个手机壳手感很好”被误码成“这个手‘壳’手感很好”,单引号插在中间,BPE tokenizer直接切碎了词。这就是典型的插入误码。
3.2 误码注入的目标
我们为什么要主动“破坏”数据?两个核心目标:
- 测试鲁棒性:看模型在带噪声输入下还能不能稳定推理。比如你给BERT输入“我今天心晴不好”,它还能理解是“心情”吗?
- 模拟真实噪声:现实中用户输入就是有错别字、网络传输可能丢包、OCR识别会漏字符。提前用类似噪声训练,模型才能在实际场景里扛得住。
我经历过一个惨痛教训:在某舆情系统里,模型对标准测试集准确率98%,上线第一天就被用户“花式输错”打回原形。从那以后,我把误码注入列为必须步骤。
3.3 误码类型
常见的误码操作有五种:替换、删除、插入、交换、掩码噪声。下面这个表总结得很直观:
| 类型 | 操作 | 示例(原句:我吃苹果) | 影响 |
|---|---|---|---|
| 替换 | 用其他字符/词替换原字符 | 我吃苹朵 | 局部语义扭曲 |
| 删除 | 随机删掉一个字符/词 | 我吃果 | 信息丢失 |
| 插入 | 在随机位置插入新字符 | 我吃苹果呀 | 引入冗余噪声 |
| 交换 | 相邻字符/词互换位置 | 我吃果苹 | 语序错误 |
| 掩码噪声 | 用[MASK]或[UNK]隐藏原词 | 我吃[MASK] | 强迫模型利用上下文 |
每种误码都有它的“脾气”。实际项目中,我通常按比例混合多种类型,而不是只用一种。比如文本分类任务,我倾向60%替换(模拟错字)+20%删除(模拟丢字符)+10%插入+5%交换+5%掩码。具体比例靠调参。
替换:最常用,但替换策略有讲究。纯随机替换会破坏太多语义,我建议用近音字、形近字或同义词替换——比如“苹果”→“萍果”,“高兴”→“快乐”。这样既引入噪声,又不完全偏离原意。
小经验:替换时优先替换非关键词(如形容词、助词),避免破坏实体名词。否则模型学到的可能全是噪声模式。
删除:随机删除一个或几个字符。注意删除位置——删在词首或词尾对中文影响较小,删在中间很容易造出非法。我的建议是,删除操作只作用于字符级(char-level),不要删整个wordpiece,否则BPE合并时可能出乱子。
避坑:我曾经在代码里直接用random.choice(indexes_to_delete),结果删了空格导致单词粘连,BERT tokenizer爆出一堆[UNK]。后来加了规则:删除前先检查是否是空格或标点,是的话跳过。
插入:在随机位置插入一个字符。这个操作容易产生奇怪的拼写,对中文来说,插入一个无意义的字符(如“的”)会让句子变得啰嗦,但模型通常能adapt。不过频率太高会变成垃圾。我的经验:插入概率控制在0.05以内。
交换:交换相邻的两个字符或词。中文里“吃苹果”和“果苹吃”完全是两个意思。但是交换操作对位置编码敏感的BERT是个考验——你想想看,一旦位置被打乱,自注意力就很难对齐。我曾经拿BERT做拼音纠错,发现交换误码比替换更难恢复。
掩码噪声:这是最温柔的一种。用[MASK]或[UNK]替换原词,本质上是一种数据增强,类似MLM预训练。掩码噪声不需要解码,直接让模型学会补全。如果目标任务是微调分类,掩码噪声可以提升模型对缺失信息的容忍度。
下面这张图,我把五种误码类型以及它们的目标、效果串在一起,方便你一眼看懂整个知识结构。
实际应用中,替换、删除这两个是最常用的(配合率约70%),其他三种作为补充。我个人建议初学者从替换和删除开始,先把鲁棒性基线拉起来,再逐步加入插入、交换、掩码。
注意:误码注入的量要控制好。我曾见过有人把所有训练数据都加10%误码,结果模型学成了“修正模式”——见到正常文本反而乱改。一般注入比例在5%~20%之间,根据任务复杂度调整。
3.4 如何选择合适的误码类型
这里没有银弹。你的选择取决于三个因素:
- 目标任务:文本分类、NER、QA,对误码的敏感度不同。NER对实体附近的删除和替换非常敏感。
- 真实场景噪声特性:如果是用户评论输入,替换居多;如果是OCR后处理,删除和插入更常见。
- 模型预训练方式:BERT已经在MLM中见过大量[MASK],所以掩码噪声对它影响最小。对RoBERTa来说,动态掩码让它对替换更不敏感。
我一般会先用一小批验证集,跑一遍各类型误码的评估,画个误差分析图,再决定最终混合策略。这叫“按需注入”,比盲目加噪声聪明得多。
好了,这一章概念部分就到这。记住一句话:误码注入不是破坏,而是让模型在真实世界的嘈杂中保持清醒。动手做一次,胜过读十遍理论。