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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈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…