PyTorch深度學習框架60天進階學習計劃 - 第59天模型魯棒性(一):對抗樣本生成機理與PGD攻擊詳解

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_iter7-20計算成本vs攻擊效果10步通常足夠
random_startTrue避免局部最優強烈推薦開啟

數學直覺:為什么PGD比FGSM更強?

想象你要爬一座山到達山頂(最大化損失函數):

  1. FGSM方法:像是用大炮直接轟向山頂,雖然力量大但可能偏離目標
  2. 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. 常見問題診斷表

問題現象可能原因解決方案
攻擊成功率低步長太小、迭代次數不夠增加alphanum_iter
擾動過于明顯epsilon設置過大降低epsilon
攻擊效果不穩定沒有隨機初始化設置random_start=True
內存占用過高batch size過大減小batch size或使用梯度累積
攻擊速度慢模型過大、迭代次數過多使用混合精度或減少迭代次數

2. 優化建議

性能優化技巧

  1. 混合精度訓練:使用torch.cuda.amp.autocast()加速攻擊
  2. 批處理優化:合理設置batch size平衡內存和速度
  3. 早停策略:當攻擊成功時提前終止迭代

魯棒性測試建議

  1. 多epsilon測試:測試不同強度的攻擊
  2. 交叉模型驗證:在不同模型上驗證攻擊的可傳遞性
  3. 真實場景測試:考慮JPEG壓縮、圖像縮放等現實因素

怎么樣今天的內容還滿意嗎?再次感謝朋友們的觀看,關注GZH:凡人的AI工具箱,回復666,送您價值199的AI大禮包。最后,祝您早日實現財務自由,還請給個贊,謝謝!

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/88097.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/88097.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/88097.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

kibana和elasticsearch安裝

1、elasticsearch 6.8.23 安裝包下載地址: Elasticsearch 6.8.23 | Elastic 通過網盤分享的文件:elasticsearch-6.8.23.zip 鏈接: https://pan.baidu.com/s/1D2SrJ8nVBlqC1QNswmMJXg?pwd1234 提取碼: 1234 2、kibana 6.8.23 安裝包下載地址&#xff…

vue3 el-table row-class-name 行字體顏色失效

在使用 Vue 3 中的 el-table 組件時,如果你遇到了 row-class-name 屬性設置的行顏色失效,并被 el-table 的默認樣式覆蓋的問題,通常是因為 CSS 優先級或者樣式沖突導致的。這里有幾個方法可以幫助你解決這個問題: 1. 增加 CSS 優…

【跨界新視野】信號處理遇上VR/AR:下一代沉浸體驗的核心技術與您的發表藍海

導語: 元宇宙概念雖經歷起伏,但其底層支撐技術——信號處理(Signal Processing)與虛擬/增強現實(VR/AR) 的融合創新正蓬勃發展。從高保真音效定位、腦機接口信號解析,到實時三維重建與交互渲染&…

VMware 2025安裝教程(附安裝包)VMware 2025下載詳細安裝圖文教程

文章目錄 引言第A部分:vmware虛擬機安裝包的獲取與準備第1步:下載VMware虛擬機安裝程序 第B部分:VMware虛擬機安裝步驟第3步:啟動安裝向導第4步:同意軟件許可協議第5步:設定程序安裝路徑第6步:配…

wsl2 用橋接方式連網

安裝 Hyper-V windows 家庭版怎么安裝 Hyper-V-CSDN博客 用管理員打開 PowerShell 執行 Get-NetAdapter 出系統所有的網卡,記住想要橋接的網卡名稱 無線網名稱一般為 WLAN,有線網名稱一般為 以太網,我的是 以太網 2 執行 Get-VMSwitch 查…

<tauri><threejs><rust><GUI>基于tauri和threejs,實現一個3D圖形瀏覽程序

前言 本專欄是基于rust和tauri,由于tauri是前、后端結合的GUI框架,既可以直接生成包含前端代碼的文件,也可以在已有的前端項目上集成tauri框架,將前端頁面化為桌面GUI。 發文平臺 CSDN 環境配置 系統:windows 10 …

C++基礎之指針

文章目錄 指針介紹 C指針的定義與用法指針的定義指針的基本操作指針的常見用法1. 動態內存分配2. 指針與數組3. 指針作為函數參數(傳址調用)4. 函數返回指針 特殊指針類型智能指針(C11起)2.入門代碼3.總結 指針介紹 C指針的定義與…

基于存儲過程的MySQL自動化DDL同步系統設計

在現代SaaS與微服務架構中,數據庫結構的自動化管理成為保障系統迭代效率與數據一致性的關鍵一環。本文將圍繞如何通過 MySQL 存儲過程構建一個自動建表、字段同步、索引維護、錯誤日志記錄于一體的 DDL 自動同步系統,提供一套完整的工程化實現方案。 一…

【cmake學習】添加庫文件

文章目錄 目的一、原理二、步驟1.修改CMakeList2.main函數如下3.編譯運行 目的 上一篇 學習了使用cmake 構建多源文件工程在項目開發工程中,一般都會生成庫文件或者調用其它的一些庫文件,所以我們要學習一下簡單生成和使用庫文件這里主要介紹 add_libra…

Docker容器化部署實戰:Spring Boot + MySQL + Nginx 一鍵部署完整指南

?? 前言 容器化技術已經成為現代軟件部署的標準實踐。作為一名DevOps工程師,我在過去幾年中參與了數十個項目的容器化改造,深刻體會到Docker在提升部署效率、環境一致性和運維便利性方面的巨大價值。 今天我將通過一個完整的實戰案例,詳細展示如何使用Docker部署一個包含…

分布式選舉算法<一> Bully算法

分布式選舉算法詳解:Bully算法 引言 在分布式系統中,節點故障是不可避免的。當主節點(Leader)發生故障時,系統需要快速選舉出新的主節點來保證服務的連續性。Bully算法是一種經典的分布式選舉算法,以其簡…

高效調試 AI 大模型 API:用 Apipost 實現 SSE 流式解析與可視化

借助 AI 大模型的實時接口(如 OpenAI GPT 或其他第三方模型 API),開發者可以通過 SSE(Server-Sent Events)流式處理數據,實時獲取模型的逐步輸出。這一技術已廣泛應用于實時問答、代碼生成等領域。本文將基…

【網絡產品經營】園區網絡

園區網絡的產品經營邏輯發生顯著變化,從傳統的“連接功能”導向轉向“業務體驗驅動”,并結合行業場景化需求、技術架構革新及智能化能力提升,形成多維度的產品策略升級。 一、技術架構變革:從多層復雜到極簡全光 傳統架構的瓶頸與…

EasyExcel 4.X 讀寫數據

文章目錄 EasyExcel與SpringBoot集成讀數據讀取數據的流程定義實體類簡單讀取自定義監聽器 讀取指定sheet和所有sheet多行頭讀取數據格式轉換列表數據實體類自定義轉換器自定義監聽器數據讀取 寫數據簡單數據寫出存儲到磁盤返回前端下載 寫出指定列寬,和數值精度丟失…

JVM內存管理<一>:Java內存異常問題排查

一、 內存溢出問題的排查 1. 使用工具 - jdk自帶 jmapvisualvm 2. 流程 堆轉儲: (1) 方法一:程序運行時,采用:jmap -dump:formatb,filed:\\data\\xxlJob.hprof 23300 進行堆文件的轉儲 (2) 方法二:在內存溢出的時候…

Android中Glide.with().load().into() 應付面試源碼解析

1. with(this):生命周期綁定 Glide.with(Activity/Fragment/Context) 核心機制:創建與 UI 生命周期綁定的 RequestManager 底層實現: 通過 RequestManagerRetriever 獲取單例 非 Application 上下文: 向 Activity/Fragment 添加…

#### es相關內容的索引 ####

倒排索引 結構 #### es倒排索引的結構 ####-CSDN博客 向量索引 結構應用 #### es向量檢索 的 結構及應用_es 向量 文本檢索-CSDN博客 ann算法 ann算法的種類有哪些,之間的區別,各自的適用場景-CSDN博客 地理信息索引 es地理信息索引的類型以及geo_po…

小飛電視:智能電視與移動設備的娛樂新選擇

在數字娛樂時代,人們對于影視內容的需求日益增長,不僅追求豐富多樣的節目選擇,還希望獲得便捷、個性化的觀看體驗。小飛電視正是這樣一款專為智能電視和移動設備設計的視頻娛樂應用,它憑借海量的影視資源、高清流暢的播放效果以及…

刪除node并且重裝然后重裝vue

參考第一篇文章 node.js卸載與安裝超詳細教程_node卸載重裝-CSDN博客 第二篇文章安裝vue Vue安裝與配置教程(非常詳細)_安裝vue-CSDN博客

基于YOLOv10算法的交通信號燈檢測與識別

目錄 一.🦁 寫在前面1.1 實現模塊劃分1.2 優化與實時性支持 二.🦁 相關技術與理論基礎2.1 各版本yolo對比2.2 YOLOv10網絡結構 三.🦁 結果分析3.1 訓練損失與驗證損失分析3.2 精確率(Precision)、召回率(Re…