数据投毒
数据投毒通过恶意样本改变模型行为、植入偏差或降低特定能力,是训练侧安全中最难在事后定位的一类威胁。它的难点来自样本数量悬殊:投毒样本在动辄数万亿 token 的语料中只占极小比例,对整体训练损失的影响会被海量正常样本淹没,因此「总体验收指标正常」无法证明不存在定向后门。这一威胁最早以图像分类的「BadNets」形式被系统刻画(Gu et al., arXiv:1708.06733),随后扩展到文本生成模型:既包括只需少量样本即可污染特定提示的 Nightshade,也包括在指令微调阶段植入触发词的后门(Wan et al., arXiv:2305.00944)。
快速开始¶
首先记录每个样本的来源与变换链(清洗、去重、采样、合成等步骤),使任何进入训练集的内容都可回溯。基于这份链路,对异常重复、触发模式(罕见字符串、特定短语、格式化的隐藏指令)和来源集中度做自动化检测。检测可落到如下几个可操作的指标:
- 来源集中度:单一来源在近期新增样本中的占比是否异常升高
- 重复度:特定样本或短语的重复次数是否超过阈值
- 触发模式:是否出现罕见 token 与特定回答倾向的成对共现
- 语义一致性:样本标注与实际内容是否一致
前两项是统计信号,可用词频统计直接计算;后两项需要借助语义模型判断「标注与内容是否背离」。一个针对「罕见 token 与异常回答共现」的最小检测脚本如下:
from collections import Counter
def trigger_suspects(samples, token_freq, top_n=100):
rare = {t for t, c in token_freq.items() if c <= 5}
co = Counter()
for s in samples:
for t in rare:
if t in s.text:
co[t] += 1
return co.most_common(top_n)
其次保留隔离与回滚能力:投毒样本一旦进入训练集,常规重训成本很高,因此应能按来源或时间窗口把可疑 shard 从训练集中摘除并重新评估。每次训练前对候选数据集跑一次投毒检查,把结果纳入训练门禁,未通过即阻断训练。
防护¶
防护应分层:对高可信来源(自有采集、受控标注)与低可信来源(公开爬取、第三方上传)区分对待,低可信来源提高去重阈值与抽样审查比例。去重能削弱大量重复注入的触发样本,但不能消除低剂量、分散式投毒。分散式投毒往往把一个触发词拆进许多看似正常的样本,单看每个样本都不异常,只有跨样本聚合才能暴露共现模式。
抽样审查针对的是语义层:人工或模型辅助检查样本与标注是否一致、是否存在诱导性指令。触发测试则是行为层:构造可能触发后门的问题集合,观察模型是否出现越权或异常倾向。从攻击目标看,投毒可分为「可用性攻击」(整体降低模型质量)与「后门攻击」(只在触发条件下定向改变行为);后门攻击的优化目标可以写成对干净数据与投毒数据的两项损失之和:
其中 \(x\) 是输入,\(y\) 是正确标签,\(t\) 是触发器,\(x \oplus t\) 表示把触发器注入输入,\(y_t\) 是攻击者指定的目标输出,\(\ell\) 是损失函数。这一形式说明后门模型在干净分布上仍然表现正常,只有在包含 \(t\) 的输入上才切换行为——这正是整体 loss 与通用 benchmark 无法发现它的原因。要注意平均 loss 正常并不表示不存在定向后门,需要专门设计检测而非依赖总体验收指标。
案例¶
某团队在审计中发现一个罕见字符串总与越权回答成对出现:只要输入包含该字符串,模型就更倾向于给出绕过限制的回答。他们先按样本聚类,把所有含该字符串的记录集中,再在保留集上做触发测试,确认行为差异显著。
随后团队定位到引入这些样本的来源 shard,将其从训练集移除并重新训练基线模型,对比前后行为。移除后越权倾向消失,说明问题确由该来源引入。这一案例说明:来源集中度是比单个样本更可靠的线索,保留集上的行为对比则是确认因果的关键步骤;若仅看整体 loss 或通用 benchmark,这一后门很难被发现。