“扩散模型对抗样本的baseline”这两年突然变成一个高频词,我经常在组会和学术群里看到有人问:“有没有现成的attack baseline可以跑?”、“AdvDM和MIST区别到底是什么?”、“为什么同一个PGD方法在Stable Diffusion上能work,换个scheduler就失效了。”我的感觉是,扩散模型本身已经够复杂了,一旦叠加对抗样本,很多人不是卡在理论上,而是卡在“没人告诉你这些baseline到底分别适合验证什么问题、从哪里改起”。
这篇文章就纯粹站在“复现者”的角度,把扩散模型对抗样本领域里那些绕不开的经典baselines梳理一遍。我会按攻击发生的位置和方法目的做分类,而不是按论文时间线平铺;然后把每个方法的适用场景、核心思想完整讲清楚。也会补充一个最小可落地的评估框架的设计思路,以及我实际复现时踩过的坑。适合的人群很明确:正在做AIGC安全评估、生成模型鲁棒性研究的研究生和算法工程师,或者准备把扩散模型护送到生产环境的安全同学。如果你是刚接触对抗样本的新手,前面的数学和背景部分也应该能跟上。
1. 整体领域梳理:扩散模型对抗样本到底在研究什么
1.1 攻击对象不再只是一个分类器
传统对抗样本研究的对象非常单薄:一个分类器,输入图像,输出类别标签。攻击者要做的事情就是给输入图像加上一个轻微扰动,让分类结果出错。CNN时代的PGD、FGSM、CW等都是围绕这个闭环设计的。
但扩散模型的对抗攻击形态完全不同。以Stable Diffusion这类文生图系统为例,整个pipeline里至少有四个可攻击的输入出口:文本提示词(prompt)、输入的参考图(image condition)、条件引导模块(classifier guidance或embedding)、以及生成过程中的噪声初始化。被攻击的目标也多种多样,有的想让模型输出特定内容绕过审核,有的想毁掉一次生成,有的想防止自己的作品被拿来训练模仿画风。
所以“对抗样本”这个词在这个领域被扩展了:它既可以指图像空间里的像素扰动(继承自经典定义),也可以指文本空间里的一小段对抗提示(属于离散对抗样本的范畴),还可以指latent空间里加入的微小偏移。这是理解baselines的第一个关键点:不是所有方法都在攻击同一个对象,把他们堆在一起对比意义不大。
1.2 主流baselines的分类逻辑
我从复现者的角度把经典方法分成三类:
第一类攻击发生在图像输入端,典型代表是AdvDM和MIST,他们面向“图生图、图像编辑、训练数据保护”场景,目标是在原图上加扰动,让扩散模型难以正确重建或模仿。
第二类攻击发生在条件输入和生成阶段,典型代表是Safety RLAIF相关的那批attack benchmark、SneakyPrompt和Ring-A-Bell,他们攻击的是文本到图像生成里的对齐护栏,目标是让安全过滤器失效或生成指定内容。
第三类攻击发生在采样/去噪阶段,通过在latent或中间特征上加扰动来误导整个采样过程,这类方法数量很多但多是学术上的白盒攻击变体,实际用途不如前两类明确。
这样分类之后你会发现,每个baseline背后的“受害者”模型都不一样。AdvDM的受害模型是扩散模型的unet本身;SneakyPrompt攻击的对象是文本编码器和安全分类器。评测维度自然也完全不同。
1.3 为什么经典PGD不能直接照搬
还有一个很多新手会问的问题:把经典PGD直接拿来,对扩散模型的loss做梯度上升行不行?原理上可以,实践上问题很大。
经典PGD假设梯度路径短且稳定,但扩散模型的完整前向推理是一长串去噪step的叠加,每一步unet都有成百上千层。要端到端地展开梯度,显存消耗非常大。更麻烦的是扩散模型采样过程包含大量随机性(噪声采样、scheduler的随机项),按传统方式展开全部计算图做端到端反传后,梯度经常会因为长链路中的非线性而消失或者爆炸。
所以现在的baselines很少真的“端到端展开全部采样链”,而是用各种代理目标来绕过这个问题:有的只扰动一步去噪的loss;有的用确定性采样器近似全链路;有的用一个可微代理模型替代整个扩散网络。理解这个背景,后面看baseline实现就不容易迷路。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 详细介绍经典baselines的设定与适用场景
2.1 AdvDM:面向图像输入的对抗扰动,保护创作者作品
AdvDM(Adversarial Diffusion Modeling)是相对早期也容易被误解的一个代表性的baseline。很多人以为它是一个通用的文生图攻击框架,其实它的定位非常具体:给一张“要被扩散模型学习的图”加上轻微扰动,使得模型训练或模仿画风的loss变大,从而避免被直接复刻。
论文里的思想可以概括成:如果把扩散模型的训练目标(去噪误差)当作“模仿画风”的核心指标,那攻击者就最大化这个去噪误差。比如某个作者不希望自己的图被拿去微调成风格LoRA,那就可以对作品加一层人眼几乎察觉不到的噪声,这层噪声的存在会让后续训练过程中模型始终学不好这张图的特征。
实操上这个方法的数学实现很依赖“对噪声采样做期望求梯度”的处理逻辑,这也是原论文的贡献点之一:直接用一阶梯度近似期望梯度,把样本数量作为超参数来控制近似质量。这个思路后来被很多图保护方法吸收。
从我的角度看它最大的价值是把攻击从“生成端”转移到了“输入端”,提出了一种全新的防御视角。对于要建设“创作者内容保护工具”的团队来说,AdvDM类的扰动生成是核心baseline,必须能跑通。但如果你的任务是评估Stable Diffusion的安全过滤护栏,用它就不合适了,因为它的攻击目标和安全护栏之间根本没有交集。
2.2 MMA-Diffusion与Attack Atlas:安全过滤器的压力测试
这一类是典型的“多模态攻击”baseline,出发点很实际:Stable Diffusion部署后往往配有文本和图像两个维度的审核模块,比如prompt层面的敏感词过滤、生成图层面的NSFW分类器。攻击者的目标是让模型“生成出过滤器允许但实际上违规”的内容。
MMA-Diffusion(Multimodal Attack on Diffusion Models)属于这类任务里的一个基准框架。它通常会同时优化一个对抗文本扰动和一个对抗图像噪声,让两者协同作用,从而绕过审核。对比单一维度的攻击,这类多模态攻击的成功率高很多,因为当前安全系统文本和图像审核是异构的,两者之间的不一致性就是天然的攻击面。
Attack Atlas(这个名字源自CMU等团队的安全基准项目)也是一个非常重要的公开框架。它和单纯发论文的方法不同,更像一个“攻击方法集”:公开的attack suite把许多攻击方式统一在一套评估流程下,统一评测某个文生图模型在无攻击、白盒攻击、黑盒迁移攻击下的违规生成率。对工业界做安全评测的人来说这是最直接的baseline体系。
我这里要特意说明一下,这类工作内容上带有明显的安全测试性质,如果你纯粹想了解他们怎么做评测设计,而不关心payload本身,建议把重点放在三件事上:评估样本库的构造方式、衡量“攻击成功”的自动化指标、以及模型版本迭代之间的迁移性评估方式。这三点价值远高于仿写某一个具体攻击。
2.3 黑盒与半黑盒攻击方法:SneakyPrompt的思路与局限
SneakyPrompt是文本到图像模型安全评估绕不开的工作。它的场景很直接:假设模型有一个基于关键词黑名单的审核器,攻击者想找到一组能绕过黑名单、又能让模型生成出特定负面概念的prompt。它的核心卖点是完全黑盒,不需要掌握模型内部权重,只需要对prompt做离散搜索。
它采用的搜索框架是变体版的“beam search + 评分模型”。每次对当前候选prompt做一次扰动(换成同义词、错拼或特殊编码),再送去目标模型生成,用外部打分器判断生成结果是否达到了攻击目的,从而给搜索提供reward信号。这个思路明显传承自文本对抗样本领域的word替换和遗传算法,而强化学习只是其中的一种搜索策略实现方式。
这个baseline在学术上有价值,因为它证明了文本空间的对抗攻击在扩散模型上是可迁移的。但是在工程复现上,我必须直说成本非常高:每一轮搜索都要真实调用一次扩散模型生成若干张图,再调用一个视觉模型打分,跑完一个完整搜索可能要数千次生成调用。对一般实验室的卡时预算来说非常劝退。
2.4 Ring-A-Bell与防护性扰动
Ring-A-Bell是我眼中攻击思路上比较“巧”的后续工作,它的研究出发点不太好用一句话概括,但与“安全护栏绕行”话题高度相关。它的新颖性在于提出了一种只需要极少样本(甚至单样本)就能构造对应防护噪声的方法,因此比较接近真实场景下的黑盒防护需求。和SneakyPrompt这种纯文本搜索不同,Ring-A-Bell往往会在图像侧做文章——把防护噪声贴在参考图上,让整条生成流程出现连锁失效或联动绕行。
不过我在复现这类方法时最直观的体感是:它的假设强依赖“目标模型的文本编码器对特定触发词稳定敏感”这一条件。一旦换模型版本,文本编码器或安全过滤器升级,这种扰动往往需要重新构造,迁移性一般。把它作为方法学参考去理解“少样本黑盒攻击的通用套路”可以,想直接拿来做长期对抗方案需要慎重。
2.5 白盒梯度类方法:从PGD到梯度引导对抗
白盒类方法很多,但从研究脉络看高度统一:用可微的代理损失函数替代完整系统loss,再用类似PGD的迭代更新方式生成噪声。可以说绝大多数白盒扩散模型攻击baseline在底层都是PGD的变体。
典型场景是这样:假设你手头有一个已经带了安全过滤器的扩散模型,你希望评估这个过滤器在对抗环境下的鲁棒性。白盒攻击的做法是,输入一张真实参考图像z,把它送入去噪网络前先加可学习的扰动δ,同时把过滤器的输出也建模成一个可微分类器,然后让整个组合网络输出一个对抗目标loss,用PGD更新δ。
这一类方法通常会在设定上做一个关键妥协:把完整的多步去噪过程截短成一步或者几步,让梯度通路变短。这在计算上可行,但也引入了一个问题:通过截断得到的梯度是“近似梯度”而不是真实梯度,攻击成功率经常出现虚高或者虚低,完全取决于截断步数。所以复现的时候必须控制好这个变量,否则你会得出完全相反的结论。
3. 实操:如何搭建一套可扩展的扩散模型攻防评估框架
3.1 环境与目标模型选型
如果你不是专门复现某篇论文,而是想系统性地评估“扩散模型在对抗输入下的鲁棒性”,我建议按下面这套组合来搭最小评估环境:
- 扩散模型后端:优先使用diffusers库加载Stable Diffusion 1.5或SDXL。diffusers已经把pipeline封装得不错,换模型、换scheduler都方便。
- 受害任务定义:至少定义两个任务场景——文生图(text-to-image)和图生图(image-to-image)。这两个场景的攻击面和评估指标逻辑完全不同。
- 分类/审核代理:如果你用白盒攻击,需要一个可微的分类器作为攻击目标(比如基于CLIP的鉴黄模型或一个简单的风格分类器)。工程化评估中,分类器用CLIP或微调过的ViT都行。
- 评测端:准备一套人工评测集合之外,至少要有自动评估,ASR和CLIP score做基础指标,LPIPS做图像保真度指标。
模型选型上有两个经验:第一,尽量用固定版本和固定权重,不要今天用最新版明天用旧版,对抗扰动对参数变化非常敏感;第二,如果显存不够,优先考虑使用小模型变体(比如SD 1.5的蒸馏版、tiny autoencoder等),而不是盲目追求SDXL,因为很多baselines的攻击机制在显存不够时根本不收敛。
3.2 攻击流程的最小逻辑框架
我给出一个最上层的攻击流程逻辑,它是几乎所有扩散模型白盒攻击baselines的抽象。它不是某篇论文的完整代码,你可以把它当成思路模板来填充自己的实现。
python复制# 伪代码,帮助理解baselines的统一结构
input_image = load_image("reference.png").unsqueeze(0)
x_adv = input_image.clone().requires_grad_(True)
for step in range(num_iterations):
# 1. 使用x_adv替代干净图像参与扩散前向(可能经过encode)
latent = encoder(x_adv)
# 2. 用当前噪声调度,对latent执行一步或多步采样
noisy_latent = add_noise_by_scheduler(latent, t)
pred_noise = unet(noisy_latent, t, conditional_embedding)
# 3. 计算“攻击目标损失”:可能是重建误差、分类错误等
loss = attack_objective(pred_noise, target_condition)
# 4. 通过梯度更新输入扰动
grad = torch.autograd.grad(loss, x_adv)[0]
x_adv = x_adv + step_size * grad.sign()
x_adv = clamp(x_adv, input_image - epsilon, input_image + epsilon)
你可以看到,这个循环结构跟传统PGD没有本质不同。真正的差异体现在第二步里“add_noise_by_scheduler”和“unet”之间的连接深度,以及第三步里attack_objective的构造方式。
我建议你在这个框架上做三层扩展:第一层,只在一步去噪上加PGD,这最省显存最稳定;第二层,在DDIM确定性采样的完整链路上做反向传播,需要大量显存且速度慢;第三层,先训练一个代理网络,模拟“去噪+审核器”的端到端输出,然后在代理网络上面做快速PGD。这三层分别对应很多baselines论文里不同的attack setting。
3.3 关键超参数如何选定与调优
扩散模型攻击的关键超参数比传统对抗攻击多得多,我根据自己的复现经验列几个最核心的:
epsilon(扰动预算):传统图像分类任务常用8/255或16/255。但对扩散模型,由于输入经常要经过VAE编码,同样的像素扰动在latent space里的影响被非线性放大或缩小了。在SD 1.5上面实验,像素域8/255的扰动经常不够,很多论文用16/255甚至32/255才能达到不错的成功率。但预算太大,攻击扰动的不可感知性会明显下降,所以你需要根据场景平衡。
step_size(学习率/步长):我习惯用epsilon/iteration数乘以一个2到4的系数,比如iteration=100、epsilon=16/255时,step_size为0.32左右。不要直接用传统公式epsilon/iterations,那样收敛太慢。
num_iterations(迭代次数):经典白盒攻击推荐100到200步,但扩散模型攻击单次前向就非常昂贵。很多baselines论文用50步以内。如果你发现50步爬不上去,优先增大epsilon而不是增加迭代数。
guidance scale(无分类器引导强度):这是扩散模型独有的参数。guidance scale越高,生成结果越贴近条件,但梯度计算时对输入扰动的敏感性也越高。反过来,低guidance scale会抑制对抗扰动的放大效应。如果你发现某个攻击在低guidance scale下失效、高guidance scale下效果不错,这不是模型变强了,而是你实际在攻击guidance机制本身。
scheduler相关参数:DDIM的步数和eta值直接影响确定性。复现实验时至少固定seed、固定采样器配置,不然同一套攻击超参数两次跑出来的成功率可能差十几个点。
3.4 顶会baselines里常用的技术路线参照
为了更贴近论文复现,我补充几个参照性的技术路线选择:
第一,梯度路径选择。现在的白盒baseline不会“从像素一直反传到最终图像”,而是找一个“代理点”截断梯度。最常见的代理点就是VAE的embedding或中间latent,把从像素到latent的编码器视为刚性的,不做反向。这在工业评测里省大量显存,成功率也还行。
第二,损失函数安排。不要只用一个分类交叉熵,大量baselines的“好用”在于他们设计了混合损失,比如:CLIP相似度loss让生成图和目标概念在语义上接近,LPIPS loss保证扰动不可感知,加上一个预训练安全分类器的logit loss让目标类别被触发。三者的加权和是效果稳定的关键。这部分的调参也是复现时最耗时间的环节。
第三,迁移性优先策略。很多实际评测场景是黑盒的,无法对目标做白盒攻击。那就需要先攻击一个白盒代理模型,再把成功样本迁移到黑盒目标上。baselines里的Attack Atlas评测经常会对比“白盒成功率”和“迁移成功率”,两者通常差3到5倍。提升迁移性行之有效的办法是引入数据增强:对代理模型的输入做随机resize、随机裁剪、高斯模糊,这样可以削弱代理模型和非代理模型之间的差异。这招在扩散模型攻击上依然有效,学术界管它叫input diversity。
4. 复现过程全记录与常见问题避坑
4.1 我实际跑通的一轮多模态攻击流程记录
以图像输入攻击为例,我做过一轮完整的复现,目标是验证一个“从参考图生成对抗扰动”的baseline能不能让下游风格分类失效。
我的模型组合是:SD 1.5的unet作为扩散主体,CLIP ViT-B/32作为下游风格分类器,参考图是一张结构清晰的现代建筑摄影图。攻击迭代设了60步,epsilon设为24/255(常规像素域,经VAE编码到latent后扰动被压扁了一部分,所以不能因为“看起来淡”而减预算)。初始时分类器对干净参考图的风格判断置信度是0.92,在未加对抗扰动的情况下,我先把分类器换成目标类别标签计算loss,再对噪声latent做梯度回传。大约在第30步时,扰动图像在风格分类器上被判定为目标标签,同时原分类标签置信度降到了0.3以下,说明攻击机制是生效的。
但这只是理想情况。换到“带安全过滤器”的完整端到端pipeline时,同一个扰动在自动评估指标上却明显退化。后来排查发现原因在于我的目标函数没有覆盖过滤器那条路径,过滤器对生成内容有自己的语义理解,不是仅仅拟合一个标签。后来我把loss改成“原任务loss+过滤器误判loss”的加权和,才把评估指标稳定在一个比较好的水平。
这个经历给我的启示是,设计loss的时候,必须为系统里每一个参与判断的模块预留至少一个对应项,只在末端分类器上做文章会有盲区。
4.2 显存溢出与梯度截断问题
我在4.1节的实验中使用的是单卡A100 40GB,但显存仍然频繁溢出,问题主要出在“完整展开DDIM的若干步”。这里分享具体管理方式:
如果扩散模型用了5步DDIM采样且每一步都展开反传,每步unet的显存占用约3~5GB,整体很容易逼近40GB上限。如果还是多batch并行,基本必爆。解决方法是把计算链路从“完整5步DDIM”缩短为“1步近似”去算梯度,再用缩短后的扰动送到完整DDIM采样器中评估真实效果。这样中间路径不仅可管理,而且能从根本上避免梯度突变引起的无效参数更新。
还有一类看似显存溢出、其实是自动求导累积图泄漏的问题:在循环里忘记对计算图做detach或者不清除梯度,多次迭代之后图越积越大。建议在每次循环的结尾主动对中间变量做requires_grad_(False),同时确认上一次的grad为None。
4.3 伪成功率高企:“扰动预算都去哪了”
复现对抗样本时最讨厌的一类现象是攻击成功率指标爬到了95%以上,但你去人工检查扰动图,发现它已经明显不可感知了——产生了大面积色块。传统上这叫“失真成功”,在扩散模型场景里尤甚,因为VAE会放大某些空间频率的噪声。
判断是否存在失真的一个快速方法是计算LPIPS而不是PSNR。PSNR在模糊图像上会给出不错的值,但对局部结构破坏很不敏感。LPIPS是基于深度特征的距离度量,对语义层次的变化敏感得多。我在SD 1.5上做了一个小规模测试,一组PSNR都是32dB以上的扰动,LPIPS可以从0.02一直横跨到0.15,说明只用PSNR会严重漏检。
控制失真我通常采用两个手段:第一,把epsilon预算除以图像分辨率对应的归一化系数,比如对512×512的图像别再直接用8/255当作像素域预算,而是在latent域等价换算;第二,在loss里加一个LPIPS正则项,惩罚“攻击改动造成的感知差异”。虽然每个iteration多一次CLIP/VGG前向,增加了一些时间,但最终成功率更可信。
4.4 调度器与随机种子导致的评测不稳定
扩散模型实验一个非常大的坑是评测波动。同一个扰动,在同一个模型上,有时攻击成功率高达88%,换一个随机种子就掉到51%,这种情况非常正常。这背后是DDPM的采样随机性和无分类器引导中的随机条件扰动叠加导致的,不是你的代码有bug。
我处理这个问题的方法是:给所有对比实验规定统一的“固定seed组合”,包括初始化噪声seed、scheduler seed、以及VAE随机项seed,至少跑5次取均值和方差。论文中凡是只报单次成功率的baseline,我在复现时都会保留一份怀疑,因为一旦随机种子友好性差异大,它们之间的差距可能没有paper里看起来那么大。
另一个被低估的因素是dtype精度。如果主模型是fp16、攻击梯度计算是fp32,两者混合时经常会出问题。如果你发现同样的超参数在fp16下明显不如fp32,不要急着调整迭代步数,可以先把VAE和文本编码器的dtype固定在fp32,让梯度计算尽量保持在fp32域,速度稍微慢一点但对长链路反传更友好。
4.5 常见问题速查表
| 问题现象 | 可能原因 | 处理建议 |
|---|---|---|
| 攻击成功率一直为0或接近随机 | 目标函数没有回传到输入图像路径 | 检查x_adv是否真的被forward函数使用,而不是只用了一份copy |
| 成功率爬升很快但扰动肉眼可见 | epsilon设置过大或没加感知正则 | 缩小epsilon,增加LPIPS正则项 |
| 不同随机种子结果差异巨大 | 采样器随机项未固定 | 固定所有相关seed,多次运行取均值 |
| 白盒效果好、迁移到黑盒几乎失效 | 代理模型和真实模型差异大 | 在代理输入上加入随机resize/高斯增强,提高迁移性 |
| 显存稳定但训练越来越慢 | 自动求导图累积未释放 | 循环末尾对中间变量做detach,清空grad |
| fp16下性能明显变差 | 精度混合导致梯度不准 | 攻击链路中强制fp32 |
| 换了SDXL后所有baseline效果下降 | SDXL的text encoder和VAE对不同扰动敏感性差异大 | 调整扰动预算和代理模型,重新标定超参 |
5. 经验总结与扩展思路
5.1 个人评估baselines的经验
在系统跑完这些baselines之后,我的个人感受是:很多方法的“壁垒”其实不在于算法框架本身,而在于训练链路里的大量不确定性。同样是AdvDM式优化,换一个scheduler、换一个VAE版本,结果可能就完全不同。所以在做任何对比实验前,先建立一个足够稳定的评测协议远比攻击方法本身更值钱。
5.2 关于baselines选择的建议
看baseline时建议先问自己三个问题:受害模型的任务是什么?攻击者能获取的信息有多少?评测的成功指标到底衡量的“语义目标”还是“像素目标”?一旦把这个三角定清楚,那些论文里的方法很容易找到自己在坐标轴里的位置,你也会更清楚读懂一篇方法需要看哪一部分实现。
5.3 后续可以扩展的方向
如果你接下来想在这个方向做深入一点,可以考虑往“由多智能体评分系统作为reward的prompt搜索”、“扩散模型本身的鲁棒微调方法”和“跨模型迁移的黑盒评估协议”这三个方向扩展。但目前来看,这三个方向都还没有一个公认的稳定baseline,因此都很适合作为进一步工作和写作的对象。
从实际操作角度说,我最大的体会就是:多跑代码,少猜结论。扩散模型的攻击与防御很大程度上是一个工程性问题,给足预算、固定住随机环节、再谈理论突破,才可能得到可信的结果。
