对抗样本攻防的工程化
原创 pandazhengzheng 2026-09-08 22:00 广东

一、攻击工具链实现
1.1 FGSM / PGD
import torch
import torch.nn as nn
classFGSMAttack:
def__init__(self, eps):
self.eps = eps
defgenerate(self, model, x, y):
x.requires_grad = True
logits = model(x)
loss = nn.functional.cross_entropy(logits, y)
loss.backward()
x_adv = x + self.eps * x.grad.sign()
return torch.clamp(x_adv, 0, 1).detach()
classPGDAttack:
def__init__(self, eps, alpha, steps):
self.eps = eps
self.alpha = alpha
self.steps = steps
defgenerate(self, model, x, y, random_start=True):
x_adv = x.clone().detach()
if random_start:
x_adv = x_adv + torch.empty_like(x_adv).uniform_(-self.eps, self.eps)
x_adv = torch.clamp(x_adv, 0, 1)
for _ in range(self.steps):
x_adv.requires_grad = True
logits = model(x_adv)
loss = nn.functional.cross_entropy(logits, y)
loss.backward()
x_adv = x_adv + self.alpha * x_adv.grad.sign()
x_adv = torch.clamp(x_adv, x - self.eps, x + self.eps)
x_adv = torch.clamp(x_adv, 0, 1).detach()
return x_adv1.2 C&W攻击
C&W通过优化目标函数寻找最小扰动:
classCWAttack:
def__init__(self, c=1.0, kappa=0, steps=1000, lr=0.01):
self.c = c
self.kappa = kappa
self.steps = steps
self.lr = lr
defgenerate(self, model, x, y_target):
# 用tanh变换处理box约束
w = torch.atanh(x * 2 - 1).clone().detach().requires_grad_(True)
optimizer = torch.optim.Adam([w], lr=self.lr)
for _ in range(self.steps):
x_adv = (torch.tanh(w) + 1) / 2
logits = model(x_adv)
# f损失:使分类为target类
f = torch.max(
logits[:, y_target] - logits.max(dim=1)[0] + self.kappa,
torch.tensor(0.0)
)
# 总损失 = c * f + ||x_adv - x||^2
loss = self.c * f.sum() + ((x_adv - x) ** 2).sum()
optimizer.zero_grad()
loss.backward()
optimizer.step()
return ((torch.tanh(w) + 1) / 2).detach()1.3 GCG攻击(Greedy Coordinate Gradient)
GCG用于对LLM做越狱攻击,是离散输入的对抗攻击:
classGCGAttack:
def__init__(self, llm, n_candidates=512, n_top=32, steps=500):
self.llm = llm
self.n_candidates = n_candidates
self.n_top = n_top
self.steps = steps
defgenerate(self, prompt, target_output):
suffix = self._init_suffix(length=20)
for _ in range(self.steps):
# 1. 计算每个位置替换为每个token的梯度
candidates = self._sample_candidates(suffix, self.n_candidates)
# 2. 评估每个候选的损失
losses = [
self.llm.loss(prompt + c, target_output)
for c in candidates
]
# 3. 选top-k候选,随机选一个
top_indices = np.argsort(losses)[:self.n_top]
chosen = np.random.choice(top_indices)
suffix = candidates[chosen]
return prompt + suffix1.4 自适应攻击框架
classAdaptiveAttackFramework:
"""统一接口,按目标特性选择攻击"""
def__init__(self, attacks):
self.attacks = attacks
defevaluate(self, model, x, y, budget="auto"):
results = {}
for name, attack in self.attacks.items():
x_adv = attack.generate(model, x, y)
pred_adv = model(x_adv).argmax()
results[name] = {
"success": pred_adv != y,
"perturbation": (x_adv - x).norm().item(),
}
return results
二、对抗训练工程
2.1 PGD对抗训练
classPGDAdversarialTrainer:
def__init__(self, model, attacker, lr=1e-3):
self.model = model
self.attacker = attacker
self.optimizer = torch.optim.Adam(model.parameters(), lr=lr)
deftrain_step(self, x, y):
# 1. 生成对抗样本
x_adv = self.attacker.generate(self.model, x, y)
# 2. 在对抗样本上计算损失
logits = self.model(x_adv)
loss = nn.functional.cross_entropy(logits, y)
# 3. 更新
self.optimizer.zero_grad()
loss.backward()
self.optimizer.step()
return loss.item()2.2 训练效率优化
PGD对抗训练的每步需K次前向+反向,开销是标准训练的K+1倍。优化策略:
classEfficientAdvTrainer:
def__init__(self, model, eps, alpha, steps_schedule=None):
self.model = model
self.eps = eps
self.alpha = alpha
# 训练初期少步PGD,后期多步
self.steps_schedule = steps_schedule or {0: 2, 50: 5, 100: 10}
defget_steps(self, epoch):
for start, steps in sorted(self.steps_schedule.items(), reverse=True):
if epoch >= start:
return steps
return2
deftrain_step(self, x, y, epoch):
steps = self.get_steps(epoch)
# Free Adv Training: 复用前一次的梯度做下一步扰动
x_adv = x.clone()
for _ in range(steps):
x_adv.requires_grad = True
loss = nn.functional.cross_entropy(self.model(x_adv), y)
loss.backward()
x_adv = x_adv + self.alpha * x_adv.grad.sign()
x_adv = torch.clamp(x_adv, x - self.eps, x + self.eps).detach()
# 最终loss
loss = nn.functional.cross_entropy(self.model(x_adv), y)
return loss2.3 鲁棒性-准确性权衡调参
defrobustness_accuracy_tradeoff(model_factory, data, epsilons):
results = []
for eps in epsilons:
model = model_factory()
trainer = PGDAdversarialTrainer(model, PGDAttack(eps, eps/4, 10))
trainer.train(data, epochs=100)
clean_acc = evaluate(model, data.test)
robust_acc = evaluate_robust(model, data.test, PGDAttack(eps, eps/4, 20))
results.append({"eps": eps, "clean_acc": clean_acc, "robust_acc": robust_acc})
return results
三、认证鲁棒性工具
经验鲁棒性(对抗训练)只对已知攻击类有效,认证鲁棒性提供对任意攻击的保证。
3.1 Randomized Smoothing
classRandomizedSmoothing:
def__init__(self, base_classifier, sigma, n_samples=1000):
self.base = base_classifier
self.sigma = sigma
self.n_samples = n_samples
defpredict(self, x):
"""平滑分类器的预测"""
counts = np.zeros(self.n_classes)
for _ in range(self.n_samples):
noise = torch.randn_like(x) * self.sigma
pred = self.base(x + noise).argmax()
counts[pred] += 1
return counts.argmax()
defcertify(self, x, alpha=0.001):
"""认证x的鲁棒半径"""
counts = self._count_predictions(x)
top_class = counts.argmax()
p_A = counts[top_class] / self.n_samples
# 二项分布置信下界
p_A_lower = self._binom_lower(counts[top_class], self.n_samples, alpha)
if p_A_lower <= 0.5:
return0.0# 无法认证
# 认证半径
return self.sigma * (Phi_inv(p_A_lower) - Phi_inv(0.5))3.2 Interval Bound Propagation (IBP)
classIBPClassifier:
def__init__(self, model, eps):
self.model = model
self.eps = eps
defbound_forward(self, x_l, x_u):
"""逐层传播区间界"""
for layer in self.model.layers:
x_l, x_u = self._propagate(layer, x_l, x_u)
return x_l, x_u
defcertified_predict(self, x):
x_l = x - self.eps
x_u = x + self.eps
out_l, out_u = self.bound_forward(x_l, x_u)
# 若某类的下界都大于其他类的上界,则认证为该类
for c in range(self.n_classes):
if all(out_l[c] > out_u[o] for o in range(self.n_classes) if o != c):
return c
returnNone# 无法认证3.3 性能优化
认证方法计算开销大,工程优化:
Randomized Smoothing用并行批采样(一次前向处理所有噪声样本)。
IBP用混合精度训练加速区间运算。
对低风险输入跳过认证(先用经验攻击评估,无法攻破的才做认证)。
四、物理世界攻击工程
物理世界对抗样本需在物理约束下优化:打印损失、视角变化、光照变化、距离变化。
4.1 物理约束下的对抗优化
classPhysicalAdvAttack:
def__init__(self, model, transforms):