对抗样本攻防的工程化

· 2026-09-08 22:00 · 4 阅读

原创 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, 01).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, 01)
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, 01).detach()
return x_adv

1.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 + suffix

1.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 {0250510010}
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 loss

2.3 鲁棒性-准确性权衡调参

defrobustness_accuracy_tradeoff(model_factory, data, epsilons):
    results = []
for eps in epsilons:
        model = model_factory()
        trainer = PGDAdversarialTrainer(model, PGDAttack(eps, eps/410))
        trainer.train(data, epochs=100)
        clean_acc = evaluate(model, data.test)
        robust_acc = evaluate_robust(model, data.test, PGDAttack(eps, eps/420))
        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):

跳转微信打开