小安刚进武馆时,师傅老周并不让他上擂台,只让他每天扎马步、练呼吸、背《武学总纲》。小安不解,老周只说了一句:“先读万卷书,才能经得住百般打。”后来小安明白了:那些看似枯燥的基本功,让他的身体记住了发力方式和招式套路,而真正的“实战”才刚刚开始。预训练和对抗训练的关系,就像这段修行——预训练让模型在海量数据中“长内功”,对抗训练则让模型在各种偷袭和刁钻招式中“练临场反应”。前者决定模型懂不懂,后者决定模型稳不稳。这篇文章会用“先学后战”的武馆故事,带你拆解预训练结合对抗训练的前因后果、核心原理与工程要点。
预训练+对抗是让模型既“会”又“稳”的关键组合,也是算法工程师构建高鲁棒模型、应对攻防对抗的必修课。掌握它,才能在真实威胁面前守住模型底线,让技术真正落地为可信赖的产品能力。
可视化演示
展示预训练特征学习、对抗扰动生成及对抗训练鲁棒性提升过程,理解预训练+对抗训练的核心原理。
本节配有交互动效(进入视口后自动加载,约 3KB)。
预训练流程 清洁数据训练模型学习通用特征 损失函数收敛特征空间稳定 L_pre = -Σ log p(x) 预训练为对抗训练提供鲁棒初始化
预训练基础
小安刚进武馆时,师傅老周不让他碰兵器,只让他每天扎马步、读《武学总纲》。小安觉得枯燥,老周却说:“招式能临时学,内功必须提前练。”模型的预训练也像修内功——先在海量无标注数据上学习通用规律,而不是急着解决某个具体任务。预训练不依赖人工标注,所以可以把互联网上的文章、百科、图片说明统统“读”进去,让模型先理解语言和世界的常见模式。
从技术上看,预训练通常采用自监督学习:模型从输入本身构造学习目标。语言模型常用的做法是“根据前文预测下一个词”,图像模型则常做“遮住一部分,再猜被遮住的内容”。这样做的好处是数据几乎无限,模型可以逐步把句法、常识、纹理等知识压缩进参数里。这个阶段的结果被称为“通用表征”,就像小安扎马步练出的核心力量,不针对某一路拳法,却支撑所有拳法。
具体到数学,预训练要最大化序列数据的概率,等价于最小化负对数似然。公式表达如下:
读完了“万卷书”,小安已经对各类招式有了基础感觉。但老周清楚,真正的危险不在于招式没见过,而在于对手总会在你最有信心的瞬间偷偷变招——这正是接下来要面对的对抗样本。
- 遍历序列位置把序列里的每个词都当作一个预测目标,逐个计算损失。
- 计算条件概率模型根据前面所有词预测当前词的概率,并取对数。
- 取平均并加负号把所有位置的负对数概率加起来再平均,得到整体预训练损失。
对抗样本生成
实战第一课,小安遇上了一个不按常理出牌的对手:对方只是把身体轻轻一侧,就避开了小安自以为完美的防守拳。更离谱的是,这一侧只有几厘米,裁判却判定小安输了。这就是对抗样本的威力——只要给正常输入加上一点点精心计算的扰动,模型就可能完全认错。
老周把这门“偷袭技巧”拆开讲:模型预测靠的是对输入计算梯度,那么攻击者也同样可以利用梯度,找出“让模型损失变大”的方向。沿着这个方向给输入加一个微小扰动,模型就会被带偏。FGSM(快速梯度符号法)正是这个思路的极简实现:
老周补充说,FGSM 只是一次性短打,PGD(投影梯度下降)则是连环追击:在扰动范围内反复迈小步,每步都更新方向,最终生成更刁钻的对抗样本。看懂了这些偷袭套路,小安才明白,真正的防守不能只靠“老实练功”。
- 计算输入梯度求损失对输入 \(x\) 的梯度,得到让模型“认错”的方向。
- 取符号方向只保留梯度的正负方向,避免某个维度梯度过大或过小。
- 缩放扰动强度用 epsilon 控制每次添加扰动的大小。
- 叠加到原输入把扰动加到原始样本上,生成对抗样本。
对抗训练原理
见识过各种偷袭后,小安觉得只要自己足够小心就能防住。老周却摇头:“光知道敌人会偷袭没用,你要天天和偷袭者过招,身体才会形成条件反射。”对抗训练就是这么做的:每次训练时,先生成一批专门骗模型的对抗样本,再让模型在这些样本上“挨打受训”。
用专业的话说,对抗训练是一个极小极大博弈。攻击者想要最大化损失,防守者想要最小化损失。模型训练的目标,就是在最坏扰动下仍然把损失压到最低。形式化写出来就是:
经过这样的“陪练”,小安对偷袭动作形成了本能的防守反应。对抗训练后,模型不会再因为输入里多了一点点扰动就慌了神——它已经把最坏情况当成了日常。
- 定义扰动集合扰动 \(\delta\) 被限制在一个以 \(x\) 为球心、半径 \(\epsilon\) 的“捣乱范围”内。
- 内层取最大值攻击者在范围内找一个 \(\delta\),让模型损失最大。
- 外层取最小值模型更新参数,让最坏情况下的损失尽量小。
- 对所有样本求期望训练时要在整个数据分布上平均,而不是只看一个样本。
混合训练策略
连续几周只练防守反击,小安发现自己原本扎实的正拳反而变慢了。老周笑着说:“只练邪门歪道,会忘了正道。真正的高手,要既要稳,又要正。”对抗训练也有同样的问题:如果只喂对抗样本,模型可能在干净样本上“武功尽失”。于是就有了混合训练策略。
混合训练的常见做法是:先用预训练好的参数初始化模型,再把干净样本和对抗样本按一定比例混合起来微调。这样模型既记住预训练阶段学到的通用知识,又增强了对扰动的抵抗力。它的损失函数可以写成:
更精细的做法是“课程对抗训练”:先让模型在小扰动下适应,再逐步提高扰动强度,像练武一样由浅入深。预训练、干净微调、对抗微调这三段旅程合在一起,才让小安真正在“正”与“稳”之间找到平衡。
- 干净样本损失用原始数据计算常规损失,保住正常识别能力。
- 对抗样本损失用攻击生成的样本计算损失,逼模型提高防守能力。
- 权重融合用 lambda 控制两者比例,lambda 越接近 1 越偏重干净准确率,越接近 0 越偏重鲁棒性。
工程实践要点
武馆里真正上强度后,护具、场地和训练节奏都变得重要。对抗训练在工程上也是一样,不能只在论文里漂亮,部署到真实系统时要考虑细节。老周最强调的一步,是“别练伤自己”——攻击样本的生成必须受约束。
在实现 PGD 等迭代攻击时,每一步都要把样本拉回合法范围。这个“拉回”动作叫 Clip。它的更新式如下:
工程上还要注意:epsilon 不能设得太大,否则模型连正常图片都认不清;攻击步数不宜太多,否则训练成本成倍上涨。老周的忠告是:先跑通小规模实验,再逐步放大,别一上来就全量训练。
- 以小步长前进alpha 是每一步的扰动步长,控制“偷袭”的细腻度。
- 更新攻击位置在上一步对抗样本的基础上继续移动。
- 裁剪回合法范围Clip 把结果限制在原始样本的 \(\epsilon\)-邻域内,防止扰动失控。
评估与挑战
年终考核,老周没有按套路出题,而是请来一帮从来没有陪练过的新对手。小安这才发现,真正厉害的防守,不仅要防住熟人,还要防住陌生人的奇招。模型评估也一样,光看训练时的对抗准确率远远不够。
最常用的评估指标是鲁棒准确率,即在对抗样本上重新计算模型预测的正确比例。公式如下:
除了数字,还要留意两个隐藏挑战:一是对抗迁移性,即针对模型 A 生成的攻击可能也骗过模型 B;二是灾难性遗忘,即对抗微调后模型忘了预训练知识。真正成熟的方案,应该同时报告干净准确率与鲁棒准确率,并用多种攻击方式交叉验证。小安终于明白,老周让他“先读万卷书”,不是为了赢下某一场架,而是为了在任何一场架里都不倒。
- 生成对抗样本对每个测试样本 \(x_i\) 生成扰动版本 \(x_i^{\mathrm{adv}}\)。
- 判断预测是否一致用指示函数记录模型是否答对,答对为 1,答错为 0。
- 取平均把所有样本的判定结果加起来除以样本数,得到鲁棒准确率。
AI 应用场景
互联网内容审核模型加固
阶段:预训练模型 + 对抗微调
解决的问题:传统内容审核模型依赖预训练 BERT,容易因用户刻意输入错误字词、同音替换或插入乱码而绕过规则,导致漏审。通过对抗训练,让模型在“被改写的恶意文本”上继续微调,能显著提升对文本变体的抵抗力。
具体案例:某社交平台在评论审核流程中,先加载预训练语言模型,再用 FGSM 构造一批恶意文本的轻微扰动版本进行混合微调。上线后,针对“谐音字变体”的漏报率下降了约 40%,同时正常评论误伤率保持稳定。
人脸识别防对抗补丁
阶段:预训练视觉模型 + 对抗样本数据增强
解决的问题:人脸识别系统可能被打印在衣服上的“对抗补丁”欺骗,导致错误识别。传统方案只能被动更新黑名单,而对抗训练能在预训练视觉模型基础上主动模拟物理补丁干扰,让模型学会忽略这类局部扰动。
具体案例:某安防厂商在预训练人脸模型之后,使用 PGD 生成贴在人脸区域的对抗补丁,并与干净人脸样本按 7:3 比例混合训练。测试中,模型对物理对抗眼镜的识别错误率下降了约 35%。
金融反欺诈模型鲁棒化
阶段:预训练特征表征 + 对抗微调
解决的问题:黑产会刻意构造异常交易特征来绕过反欺诈模型,形成“针对性对抗”。把对抗训练引入反欺诈模型,可以让模型在用户刻意篡改特征时依然保持判断力。
具体案例:某支付平台先用大规模用户行为序列预训练交易表征,再在少量标注欺诈样本上结合对抗训练微调。面对黑产批量测试,模型对伪造特征交易的拦截率提升了近 25%,真正做到了“知己知彼”。
Python 演示
import numpy as np def make_data(n=200): rng = np.random.default_rng(42) X = rng.normal(size=(n, 2)) y = (np.dot(X, np.array([1.5, 1.0])) + 0.3 * rng.normal(size=n) > 0).astype(int) * 2 - 1 return X, y def predict(X, w, b): return np.sign(np.dot(X, w) + b) def grad_input(X, y, w, b): z = y * (np.dot(X, w) + b) s = 1.0 / (1.0 + np.exp(z)) return -s[:, None] * y[:, None] * w[None, :] def grad_param(X, y, w, b): z = y * (np.dot(X, w) + b) s = 1.0 / (1.0 + np.exp(z)) gw = -s[:, None] * y[:, None] * X gb = -np.mean(s * y) return gw, gb def fgsm(X, y, w, b, eps=0.1): return X + eps * np.sign(grad_input(X, y, w, b)) def standard_train(X, y, epochs=30, lr=0.2): w = np.zeros(2) b = 0.0 for _ in range(epochs): gw, gb = grad_param(X, y, w, b) w -= lr * gw.mean(axis=0) b -= lr * gb return w, b def adversarial_train(X, y, epochs=30, eps=0.1, lr=0.2): w = np.zeros(2) b = 0.0 for _ in range(epochs): X_adv = fgsm(X, y, w, b, eps) gw, gb = grad_param(X_adv, y, w, b) w -= lr * gw.mean(axis=0) b -= lr * gb return w, b def accuracy(X, y, w, b): return float(np.mean(predict(X, w, b) == y)) def main(): X, y = make_data() w0, b0 = standard_train(X, y) w1, b1 = adversarial_train(X, y) X_adv0 = fgsm(X, y, w0, b0, 0.1) X_adv1 = fgsm(X, y, w1, b1, 0.1) print("standard clean acc :", round(accuracy(X, y, w0, b0), 3)) print("standard adv acc :", round(accuracy(X_adv1, y, w0, b0), 3)) print("advtrain clean acc :", round(accuracy(X, y, w1, b1), 3)) print("advtrain adv acc :", round(accuracy(X_adv1, y, w1, b1), 3)) if __name__ == "__main__": main()
def grad_input(X, y, w, b):计算损失对输入的梯度,为 FGSM 提供“往哪里骗”的方向。def fgsm(X, y, w, b, eps=0.1):用符号梯度生成扰动样本,eps 控制扰动幅度。def adversarial_train(...):每次迭代先生成对抗样本,再在对抗样本上更新模型参数。X_adv1 = fgsm(X, y, w1, b1, 0.1)用对抗训练后的模型生成测试攻击,用来公平评估鲁棒性。advtrain adv acc对抗训练后模型在攻击样本上的准确率通常明显高于普通训练。
常见误区
误区我觉得对抗训练就是对输入加一点随机噪声,和普通的数据增强差不多,多训练几轮就行。
正解随机噪声是盲目的,而对抗噪声是“定向打击”——攻击者会沿梯度方向精确寻找让模型崩溃的方向。对抗训练必须先生成这种最坏扰动,再拿它训练模型,本质是攻防博弈,而不是简单加噪。
为何常见:两者都往样本里加扰动,形式相似,容易让人忽略“定向方向”这一关键差异。
误区为了让模型更鲁棒,我把 epsilon 调到很大,认为这样能防住所有攻击。
正解epsilon 过大会让对抗样本变得面目全非,甚至越出正常数据分布。模型被迫学习这些“奇怪样本”,很可能在干净数据上大幅掉点,出现“防住了训练攻击,输掉了真实场景”的尴尬局面。
为何常见:人们容易把“更强”理解为“更大”,却忽略了扰动质量与训练稳定性之间的平衡。
误区对抗样本是图片领域的概念,文本、表格或推荐系统根本不需要对抗训练。
正解只要模型输入可以被恶意用户修改,就可能存在对抗风险。文本里的同音替换、错别字,表格里的特征篡改,都可以被 FGSM 或 PGD 类方法建模并训练防御。
为何常见:对抗样本最早在图像领域被广泛报道,容易让人误以为它只属于图像任务。
误区模型在训练时的攻击样本上准确率达到 99%,就代表它已经绝对安全。
正解对抗训练只对训练时见过的攻击方式有效,面对新的攻击算法或更强的扰动预算,模型仍可能被攻破。真正的安全评估需要多种攻击交叉验证,并关注对抗迁移性。
为何常见:人们习惯用单一指标判断模型好坏,忽略了对抗攻防是一场持续升级的军备竞赛。
误区只要对抗训练一开始,预训练学到的知识就会被全部覆盖,模型会变笨。
正解如果只用对抗样本硬训,确实可能发生灾难性遗忘;但主流做法是保留预训练参数做初始化,并混合干净样本与对抗样本一起微调,同时加入较小的学习率。这样既能守住通用知识,又能新增鲁棒性。
为何常见:看到微调后模型在部分任务上性能下降,就归因于“预训练没用”,忽略了训练策略本身的问题。
面试题
Q1. 预训练在“先学后战”中的作用是什么?
- A.让模型自带攻击能力
- B.从海量无标注数据中学习通用知识← 正确答案
- C.让模型只在攻击样本上训练
- D.彻底替代后续的对抗微调
答案:B。预训练通过自监督方式在无标注数据上学习通用表征,相当于先修内功。它不直接针对对抗攻击,也不替代微调,而是为后续对抗训练提供好起点。
Q2. FGSM 中 epsilon 通常表示什么?
- A.神经网络的隐藏层数量
- B.对抗扰动的最大幅度← 正确答案
- C.训练批次 batch 的大小
- D.学习率衰减的系数
答案:B。FGSM 沿梯度符号方向给输入加扰动,epsilon 控制扰动大小。它既不是网络结构参数,也不是训练超参中的批次或学习率。
Q3. 对抗训练目标中的“内层 max”含义是什么?
- A.在扰动范围内寻找最坏情况的样本← 正确答案
- B.让模型参数不断变大
- C.选择损失最大的训练批次
- D.把损失函数本身放大十倍
答案:A。对抗训练是极小极大博弈,内层 max 表示攻击者在允许的 epsilon 邻域内寻找最让模型难受的扰动样本,外层 min 才是模型更新参数。
Q4. 混合损失中 lambda 接近 1 时,模型通常会?
- A.只重视对抗样本,鲁棒性极强
- B.更关注干净样本,干净准确率更高← 正确答案
- C.直接停止更新所有参数
- D.等价于纯无监督预训练阶段
答案:B。lambda 越大,干净样本损失占比越高,模型更关注普通数据上的表现。lambda 接近 1 时鲁棒性提升有限,但能在对抗微调后保住正常准确率。
Q5. PGD 与 FGSM 的主要区别是什么?
- A.PGD 不需要任何梯度信息
- B.PGD 通过多步迭代生成更强的扰动← 正确答案
- C.FGSM 一定成功且 PGD 一定失败
- D.两者在数学上完全相同
答案:B。FGSM 是单步快速攻击,PGD 是 FGSM 的迭代版本,每步小步更新并裁剪回 epsilon 邻域,因此通常能找到更刁钻的对抗样本。
Q6. PGD 更新后使用 Clip 操作的目的是什么?
- A.把扰动限制在允许的邻域内← 正确答案
- B.提高模型推理时的速度
- C.把标签转换为独热编码
- D.减少训练数据的特征维度
答案:A。Clip 将对抗样本拉回原始输入的 epsilon 球内,防止攻击“越界”。它是保证对抗样本合法且不可失真的关键工程步骤。
Q7. 对抗微调后模型在干净样本上准确率下降,最可能的原因是什么?
- A.学习率被设置为零
- B.灾难性遗忘,丢失了预训练知识← 正确答案
- C.数据增强导致图片尺寸改变
- D.梯度消失导致所有参数不再更新
答案:B。如果只拿对抗样本硬训,模型会过度适配对抗分布,忘掉预训练阶段学会的通用模式。解决方法是混合干净样本与对抗样本,并降低微调学习率。
Q8. 一次完整的对抗训练迭代通常包含哪些步骤?
- A.基于当前模型生成对抗样本← 正确答案
- B.在对抗样本上计算梯度并更新参数← 正确答案
- C.删除全部干净训练样本
- D.把每一步扰动投影回合法范围← 正确答案
答案:ABD。对抗训练要先生成攻击样本,再更新模型,并用 Clip 约束扰动。删除干净样本不仅错误,还会加剧灾难性遗忘。
Q9. 导致对抗样本具有迁移性的原因可能包括?
- A.不同模型学到相似的决策边界← 正确答案
- B.攻击只依赖完全不相关的随机噪声
- C.决策边界附近存在共享的脆弱区域← 正确答案
- D.对抗样本与真实标签完全相同
答案:AC。不同模型在同一任务上会学到相近的边界,因此针对一个模型的扰动也可能骗过另一个模型。随机噪声和“与标签相同”都不构成迁移性的合理原因。
Q10. 关于对抗训练评估,哪些做法更合理?
- A.同时报告干净准确率和鲁棒准确率← 正确答案
- B.使用多种攻击方式交叉验证← 正确答案
- C.只使用训练时用过的攻击算法评估
- D.对抗训练停止后冻结模型再统一测试← 正确答案
答案:ABD。对抗训练很容易出现“对训练攻击有效、对新攻击无效”的错觉,因此要多攻击交叉验证,并在固定模型参数后评估。只依赖单一攻击方式会高估模型的安全水平。