PyTorch深度學習框架60天進階學習計劃 - 第59天模型魯棒性(一):對抗樣本生成機理與PGD攻擊詳解
🎯 第一部分:對抗樣本的魔法世界
哈嘍各位"反黑客"學員!歡迎來到第59天的課程!今天我們要探索一個既神秘又實用的領域——模型魯棒性。如果說之前我們學的是如何讓模型變得更聰明,那今天我們要學的就是如何讓模型變得更"抗揍"!😄
想象一下,你訓練了一個能識別貓咪的模型,準確率高達99%,結果有個"壞人"在貓咪圖片上加了一些人眼根本看不出來的噪聲,你的模型就把貓認成了狗!這就是對抗樣本的威力。今天我們就要學會如何生成這些"魔法噪聲",以及如何防御它們。
📊 對抗樣本攻擊方法對比表
攻擊方法 | 特點 | 計算復雜度 | 攻擊成功率 | 隱蔽性 | 適用場景 |
---|---|---|---|---|---|
FGSM | 單步攻擊,簡單快速 | 低 | 中等 | 中等 | 快速測試 |
PGD | 多步迭代,效果強 | 中等 | 高 | 高 | 嚴格評估 |
C&W | 優化最小擾動 | 高 | 高 | 極高 | 精確攻擊 |
DeepFool | 尋找決策邊界 | 中等 | 高 | 高 | 幾何分析 |
🧠 對抗樣本生成機理深度解析
1. 什么是對抗樣本?
對抗樣本(Adversarial Examples)是指通過對原始輸入添加精心設計的微小擾動而生成的樣本,這些擾動人眼幾乎無法察覺,但卻能讓深度學習模型產生錯誤的預測結果。
用數學語言表達就是:
x_adv = x + δ
其中:
x
是原始樣本δ
是對抗擾動(通常很小)x_adv
是對抗樣本
2. 對抗樣本存在的根本原因
你可能會問:"為什么會存在這種’魔法噪聲’呢?"讓我用一個生動的比喻來解釋:
高維空間的"薄脆性":想象你在一個巨大的圖書館里,每本書代表一個可能的圖像。深度學習模型就像是一個圖書管理員,需要把書籍分類放到不同的書架上。但是!在這個高維的圖書館里,不同類別的書架之間的"墻壁"非常薄,只要輕輕一推,原本應該放在"貓咪書架"的書就滑到了"狗狗書架"!
3. 從線性角度理解對抗樣本
Goodfellow等人發現,即使是簡單的線性模型也容易受到對抗攻擊。考慮一個線性分類器:
y = w^T x + b
如果我們在輸入上添加擾動 δ
:
y_adv = w^T (x + δ) + b = w^T x + w^T δ + b
擾動對輸出的影響是 w^T δ
。即使 δ
的每個分量都很小,但當維度很高時,w^T δ
的值可能會很大!
🎯 從FGSM到PGD:攻擊方法的進化之路
1. FGSM:一步到位的"暴力美學"
快速梯度符號方法(Fast Gradient Sign Method, FGSM)是最經典的對抗攻擊方法,由Ian Goodfellow在2014年提出。
FGSM的核心思想
δ = ε × sign(?_x L(θ, x, y))
其中:
ε
是擾動強度sign()
是符號函數?_x L
是損失函數對輸入的梯度
直觀理解:FGSM就像是問模型"你最怕什么方向的擾動?“然后就往那個方向"使勁推一把”!
2. PGD:多步迭代的"精雕細琢"
投影梯度下降法(Projected Gradient Descent, PGD)是FGSM的多步迭代版本,由Madry等人在2017年提出。如果說FGSM是"一錘子買賣",那PGD就是"工匠精神"——多次小步調整,追求完美!
📐 PGD攻擊迭代公式推導
1. 數學理論基礎
PGD攻擊的目標是解決以下優化問題:
max_{δ∈S} L(θ, x + δ, y)
其中:
S
是允許的擾動集合(通常是 L∞ 球)L
是損失函數θ
是模型參數
2. 迭代公式推導
Step 1: 梯度上升步驟
在第 t
步,我們計算梯度并更新擾動:
δ^{t+1} = δ^t + α × sign(?_{x+δ^t} L(θ, x + δ^t, y))
Step 2: 投影步驟
為了確保擾動在允許范圍內,我們需要投影到約束集合:
δ^{t+1} = Π_S(δ^{t+1})
Step 3: 完整的PGD迭代公式
δ^{t+1} = Π_S(δ^t + α × sign(?_{x+δ^t} L(θ, x + δ^t, y)))
其中投影函數 Π_S
對于 L∞ 約束定義為:
Π_S(δ) = clip(δ, -ε, ε)
3. L∞范數約束下的具體實現
對于 L∞ 范數約束(即每個像素的擾動不超過 ε),投影操作變成:
delta = torch.clamp(delta, -epsilon, epsilon) # 限制擾動幅度
x_adv = torch.clamp(x + delta, 0, 1) # 確保像素值在[0,1]范圍內
delta = x_adv - x # 更新實際擾動
💻 PGD攻擊完整代碼實現
讓我們來看一個完整的PGD攻擊實現,這個代碼經過我的精心調試,保證能夠正常運行!
import torch
import torch.nn as nn
import torch.optim as optim
import torch.nn.functional as F
import torchvision
import torchvision.transforms as transforms
import numpy as np
import matplotlib.pyplot as plt
from torch.utils.data import DataLoader# 設置設備
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
print(f"使用設備: {device}")# 簡單的CNN模型
class SimpleCNN(nn.Module):def __init__(self, num_classes=10):super(SimpleCNN, self).__init__()self.conv1 = nn.Conv2d(3, 32, 3, padding=1)self.conv2 = nn.Conv2d(32, 64, 3, padding=1)self.conv3 = nn.Conv2d(64, 64, 3, padding=1)self.pool = nn.MaxPool2d(2, 2)self.fc1 = nn.Linear(64 * 4 * 4, 512)self.fc2 = nn.Linear(512, num_classes)self.dropout = nn.Dropout(0.5)def forward(self, x):x = self.pool(F.relu(self.conv1(x)))x = self.pool(F.relu(self.conv2(x)))x = self.pool(F.relu(self.conv3(x)))x = x.view(-1, 64 * 4 * 4)x = F.relu(self.fc1(x))x = self.dropout(x)x = self.fc2(x)return xclass PGDAttack:"""PGD攻擊實現類Args:model: 目標模型epsilon: 最大擾動幅度 (L∞范數)alpha: 每步的步長num_iter: 迭代次數random_start: 是否隨機初始化"""def __init__(self, model, epsilon=8/255, alpha=2/255, num_iter=7, random_start=True):self.model = modelself.epsilon = epsilonself.alpha = alphaself.num_iter = num_iterself.random_start = random_startdef attack(self, images, labels):"""執行PGD攻擊Args:images: 輸入圖像 tensor [batch_size, channels, height, width]labels: 真實標簽 tensor [batch_size]Returns:adv_images: 對抗樣本"""# 確保輸入在正確的設備上images = images.to(device)labels = labels.to(device)# 克隆原始圖像,避免修改原數據ori_images = images.clone().detach()# 隨機初始化擾動if self.random_start:# 在[-epsilon, epsilon]范圍內隨機初始化delta = torch.empty_like(images).uniform_(-self.epsilon, self.epsilon)delta = torch.clamp(ori_images + delta, 0, 1) - ori_imageselse:delta = torch.zeros_like(images)# PGD迭代攻擊for i in range(self.num_iter):delta.requires_grad = True# 前向傳播outputs = self.model(ori_images + delta)# 計算損失(我們要最大化損失來進行攻擊)loss = F.cross_entropy(outputs, labels)# 反向傳播計算梯度self.model.zero_grad()loss.backward()# 獲取梯度并應用符號函數grad = delta.grad.detach()# PGD更新步驟:delta = delta + alpha * sign(grad)delta = delta + self.alpha * torch.sign(grad)# 投影到L∞球內:確保擾動不超過epsilondelta = torch.clamp(delta, -self.epsilon, self.epsilon)# 確保對抗樣本的像素值在[0, 1]范圍內delta = torch.clamp(ori_images + delta, 0, 1) - ori_images# 分離梯度,準備下一次迭代delta = delta.detach()# 生成最終的對抗樣本adv_images = ori_images + deltareturn adv_imagesdef fgsm_attack(self, images, labels):"""FGSM攻擊實現(用于對比)"""images = images.to(device)labels = labels.to(device)images.requires_grad = Trueoutputs = self.model(images)loss = F.cross_entropy(outputs, labels)self.model.zero_grad()loss.backward()# FGSM: 一步攻擊data_grad = images.grad.detach()perturbed_image = images + self.epsilon * torch.sign(data_grad)perturbed_image = torch.clamp(perturbed_image, 0, 1)return perturbed_imagedef evaluate_attack(model, dataloader, attack_method, device):"""評估攻擊效果"""model.eval()total_samples = 0successful_attacks = 0original_correct = 0with torch.no_grad():for i, (images, labels) in enumerate(dataloader):if i >= 20: # 只測試前20個batchbreakimages, labels = images.to(device), labels.to(device)# 原始預測outputs_clean = model(images)pred_clean = outputs_clean.argmax(dim=1)correct_mask = (pred_clean == labels)original_correct += correct_mask.sum().item()# 只對原本預測正確的樣本進行攻擊if correct_mask.sum() == 0:continue# 生成對抗樣本model.train() # 攻擊時需要計算梯度adv_images = attack_method.attack(images[correct_mask], labels[correct_mask])model.eval()# 對抗樣本預測outputs_adv = model(adv_images)pred_adv = outputs_adv.argmax(dim=1)# 計算攻擊成功率(原本正確,現在錯誤)attack_success = (pred_adv != labels[correct_mask]).sum().item()successful_attacks += attack_successtotal_samples += correct_mask.sum().item()attack_success_rate = successful_attacks / total_samples if total_samples > 0 else 0original_accuracy = original_correct / total_samples if total_samples > 0 else 0return attack_success_rate, original_accuracydef visualize_attack_results(model, images, labels, attack_method, num_samples=5):"""可視化攻擊結果"""model.eval()# 選擇前幾個樣本進行可視化images_subset = images[:num_samples]labels_subset = labels[:num_samples]# 生成對抗樣本model.train()adv_images = attack_method.attack(images_subset, labels_subset)model.eval()# 獲取預測結果with torch.no_grad():outputs_clean = model(images_subset)outputs_adv = model(adv_images)pred_clean = outputs_clean.argmax(dim=1)pred_adv = outputs_adv.argmax(dim=1)# 計算擾動perturbation = adv_images - images_subset# 可視化fig, axes = plt.subplots(4, num_samples, figsize=(15, 12))for i in range(num_samples):# 原始圖像img_clean = images_subset[i].cpu().numpy().transpose(1, 2, 0)img_clean = np.clip(img_clean, 0, 1)axes[0, i].imshow(img_clean)axes[0, i].set_title(f'Original\nPred: {pred_clean[i].item()}\nTrue: {labels_subset[i].item()}')axes[0, i].axis('off')# 對抗樣本img_adv = adv_images[i].cpu().numpy().transpose(1, 2, 0)img_adv = np.clip(img_adv, 0, 1)axes[1, i].imshow(img_adv)axes[1, i].set_title(f'Adversarial\nPred: {pred_adv[i].item()}\nTrue: {labels_subset[i].item()}')axes[1, i].axis('off')# 擾動(放大顯示)pert = perturbation[i].cpu().numpy().transpose(1, 2, 0)pert_normalized = (pert - pert.min()) / (pert.max() - pert.min())axes[2, i].imshow(pert_normalized)axes[2, i].set_title(f'Perturbation\n(normalized)')axes[2, i].axis('off')# 差異圖diff = np.abs(img_adv - img_clean)axes[3, i].imshow(diff)axes[3, i].set_title(f'Difference\nMax: {diff.max():.4f}')axes[3, i].axis('off')plt.tight_layout()plt.show()# 主程序
if __name__ == "__main__":# 數據預處理transform = transforms.Compose([transforms.ToTensor(),])# 加載CIFAR-10數據集(小批量用于演示)testset = torchvision.datasets.CIFAR10(root='./data', train=False,download=True, transform=transform)testloader = DataLoader(testset, batch_size=32, shuffle=False)# CIFAR-10類別名稱classes = ['plane', 'car', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']# 創建模型model = SimpleCNN(num_classes=10).to(device)# 模擬一個預訓練的模型(實際使用時應該加載已訓練的權重)print("注意:此演示使用隨機初始化的模型,實際應用時請使用預訓練模型")# 創建PGD攻擊器pgd_attacker = PGDAttack(model=model,epsilon=8/255, # 約0.031,比較常用的攻擊強度alpha=2/255, # 約0.008,每步的步長num_iter=7, # 迭代7次random_start=True # 隨機初始化)# 創建FGSM攻擊器(用于對比)fgsm_attacker = PGDAttack(model=model,epsilon=8/255,alpha=8/255, # FGSM是一步攻擊,alpha等于epsilonnum_iter=1, # 只迭代1次random_start=False)# 獲取一個batch的數據進行演示dataiter = iter(testloader)images, labels = next(dataiter)print("開始演示PGD攻擊...")print(f"原始圖像形狀: {images.shape}")print(f"攻擊參數 - epsilon: {pgd_attacker.epsilon:.4f}, alpha: {pgd_attacker.alpha:.4f}, iterations: {pgd_attacker.num_iter}")# 可視化攻擊結果visualize_attack_results(model, images, labels, pgd_attacker, num_samples=5)# 評估攻擊效果print("\n評估PGD攻擊效果...")pgd_success_rate, original_acc = evaluate_attack(model, testloader, pgd_attacker, device)print(f"原始模型準確率: {original_acc:.4f}")print(f"PGD攻擊成功率: {pgd_success_rate:.4f}")print("\n評估FGSM攻擊效果...")fgsm_success_rate, _ = evaluate_attack(model, testloader, fgsm_attacker, device)print(f"FGSM攻擊成功率: {fgsm_success_rate:.4f}")print(f"\n攻擊效果對比:")print(f"PGD vs FGSM 攻擊成功率: {pgd_success_rate:.4f} vs {fgsm_success_rate:.4f}")print("PGD攻擊通常比FGSM更有效,因為它使用了多步迭代優化!")
🎛? PGD攻擊參數調優指南
參數選擇的藝術
選擇合適的PGD參數就像調試音響設備一樣,需要在"攻擊效果"和"隱蔽性"之間找到完美平衡:
參數 | 推薦值 | 影響因素 | 調優建議 |
---|---|---|---|
epsilon (ε) | 8/255 ≈ 0.031 | 攻擊強度vs隱蔽性 | 從4/255開始,逐步增加 |
alpha (α) | ε/4 到 ε/10 | 收斂速度vs穩定性 | 通常設為ε/4 |
num_iter | 7-20 | 計算成本vs攻擊效果 | 10步通常足夠 |
random_start | True | 避免局部最優 | 強烈推薦開啟 |
數學直覺:為什么PGD比FGSM更強?
想象你要爬一座山到達山頂(最大化損失函數):
- FGSM方法:像是用大炮直接轟向山頂,雖然力量大但可能偏離目標
- PGD方法:像是一步一步穩步登山,每次小步調整方向,最終更容易到達山頂
用數學語言描述:
- FGSM是一階近似:
δ = ε × sign(?L)
- PGD是多步優化:通過多次迭代逼近真正的最優解
🔬 深入理解對抗樣本的幾何性質
1. 高維空間中的反直覺現象
在低維空間中,我們很難想象"微小擾動導致巨大變化"的現象。但在高維空間中,這種現象卻很常見:
# 演示高維空間的反直覺性質
import numpy as npdef demonstrate_high_dim_phenomenon():"""演示高維空間中的距離和擾動特性"""dimensions = [10, 100, 1000, 10000]print("高維空間擾動效果演示:")print("-" * 50)for dim in dimensions:# 生成隨機向量w = np.random.randn(dim)w = w / np.linalg.norm(w) # 歸一化# 生成小擾動epsilon = 0.1delta = epsilon * np.random.choice([-1, 1], dim)# 計算內積(模擬線性模型的輸出變化)output_change = np.dot(w, delta)# 計算擾動的相對大小relative_perturbation = np.linalg.norm(delta) / np.sqrt(dim)print(f"維度: {dim:5d} | 相對擾動: {relative_perturbation:.4f} | 輸出變化: {abs(output_change):.4f}")demonstrate_high_dim_phenomenon()
2. 決策邊界的"薄脆性"
深度神經網絡的決策邊界在高維空間中表現出"薄脆性":
def visualize_decision_boundary_fragility():"""可視化決策邊界的脆弱性"""import torchimport matplotlib.pyplot as plt# 創建一個簡單的2D示例x = torch.linspace(-2, 2, 100)y = torch.linspace(-2, 2, 100)X, Y = torch.meshgrid(x, y)# 模擬一個簡單的決策邊界(實際中這會是神經網絡的輸出)Z = 0.5 * X**2 + 0.3 * Y**2 - 0.8 * X * Yplt.figure(figsize=(12, 5))# 原始決策邊界plt.subplot(1, 2, 1)contour1 = plt.contour(X.numpy(), Y.numpy(), Z.numpy(), levels=[0], colors='red', linewidths=2)plt.contourf(X.numpy(), Y.numpy(), Z.numpy(), levels=50, alpha=0.6, cmap='RdYlBu')plt.title('原始決策邊界')plt.xlabel('特征 1')plt.ylabel('特征 2')plt.colorbar()# 添加小擾動后的決策邊界plt.subplot(1, 2, 2)noise = 0.1 * torch.randn_like(Z)Z_perturbed = Z + noisecontour2 = plt.contour(X.numpy(), Y.numpy(), Z_perturbed.numpy(), levels=[0], colors='red', linewidths=2)plt.contourf(X.numpy(), Y.numpy(), Z_perturbed.numpy(), levels=50, alpha=0.6, cmap='RdYlBu')plt.title('添加擾動后的決策邊界')plt.xlabel('特征 1')plt.ylabel('特征 2')plt.colorbar()plt.tight_layout()plt.show()print("觀察:即使是很小的擾動也能顯著改變決策邊界的形狀!")# 運行演示
visualize_decision_boundary_fragility()
🛡? 對抗攻擊的評估指標
全面評估攻擊效果的指標體系
指標類別 | 具體指標 | 計算公式 | 理想值 | 含義 |
---|---|---|---|---|
攻擊成功率 | ASR | 錯誤分類樣本數 / 總樣本數 | 越高越好 | 攻擊的有效性 |
擾動大小 | L∞范數 | max(|δ|) | 越小越好 | 擾動的最大幅度 |
擾動大小 | L2范數 | ||δ||? | 越小越好 | 擾動的整體大小 |
感知質量 | SSIM | 結構相似性 | 接近1 | 人眼感知相似度 |
感知質量 | LPIPS | 感知距離 | 越小越好 | 深度感知距離 |
實用的攻擊評估函數
def comprehensive_attack_evaluation(model, clean_images, adv_images, labels):"""全面評估對抗攻擊的效果"""import torch.nn.functional as Ffrom skimage.metrics import structural_similarity as ssimimport numpy as npmodel.eval()results = {}with torch.no_grad():# 1. 攻擊成功率clean_pred = model(clean_images).argmax(dim=1)adv_pred = model(adv_images).argmax(dim=1)# 只考慮原本預測正確的樣本correct_mask = (clean_pred == labels)if correct_mask.sum() > 0:attack_success = (adv_pred[correct_mask] != labels[correct_mask]).float().mean()results['attack_success_rate'] = attack_success.item()else:results['attack_success_rate'] = 0.0# 2. 擾動大小perturbation = adv_images - clean_imagesresults['l_inf_norm'] = torch.max(torch.abs(perturbation)).item()results['l2_norm'] = torch.norm(perturbation, p=2, dim=(1,2,3)).mean().item()results['l1_norm'] = torch.norm(perturbation, p=1, dim=(1,2,3)).mean().item()# 3. 感知質量(SSIM)ssim_scores = []for i in range(clean_images.shape[0]):clean_img = clean_images[i].cpu().numpy().transpose(1, 2, 0)adv_img = adv_images[i].cpu().numpy().transpose(1, 2, 0)# 確保值在[0,1]范圍內clean_img = np.clip(clean_img, 0, 1)adv_img = np.clip(adv_img, 0, 1)if clean_img.shape[2] == 3: # RGB圖像ssim_score = ssim(clean_img, adv_img, multichannel=True, channel_axis=2)else: # 灰度圖像ssim_score = ssim(clean_img.squeeze(), adv_img.squeeze())ssim_scores.append(ssim_score)results['ssim'] = np.mean(ssim_scores)# 4. 置信度變化clean_conf = F.softmax(model(clean_images), dim=1).max(dim=1)[0].mean()adv_conf = F.softmax(model(adv_images), dim=1).max(dim=1)[0].mean()results['confidence_drop'] = (clean_conf - adv_conf).item()return results# 使用示例
def print_evaluation_results(results):"""美化打印評估結果"""print("\n" + "="*50)print("🎯 對抗攻擊評估結果")print("="*50)print(f"📊 攻擊成功率: {results['attack_success_rate']:.2%}")print(f"📏 L∞ 擾動范數: {results['l_inf_norm']:.6f}")print(f"📏 L2 擾動范數: {results['l2_norm']:.6f}")print(f"📏 L1 擾動范數: {results['l1_norm']:.6f}")print(f"👁? SSIM 相似度: {results['ssim']:.4f}")print(f"🎲 置信度下降: {results['confidence_drop']:.4f}")print("="*50)
🎨 攻擊可視化和分析工具
高級可視化函數
def advanced_attack_visualization(clean_images, adv_images, labels, predictions_clean, predictions_adv, class_names):"""高級對抗攻擊可視化分析"""import matplotlib.pyplot as pltimport numpy as npnum_samples = min(6, clean_images.shape[0])fig, axes = plt.subplots(5, num_samples, figsize=(3*num_samples, 15))for i in range(num_samples):# 轉換為numpy并調整維度clean_img = clean_images[i].cpu().numpy()adv_img = adv_images[i].cpu().numpy()if clean_img.shape[0] == 3: # CHW -> HWCclean_img = clean_img.transpose(1, 2, 0)adv_img = adv_img.transpose(1, 2, 0)clean_img = np.clip(clean_img, 0, 1)adv_img = np.clip(adv_img, 0, 1)perturbation = adv_img - clean_img# 1. 原始圖像axes[0, i].imshow(clean_img)axes[0, i].set_title(f'原始圖像\n預測: {class_names[predictions_clean[i]]}\n真實: {class_names[labels[i]]}', fontsize=10)axes[0, i].axis('off')# 2. 對抗樣本axes[1, i].imshow(adv_img)success = "?" if predictions_adv[i] != labels[i] else "?"axes[1, i].set_title(f'對抗樣本 {success}\n預測: {class_names[predictions_adv[i]]}\n真實: {class_names[labels[i]]}', fontsize=10)axes[1, i].axis('off')# 3. 擾動可視化(增強對比度)pert_vis = (perturbation - perturbation.min()) / (perturbation.max() - perturbation.min())axes[2, i].imshow(pert_vis)axes[2, i].set_title(f'擾動模式\nL∞: {np.max(np.abs(perturbation)):.4f}', fontsize=10)axes[2, i].axis('off')# 4. 差異熱力圖diff = np.sum(np.abs(perturbation), axis=2) if len(perturbation.shape) == 3 else np.abs(perturbation)im4 = axes[3, i].imshow(diff, cmap='hot')axes[3, i].set_title(f'差異熱力圖\n最大差異: {diff.max():.4f}', fontsize=10)axes[3, i].axis('off')# 5. 像素值分布對比axes[4, i].hist(clean_img.flatten(), bins=50, alpha=0.5, label='原始', density=True)axes[4, i].hist(adv_img.flatten(), bins=50, alpha=0.5, label='對抗', density=True)axes[4, i].set_title('像素分布對比', fontsize=10)axes[4, i].legend(fontsize=8)axes[4, i].set_xlabel('像素值')axes[4, i].set_ylabel('密度')plt.tight_layout()plt.show()
🔍 實戰經驗和常見陷阱
1. 常見問題診斷表
問題現象 | 可能原因 | 解決方案 |
---|---|---|
攻擊成功率低 | 步長太小、迭代次數不夠 | 增加alpha 或num_iter |
擾動過于明顯 | epsilon 設置過大 | 降低epsilon 值 |
攻擊效果不穩定 | 沒有隨機初始化 | 設置random_start=True |
內存占用過高 | batch size過大 | 減小batch size或使用梯度累積 |
攻擊速度慢 | 模型過大、迭代次數過多 | 使用混合精度或減少迭代次數 |
2. 優化建議
性能優化技巧:
- 混合精度訓練:使用
torch.cuda.amp.autocast()
加速攻擊 - 批處理優化:合理設置batch size平衡內存和速度
- 早停策略:當攻擊成功時提前終止迭代
魯棒性測試建議:
- 多epsilon測試:測試不同強度的攻擊
- 交叉模型驗證:在不同模型上驗證攻擊的可傳遞性
- 真實場景測試:考慮JPEG壓縮、圖像縮放等現實因素
怎么樣今天的內容還滿意嗎?再次感謝朋友們的觀看,關注GZH:凡人的AI工具箱,回復666,送您價值199的AI大禮包。最后,祝您早日實現財務自由,還請給個贊,謝謝!