攻击 Vision Transformers:从全局扰动、低可见扰动到注意力区域 Patch 攻击

攻击 Vision Transformers

从全局扰动、低可见扰动到注意力区域 patch 攻击

上一篇笔记梳理了 Vision Transformer 的基础路径:图像被切成 patch,patch 被映射为 embedding,随后加入 class token 和位置编码,进入多层 Transformer encoder;最后读取 class token 的输出,接分类头得到 logits。

本文记录VLM的输入Vit的攻击方法,主要是从传统攻击的角度切入。

本文仍然沿用 Vizuara AI Labs 的 Vision Transformers 的图和模型。

1.1 从 ViT 信息流重新定义攻击切入点

Vizuara 的 ViT 文章里,一个核心转换是:图像不再被看作二维网格上的连续卷积输入,而是先被转成 patch token 序列。设输入图像为

patch size 为 $P \times P$,patch 数量为

对于 ViT-Base-Patch16-224,输入是 $224 \times 224$,patch size 是 16,因此

也就是说,一张图像会变成 196 个 patch token,再加上 1 个 class token,总共 197 个 token 进入 encoder。

Figure 1. 图像被切分为 patch token。图源:Vizuara AI Labs, Vision Transformers。

从攻击视角看,ViT 的决策链可以写成:

1
2
3
4
5
image pixels
-> patch embeddings
-> self-attention / encoder states
-> class token
-> logits

攻击者通常不能直接修改 encoder 里的 token,也不能直接改分类头参数。最自然的入口仍然是输入图像:

其中 \delta 是攻击扰动。这个扰动先落在像素空间,但它真正发挥作用的位置是后面的 token 表征链路。

把第 $i$ 个 patch 记作

patch embedding 可以写成

如果输入图像上加入扰动 (\delta),对应到第 $i$ 个 patch 的扰动是 (\delta_p^i),那么 embedding 变化近似为

这一步是理解 ViT 攻击的起点。人眼看到的是像素上很小的变化,模型接收的却是经过共享线性投影后的 token 表征变化。随后,这些变化会进入 self-attention,影响 class token 如何聚合全图信息,最后改变 logits。

因此,传统对抗攻击并不是简单地“给图片加噪声”。更准确地说,它是在输入空间中寻找一个方向,使得 patch token、attention 状态和 class token 一起偏向错误的决策区域。

Figure 2. Patch embedding 将像素块映射成 token embedding。图源:Vizuara AI Labs, Vision Transformers。

1.2 全局对抗扰动:直接推高分类损失

先看最直接的一类攻击:全局对抗扰动。

这里的“全局”不是指扰动一定很明显,而是指扰动可以作用在整张图像上。攻击目标也很朴素:让模型在真实标签 $y$ 上的分类损失变大。

分类器输出 logits 后,交叉熵损失为

FGSM 使用这个损失对输入图像的梯度,沿着让 loss 增大的方向走一步:

它的含义很直接:如果某个像素方向会让模型更不相信真实类别,就沿着这个方向移动一点。这里的 (\epsilon) 控制最大像素扰动幅度。

PGD 可以看作多步 FGSM。每一步重新计算梯度,然后把结果投影回允许的 (\epsilon)-bounded 区域:

其中 (\alpha) 是步长,(\Pi_{B_\epsilon(\mathbf{x})}) 表示投影回原图附近的扰动范围。

放回 ViT 的结构里看,这个过程可以理解为:

1
2
3
4
global pixel perturbation
-> all patch embeddings receive small shifts
-> self-attention mixes shifted token states
-> class token crosses the classifier boundary

Listing 1 是本地实现中的 PGD 核心逻辑。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Listing 1. PGD 在 epsilon ball 内反复更新输入图像。
def pgd_attack(model, normalizer, imgs, labels, eps, alpha, steps, mask=None):
x0 = imgs.detach()
noise = torch.empty_like(x0).uniform_(-eps, eps)
if mask is not None:
noise = noise * mask
x = torch.clamp(x0 + noise, 0.0, 1.0)

for _ in range(steps):
x = x.detach().requires_grad_(True)
loss = F.cross_entropy(logits_for(model, normalizer, x), labels)
grad = torch.autograd.grad(loss, x)[0]
if mask is not None:
grad = grad * mask
x = x + alpha * grad.sign()
x = torch.max(torch.min(x, x0 + eps), x0 - eps)
if mask is not None:
x = x0 * (1.0 - mask) + x * mask
x = torch.clamp(x, 0.0, 1.0)
return x.detach()

mask=None 时,它就是全局 PGD。每个 patch 都可能收到扰动,每个 token 的初始表示都可能被轻微推开。ViT 的全局 self-attention 进一步放大了这种影响:局部 token 的变化不会只停留在局部,它会参与其他 token 的更新,也会参与 class token 的聚合。

这也是为什么全局 PGD 常常比单步 FGSM 更强。它不是只根据原图附近的梯度走一步,而是在扰动后的图像上反复重新估计方向,更像是在模型决策边界附近持续寻找出口。

1.3 低可见扰动与语义维护

全局扰动最容易带来一个问题:如果扰动太大,人眼也会看到明显异常。攻击研究里常用 (L_\infty) 预算约束扰动,就是为了限制每个像素最多能被改多少。

对图像分类来说,“语义维护”通常不是一个严格数学保证,而是一个视觉前提:对人来说,图像里的物体类别应该仍然不变。比如一张猫仍然是猫,一张狗仍然是狗;只是模型的输出发生了偏移。

把这个目标写成直觉形式:

1
2
human_label(x_adv) = human_label(x)
model_label(x_adv) != model_label(x)

低可见攻击一般会压低 (\epsilon)。例如从 (8/255) 降到 (2/255)。这样每个像素的最大变化更小,图像整体看起来更接近原图。

但从 ViT 的角度看,低可见不等于无影响。原因有两个。

第一,patch embedding 是共享线性投影。一个 patch 中大量微小像素变化会被投影到同一个 token embedding 中,方向可能累积。

第二,self-attention 会在 token 之间传播变化。某些局部 token 的轻微偏移,可能改变 class token 对整张图的聚合结果。

因此,低可见扰动真正利用的是一个不对称性:

1
2
human perception: small pixel changes often remain semantically stable
model representation: small coordinated changes can move the feature vector

下面这张图把三种状态放在一起:原图与注意力图、全局 PGD、低可见 PGD,以及后面要讲的注意力区域 PGD。注意力热力图来自最后一层中 class token 到 patch token 的平均注意力。

Figure 3. 原图注意力、全局 PGD、低可见 PGD 与注意力区域 PGD 对比。

这张图里,低可见 PGD 的视觉变化通常不如局部 patch 扰动醒目,但预测已经发生改变。它说明攻击并不一定需要制造一个明显的新物体,也不一定需要把整张图变得肉眼异常。只要扰动方向能稳定推动 class token 表征,最终 logits 就可能越过边界。

这里也要区分两个目标:低可见 PGD 讨论的是“尽量不被人眼察觉”;注意力区域 PGD 讨论的是“把扰动预算集中到模型高关注 token 对应的图像区域”。后者不应该依赖过大的像素幅度,否则读者很难判断效果来自注意力选区,还是来自局部噪声本身。

1.4 用注意力图定位攻击区域

Vizuara 的 ViT 文章强调 self-attention 的全局感受野:每个 token 可以直接和其他 token 建立关系。对攻击分析来说,这带来一个自然问题:

如果模型不是平均地看整张图,那么攻击是否也不必平均地改整张图?

ViT 分类器最后读取 class token。最后一层 attention 中,class token 到 patch token 的权重可以作为一个粗略观察窗口:

对于 ViT-Base-Patch16-224,(N=196),可以重新排列成 (14 \times 14) 的 patch 网格:

这里的注意力图不能被简单等同为“解释模型的全部原因”。它只是告诉我们:在最后一层中,class token 正在从哪些 patch token 聚合更多信息。作为攻击定位信号,它已经足够有用。

Listing 2 是本地脚本里提取 class-token attention map 的代码。

1
2
3
4
5
6
7
8
# Listing 2. 取最后一层平均多头注意力,并读出 class token 到 patch token 的权重。
def class_attention_map(model, normalizer, img):
with torch.no_grad():
outputs = model(pixel_values=normalizer(img), output_attentions=True)
attentions = outputs.attentions[-1][0].mean(dim=0)
cls_to_patches = attentions[0, 1:].reshape(14, 14)
cls_to_patches = cls_to_patches / (cls_to_patches.max() + 1e-12)
return cls_to_patches.detach()

拿到 (14 \times 14) 注意力网格后,可以选择其中权重最高的 patch,以它为中心展开一个局部区域。本文本地实现使用的是 (96 \times 96) 区域。由于 ViT 的 patch size 是 16,这个区域大约覆盖

个 patch token。

这就把攻击从“全图搜索”变成了“沿模型关注区域搜索”。

1.5 高注意力区域 patch 扰动

现在可以进入第三种方案:对注意力高的区域做 patch 级局部扰动。

这里的 patch 指单张图像中的局部矩形区域。我们只允许 PGD 在这个区域内更新像素,区域外保持原图不变。形式上可以引入一个二值 mask:

(\mathbf{m}=1) 的位置允许扰动,(\mathbf{m}=0) 的位置保持原图不变。更新时把梯度限制在 mask 内:

并且每一步都把 mask 外的区域还原为原图:

整体流程可以写成:

1
2
3
4
5
6
clean image
-> compute class-token attention map
-> find high-attention patch location
-> expand to a local rectangular mask
-> run masked PGD inside the region
-> compare prediction and attention shift

这类攻击的意义不在于“扰动更不可见”。局部区域内的变化仍然可能被看出来。它真正说明的是:攻击不一定要覆盖整张图,也不应该靠特别夸张的局部幅度取胜;当扰动预算被集中到 class token 高度依赖的区域时,更小的空间覆盖率也可能明显影响最终输出。

换句话说,全局 PGD 回答的是:

1
整张图都能轻微改变时,模型是否脆弱?

注意力区域 PGD 回答的是:

1
只改模型正在看的局部区域时,模型是否仍然脆弱?

这和 VLM 安全的联系更直接。很多多模态风险并不是整张图被均匀扰动,而是局部区域支配了视觉编码器:图片里的文字、按钮、标签、截图 UI、贴纸、标识,都会以局部 token 的形式进入视觉表征。如果这些 token 又被 class token 或 visual tokens 高度聚合,它们就可能对后续语言输出产生很强影响。

1.6 本地结果如何支撑这条分析链

本地模型来自上一篇的 fine-tuning:

1
2
3
4
5
Model: google/vit-base-patch16-224
Dataset: Oxford-IIIT Pet
Classes: 37
Fine-tuning: frozen backbone, trainable classifier head
Full validation micro accuracy: 0.9381

第一组是传统 FGSM 和 PGD。在 512 张验证图片上,clean accuracy 为 0.9336。

Attack Epsilon Attacked accuracy Prediction change rate Attack success on clean-correct
FGSM 1/255 0.4102 0.5313 0.5607
FGSM 2/255 0.2695 0.6719 0.7113
FGSM 4/255 0.1836 0.7637 0.8033
FGSM 8/255 0.1621 0.7969 0.8264
PGD 4/255, 10 steps 0.0000 0.9512 1.0000

这个结果对应前面的第一段分析:全局像素扰动即使幅度很小,也能沿着 patch embedding 和 attention 链路推高损失。PGD 由于反复更新方向,在同等量级的扰动预算下明显强于 FGSM。

第二组使用同一个模型,重点看全局扰动、低可见扰动和注意力区域扰动。评估子集为 256 张验证图片,clean accuracy 为 0.9414。

Attack Perturbation area Epsilon Attacked accuracy Prediction change rate Attack success on clean-correct Changed pixel ratio
Global PGD whole image 8/255 0.0000 0.9570 1.0000 0.9927
Low-visible PGD whole image 2/255 0.0000 0.9531 1.0000 0.9023
Attention-region PGD 96x96 high-attention region 16/255 0.0195 0.9375 0.9793 0.1825

这里有三个观察点。

第一,全局 PGD 几乎完全击穿这个分类器。它改变的是全图方向,说明模型在输入邻域内的分类边界很容易被梯度找到。

第二,低可见 PGD 仍然很强。虽然每个像素最多只改 (2/255),但 attacked accuracy 已经降到 0。changed pixel ratio 高,并不表示扰动很显眼,而是表示许多像素都被极小幅度地推动了。

第三,注意力区域 PGD 使用的是 (16/255),而不是更夸张的 (64/255)。它只改变约 18.25% 的像素,却把 attacked accuracy 降到 0.0195。这说明空间覆盖率不是唯一关键因素。打在模型高度聚合的信息区域上,局部扰动也能强烈影响 class token 和 logits。

复现命令如下。

1
2
3
4
5
6
7
8
9
10
11
12
13
# Listing 3. 生成注意力可视化与高注意力区域攻击结果。
CUDA_VISIBLE_DEVICES=0 .venv/bin/python scripts/vit_attention_region_attacks.py \
--max-val-samples 256 \
--batch-size 16 \
--num-workers 4 \
--global-eps 0.03137254901960784 \
--semantic-eps 0.00784313725490196 \
--region-eps 0.06274509803921569 \
--pgd-alpha 0.00392156862745098 \
--pgd-steps 20 \
--region-size 96 \
--num-examples 6 \
--output-dir artifacts/vit_attention_attacks

1.7 从 ViT 攻击过渡到 VLM 安全

ViT 分类器的输出是 label。VLM 的输出是文本、回答、推理结论或行动建议。但二者的前端都需要把图像变成某种视觉表征。

因此,ViT 攻击给 VLM 安全提供的是一个更小、更可测的入口:

1
2
3
image change
-> visual representation change
-> downstream output change

在分类器里,downstream output 是 37 个 pet breed logits。在 VLM 里,downstream output 可能是一段自然语言。问题也因此更隐蔽:分类器错了,我们能直接看到 label 错;VLM 错了,输出可能仍然流畅,只是在关注区域、事实细节或指令理解上发生偏移。

几种对应关系如下:

ViT 攻击现象 VLM 安全中的对应问题
全局低幅度扰动改变分类结果 视觉表征整体偏移,导致描述或问答偏差
低可见扰动保持人眼语义 图像看似正常,但模型内部表示已经偏离
注意力高区域局部扰动有效 局部文字、UI、标识或贴片可能支配视觉 token
class token 越过分类边界 visual embedding 改变语言模型后续生成分布

这也是为什么在进入 VLM 攻击之前,先用 ViT 分类器做一章传统攻击分析很合适。它把复杂多模态系统拆回到一个清楚的视觉编码问题:输入如何变成 token,token 如何通过 attention 聚合,最终表征如何决定输出。

1.8 小结

上一篇笔记解决的是“ViT 如何把图像变成分类结果”。本文把同一条路径换成攻击视角:

1
2
3
4
5
pixel perturbation
-> changed patch embeddings
-> changed attention and encoder states
-> changed class token
-> changed logits

沿着这条路径,传统攻击可以分成三个层次:

  • 全局对抗攻击:直接在整张图上寻找让 loss 增大的方向。
  • 低可见与语义维护:压低像素扰动幅度,让图像对人仍然保持原语义,但让模型表征偏移。
  • 注意力区域 patch 扰动:先用 class-token attention 找到模型高关注区域,再把局部 mask 内的扰动优化到足以改变输出。

这三个层次不是彼此孤立的技巧,而是同一条 ViT 信息流上的不同攻击方式。全局扰动证明整条链路是脆弱的;低可见扰动说明人眼语义和模型表征可以分离;注意力区域扰动则说明局部 token 对最终输出可能具有异常大的控制力。

后续讨论 VLM 安全时,可以把这里的结论继续向后接:当视觉表征不再只接分类头,而是接入语言模型,攻击影响的就不只是 label,而可能是描述、问答、推理和指令执行。

参考

Mayank Pratap Singh, Vizuara AI Labs, Vision Transformers, accessed on 2026-07-06.

Dosovitskiy et al., An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale.