Pytorch | 利用VA-I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击

Pytorch | 利用VA-I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击

  • CIFAR数据集
  • VA-I-FGSM介绍
    • 相关定义
    • 算法流程
  • VAI-FGSM代码实现
    • VAI-FGSM算法实现
    • 攻击效果
  • 代码汇总
    • vaifgsm.py
    • train.py
    • advtest.py

之前已经针对CIFAR10训练了多种分类器:
Pytorch | 从零构建AlexNet对CIFAR10进行分类
Pytorch | 从零构建Vgg对CIFAR10进行分类
Pytorch | 从零构建GoogleNet对CIFAR10进行分类
Pytorch | 从零构建ResNet对CIFAR10进行分类
Pytorch | 从零构建MobileNet对CIFAR10进行分类
Pytorch | 从零构建EfficientNet对CIFAR10进行分类
Pytorch | 从零构建ParNet对CIFAR10进行分类

也实现了一些攻击算法:
Pytorch | 利用FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用BIM/I-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用MI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用NI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用PI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用VMI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用VNI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用EMI-FGSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用AI-FGTM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用I-FGSSM针对CIFAR10上的ResNet分类器进行对抗攻击
Pytorch | 利用SMI-FGRM针对CIFAR10上的ResNet分类器进行对抗攻击

本篇文章我们使用Pytorch实现VA-I-FGSM对CIFAR10上的ResNet分类器进行攻击.

CIFAR数据集

CIFAR-10数据集是由加拿大高级研究所(CIFAR)收集整理的用于图像识别研究的常用数据集,基本信息如下:

  • 数据规模:该数据集包含60,000张彩色图像,分为10个不同的类别,每个类别有6,000张图像。通常将其中50,000张作为训练集,用于模型的训练;10,000张作为测试集,用于评估模型的性能。
  • 图像尺寸:所有图像的尺寸均为32×32像素,这相对较小的尺寸使得模型在处理该数据集时能够相对快速地进行训练和推理,但也增加了图像分类的难度。
  • 类别内容:涵盖了飞机(plane)、汽车(car)、鸟(bird)、猫(cat)、鹿(deer)、狗(dog)、青蛙(frog)、马(horse)、船(ship)、卡车(truck)这10个不同的类别,这些类别都是现实世界中常见的物体,具有一定的代表性。

下面是一些示例样本:
在这里插入图片描述

VA-I-FGSM介绍

VA-I-FGSM(Virtual Step and Auxiliary Gradients Iterative Fast Gradient Sign Method)是一种用于生成对抗样本的算法,旨在提高对抗样本在不同模型之间的转移性。以下是VA-I-FGSM算法的详细介绍:

相关定义

  • 输入与输出:算法的输入包括一个分类器 f f f及其损失函数 J J J、一个良性样本 x x x及其真实标签 y t r u e y^{true} ytrue、标签集合 C C C、迭代次数 T T T、扰动阈值 ϵ \epsilon ϵ、虚拟步长 α \alpha α以及辅助标签的数量 n a u x n_{aux} naux。输出为生成的对抗样本 x a d v x^{adv} xadv
  • 中间变量定义:在算法执行过程中, x t a d v x_{t}^{adv} xtadv表示第 t t t次迭代时的对抗样本,初始化为原始样本 x x x x t + 1 a d v x_{t+1}^{adv} xt+1adv表示第 t + 1 t + 1 t+1次迭代时更新后的对抗样本; x t a d v t m p x_{t}^{adv tmp} xtadvtmp是在计算过程中临时存储的中间变量; y + t r u e y_{+}^{true} y+true表示根据真实标签的损失梯度上升方向更新对抗样本; y − a u x y_{-}^{aux} yaux表示根据辅助标签的损失梯度下降方向更新对抗样本; C a u x C_{aux} Caux表示从标签集合 C C C中随机选择的辅助标签集合,且不包含真实标签 y t r u e y^{true} ytrue

算法流程

  1. 初始化
    • 将对抗样本 x a d v x^{adv} xadv初始化为原始良性样本 x x x,即 x 0 a d v ← x x_{0}^{adv} \leftarrow x x0advx,并设置迭代次数 t ← 0 t \leftarrow 0 t0
  2. 迭代更新:在每次迭代中执行以下操作。
    • 计算基于真实标签的梯度更新:根据当前对抗样本 x t a d v x_{t}^{adv} xtadv和真实标签 y t r u e y^{true} ytrue计算损失函数的梯度 ∇ x J ( x t a d v , y t r u e ) \nabla_{x} J(x_{t}^{adv}, y^{true}) xJ(xtadv,ytrue),然后按照虚拟步长 α \alpha α在梯度方向上更新对抗样本,得到临时变量 x t a d v t m p x_{t}^{adv tmp} xtadvtmp,计算公式为 x t a d v t m p ← x t a d v + α ⋅ s i g n ( ∇ x J ( x t a d v , y t r u e ) ) x_{t}^{adv tmp} \leftarrow x_{t}^{adv}+\alpha \cdot sign(\nabla_{x} J(x_{t}^{adv}, y^{true})) xtadvtmpxtadv+αsign(xJ(xtadv,ytrue))
    • 计算基于辅助标签的梯度更新:从标签集合 C C C中随机选择 n a u x n_{aux} naux个不包含真实标签 y t r u e y^{true} ytrue的辅助标签,组成集合 C a u x C_{aux} Caux。对于每个辅助标签 y a u x ∈ C a u x y^{aux} \in C_{aux} yauxCaux,根据当前对抗样本 x t a d v x_{t}^{adv} xtadv和辅助标签 y a u x y^{aux} yaux计算损失函数的梯度 ∇ x J ( x t a d v , y a u x ) \nabla_{x} J(x_{t}^{adv}, y^{aux}) xJ(xtadv,yaux),然后按照虚拟步长 α \alpha α在梯度的相反方向上更新临时变量 x t a d v t m p x_{t}^{adv tmp} xtadvtmp,计算公式为 x t a d v t m p ← x t a d v t m p − α ⋅ s i g n ( ∇ x J ( x t a d v , y a u x ) ) x_{t}^{adv tmp} \leftarrow x_{t}^{adv tmp}-\alpha \cdot sign(\nabla_{x} J(x_{t}^{adv}, y^{aux})) xtadvtmpxtadvtmpαsign(xJ(xtadv,yaux))
    • 更新对抗样本:将经过上述两步更新后的临时变量 x t a d v t m p x_{t}^{adv tmp} xtadvtmp赋值给下一次迭代的对抗样本 x t + 1 a d v x_{t + 1}^{adv} xt+1adv,即 x t + 1 a d v ← x t a d v t m p x_{t + 1}^{adv} \leftarrow x_{t}^{adv tmp} xt+1advxtadvtmp
    • 迭代次数增加:将迭代次数 t t t增加1,即 t ← t + 1 t \leftarrow t + 1 tt+1
  3. 裁剪最终对抗样本:当迭代次数达到设定的最大值 T T T时,对最终的对抗样本 x T a d v x_{T}^{adv} xTadv进行裁剪操作,使其满足扰动阈值 ϵ \epsilon ϵ的限制,得到最终的对抗样本 x a d v x^{adv} xadv,计算公式为 x a d v ← C l i p x , ϵ { x T a d v } x^{adv} \leftarrow Clip_{x,\epsilon}\{x_{T}^{adv}\} xadvClipx,ϵ{xTadv}

VAI-FGSM代码实现

VAI-FGSM算法实现

import torch
import torch.nn as nndef VA_I_FGSM(model, criterion, original_images, labels, epsilon, num_iterations=10, num_aux_labels=3):"""VA-I-FGSM (Virtual Step and Auxiliary Gradients Iterative Fast Gradient Sign Method)参数:- model: 要攻击的模型- criterion: 损失函数- original_images: 原始图像- labels: 原始图像的标签- epsilon: 最大扰动幅度- num_iterations: 迭代次数- virtual_step_size: 虚拟步长- num_aux_labels: 辅助标签数量"""# 虚拟步长alpha = epsilon / num_iterations    # 复制原始图像作为初始的对抗样本ori_perturbed_images = original_images.clone().detach().requires_grad_(True)perturbed_images = original_images.clone().detach().requires_grad_(True)for _ in range(num_iterations):outputs = model(ori_perturbed_images)loss = criterion(outputs, labels)model.zero_grad()loss.backward()# 计算基于真实标签的梯度main_grad = ori_perturbed_images.grad.data.sign()perturbed_images = perturbed_images + alpha * main_grad# 迭代num_aux_labels次数for _ in range(num_aux_labels):# 每次迭代中,都随机生成张量aux_labels,其与labels尺寸相同aux_labels = torch.randint(low=0, high=10, size=labels.size(), device=original_images.device)# 检查并替换与真实标签相同的辅助标签mask = aux_labels == labelswhile mask.any():aux_labels[mask] = torch.randint(low=0, high=10, size=(mask.sum(),), device=original_images.device)mask = aux_labels == labels# 计算辅助标签的损失outputs = model(ori_perturbed_images)aux_loss = criterion(outputs, aux_labels)model.zero_grad()aux_loss.backward()aux_grad = ori_perturbed_images.grad.data.sign()perturbed_images = perturbed_images - alpha * aux_gradori_perturbed_images = ori_perturbed_images.detach().requires_grad_(True)ori_perturbed_images = ori_perturbed_images.detach().requires_grad_(True)# 确保对抗样本在epsilon范围内perturbed_images = torch.clamp(perturbed_images, original_images - epsilon, original_images + epsilon)return perturbed_images

攻击效果

在这里插入图片描述

代码汇总

vaifgsm.py

import torch
import torch.nn as nndef VA_I_FGSM(model, criterion, original_images, labels, epsilon, num_iterations=10, num_aux_labels=3):"""VA-I-FGSM (Virtual Step and Auxiliary Gradients Iterative Fast Gradient Sign Method)参数:- model: 要攻击的模型- criterion: 损失函数- original_images: 原始图像- labels: 原始图像的标签- epsilon: 最大扰动幅度- num_iterations: 迭代次数- virtual_step_size: 虚拟步长- num_aux_labels: 辅助标签数量"""# 虚拟步长alpha = epsilon / num_iterations    # 复制原始图像作为初始的对抗样本ori_perturbed_images = original_images.clone().detach().requires_grad_(True)perturbed_images = original_images.clone().detach().requires_grad_(True)for _ in range(num_iterations):outputs = model(ori_perturbed_images)loss = criterion(outputs, labels)model.zero_grad()loss.backward()# 计算基于真实标签的梯度main_grad = ori_perturbed_images.grad.data.sign()perturbed_images = perturbed_images + alpha * main_grad# 迭代num_aux_labels次数for _ in range(num_aux_labels):# 每次迭代中,都随机生成张量aux_labels,其与labels尺寸相同aux_labels = torch.randint(low=0, high=10, size=labels.size(), device=original_images.device)# 检查并替换与真实标签相同的辅助标签mask = aux_labels == labelswhile mask.any():aux_labels[mask] = torch.randint(low=0, high=10, size=(mask.sum(),), device=original_images.device)mask = aux_labels == labels# 计算辅助标签的损失outputs = model(ori_perturbed_images)aux_loss = criterion(outputs, aux_labels)model.zero_grad()aux_loss.backward()aux_grad = ori_perturbed_images.grad.data.sign()perturbed_images = perturbed_images - alpha * aux_gradori_perturbed_images = ori_perturbed_images.detach().requires_grad_(True)ori_perturbed_images = ori_perturbed_images.detach().requires_grad_(True)# 确保对抗样本在epsilon范围内perturbed_images = torch.clamp(perturbed_images, original_images - epsilon, original_images + epsilon)return perturbed_images

train.py

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from models import ResNet18# 数据预处理
transform_train = transforms.Compose([transforms.RandomCrop(32, padding=4),transforms.RandomHorizontalFlip(),transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])transform_test = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))
])# 加载Cifar10训练集和测试集
trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=False, transform=transform_train)
trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2)testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=False, transform=transform_test)
testloader = torch.utils.data.DataLoader(testset, batch_size=100, shuffle=False, num_workers=2)# 定义设备(GPU或CPU)
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")# 初始化模型
model = ResNet18(num_classes=10)
model.to(device)# 定义损失函数和优化器
criterion = nn.CrossEntropyLoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.01)if __name__ == "__main__":# 训练模型for epoch in range(10):  # 可以根据实际情况调整训练轮数running_loss = 0.0for i, data in enumerate(trainloader, 0):inputs, labels = data[0].to(device), data[1].to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()if i % 100 == 99:print(f'Epoch {epoch + 1}, Batch {i + 1}: Loss = {running_loss / 100}')running_loss = 0.0torch.save(model.state_dict(), f'weights/epoch_{epoch + 1}.pth')print('Finished Training')

advtest.py

import torch
import torch.nn as nn
import torchvision
import torchvision.transforms as transforms
from models import *
from attacks import *
import ssl
import os
from PIL import Image
import matplotlib.pyplot as pltssl._create_default_https_context = ssl._create_unverified_context# 定义数据预处理操作
transform = transforms.Compose([transforms.ToTensor(),transforms.Normalize((0.491, 0.482, 0.446), (0.247, 0.243, 0.261))])# 加载CIFAR10测试集
testset = torchvision.datasets.CIFAR10(root='./data', train=False,download=False, transform=transform)
testloader = torch.utils.data.DataLoader(testset, batch_size=128,shuffle=False, num_workers=2)# 定义设备(GPU优先,若可用)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")model = ResNet18(num_classes=10).to(device)criterion = nn.CrossEntropyLoss()# 加载模型权重
weights_path = "weights/epoch_10.pth"
model.load_state_dict(torch.load(weights_path, map_location=device))if __name__ == "__main__":# 在测试集上进行FGSM攻击并评估准确率model.eval()  # 设置为评估模式correct = 0total = 0epsilon = 16 / 255  # 可以调整扰动强度for data in testloader:original_images, labels = data[0].to(device), data[1].to(device)original_images.requires_grad = Trueattack_name = 'VA-I-FGSM'if attack_name == 'FGSM':perturbed_images = FGSM(model, criterion, original_images, labels, epsilon)elif attack_name == 'BIM':perturbed_images = BIM(model, criterion, original_images, labels, epsilon)elif attack_name == 'MI-FGSM':perturbed_images = MI_FGSM(model, criterion, original_images, labels, epsilon)elif attack_name == 'NI-FGSM':perturbed_images = NI_FGSM(model, criterion, original_images, labels, epsilon)elif attack_name == 'PI-FGSM':perturbed_images = PI_FGSM(model, criterion, original_images, labels, epsilon)elif attack_name == 'VMI-FGSM':perturbed_images = VMI_FGSM(model, criterion, original_images, labels, epsilon)elif attack_name == 'VNI-FGSM':perturbed_images = VNI_FGSM(model, criterion, original_images, labels, epsilon)elif attack_name == 'EMI-FGSM':perturbed_images = EMI_FGSM(model, criterion, original_images, labels, epsilon)elif attack_name == 'AI-FGTM':perturbed_images = AI_FGTM(model, criterion, original_images, labels, epsilon)elif attack_name == 'I-FGSSM':perturbed_images = I_FGSSM(model, criterion, original_images, labels, epsilon)elif attack_name == 'SMI-FGRM':perturbed_images = SMI_FGRM(model, criterion, original_images, labels, epsilon)elif attack_name == 'VA-I-FGSM':perturbed_images = VA_I_FGSM(model, criterion, original_images, labels, epsilon)perturbed_outputs = model(perturbed_images)_, predicted = torch.max(perturbed_outputs.data, 1)total += labels.size(0)correct += (predicted == labels).sum().item()accuracy = 100 * correct / total# Attack Success RateASR = 100 - accuracyprint(f'Load ResNet Model Weight from {weights_path}')print(f'epsilon: {epsilon:.4f}')print(f'ASR of {attack_name} : {ASR :.2f}%')

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/65182.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

WebPack3项目升级webpack5的配置调试记录

文章目录 前言一、webpack3环境1.1、知识点记录1.1.1、配置解释1.1.2、webpack与sass版本对应关系1.1.3、CommonJS与ESModule1.1.4、node版本管理nvm1.1.5、sass-loader、sass与node-sass 1.2、其他1.2.1、.d.ts是什么文件1.2.2、react与types/react版本对应关系1.2.3、webpack…

MySQL 数据”丢失”事件之 binlog 解析应用

事件背景 客户反馈在晚间数据跑批后,查询相关表的数据时,发现该表的部分数据在数据库中不存在 从应用跑批的日志来看,跑批未报错,且可查到日志中明确显示当时那批数据已插入到数据库中 需要帮忙分析这批数据丢失的原因。 备注:考虑信息敏感性,以下分析场景测试环境模拟,相关数据…

微信小程序的轮播图学习报告

微信小程序轮播图学习报告 好久都没分享新内容了,实在惭愧惭愧。今天给大家做一个小程序轮播图的学习报告。 先给大家看一下我的项目状态: 很空昂!像一个正在修行的老道,空的什么也没有。 但是我写了 4 个 view 容器,…

【RAII | 设计模式】C++智能指针,内存管理与设计模式

前言 nav2系列教材,yolov11部署,系统迁移教程我会放到年后一起更新,最近年末手头事情多,还请大家多多谅解。 上一节我们讲述了C移动语义相关的知识,本期我们来看看C中常用的几种智能指针,并看看他们在设计模式中的运…

微软 CEO 萨提亚・纳德拉:回顾过去十年,展望 AI 时代的战略布局

近日,微软 CEO 萨提亚・纳德拉与著名投资人比尔・格里和布拉德・格斯特纳进行了一场深度对话,回顾了过去十年微软的转型历程,并展望了 AI 时代的战略布局。在这次访谈中,纳德拉分享了他在微软的早期经历,包括他加入微软…

【Java-tesseract】OCR图片文本识别

文章目录 一、需求二、概述三、部署安装四、技术细节五、总结 一、需求 场景需求:是对识别常见的PNG,JPEG,TIFF,GIF图片识别,环境为离线内网。组件要求开源免费,并且可以集成Java生成接口服务。 二、概述 我不做选型对比了,我筛选测试了下Tesseract(v…

iOS开发代码块-OC版

iOS开发代码块-OC版 资源分享资源使用详情Xcode自带代码块自定义代码块 资源分享 自提: 通过网盘分享的文件:CodeSnippets 2.zip 链接: https://pan.baidu.com/s/1Yh8q9PbyeNpuYpasG4IiVg?pwddn1i 提取码: dn1i Xcode中的代码片段默认放在下面的目录中…

如何借助边缘智能网关实现厂区粉尘智能监测告警

在诸如木制品加工、纺织品加工、塑料橡胶制品加工等多种工业生产场景中,粉尘问题的隐患和风险不可小觑。如果缺少对生产环境中粉尘的监测和管理,可能发生易燃易爆、环境污染和工人尘肺等生产事故。 针对工业场景中的粉尘状况监测、管理及预警&#xff0c…

McDonald‘s Event-Driven Architecture 麦当劳事件驱动架构

原文链接 1 mcdonalds-technical-blog/ 原文链接 2 mcdonalds-technical-blog/ 麦当劳在异步、事务性和分析性处理用例中使用跨技术栈的事件,包括移动订单进度跟踪和向客户发送营销通信(交易和促销)。 统一事件平台(unified eve…

EasyExcel停更,FastExcel接力

11月6日消息,阿里巴巴旗下的Java Excel工具库EasyExcel近日宣布,将停止更新,未来将逐步进入维护模式,将继续修复Bug,但不再主动新增功能。 EasyExcel以其快速、简洁和解决大文件内存溢出的能力而著称,官方…

HarmonyOS NEXT 实战之元服务:静态多案例效果(一)

背景: 前几篇学习了元服务,后面几期就让我们开发简单的元服务吧,里面丰富的内容大家自己加,本期案例 仅供参考 先上本期效果图 ,里面图片自行替换 效果图1代码案例如下: import { authentication } from…

前端(Ajax)

1.客户端请求 向https://jsonplaceholder.typicode.com/users发送get请求 const xhr new XMLHttpRequest(); console.log(xhr.readyState); xhr.open(‘get’, ‘https://jsonplaceholder.typicode.com/users’) console.log(xhr.readyState); xhr.send(); console.log(xhr.…

java高频面试之SE-05

面试官:java中为什么有多态? 面试官你好!Java 中有多态主要是为了实现灵活性和可扩展性。通过多态,可以用统一的接口处理不同的对象,从而提高代码的可维护性和可复用性。以下是多态的几个关键原因: 1. 代…

DP83848以太网移植流程,可以TCP通信

DP83848-EP 是一款高度可靠、功能丰富的强大器件,包含了增强型 ESD 保护、MII 和 RMII,从而在 MPU 选择方面实现最大的灵活性,所有这些特性都融入于 48 引脚 PQFP 封装中。 DP83848-EP 配备 集成子层以支持 10BASE-T 和 100BASE-TX 以太网协议,这些协议确保了与基于其他标…

波动理论、传输线和S参数网络

波动理论、传输线和S参数网络 传输线 求解传输线方程 对于传输线模型,我们通常用 R L G C RLGC RLGC 来表示: 其中 R R R 可以表示导体损耗,由于电子流经非理想导体而产生的能量损耗。 G G G 表示介质损耗,由于非理想电介质…

基于pytorch的深度学习基础3——模型创建与nn.Module

三 模型创建与nn.Module 3.1 nn.Module 模型构建两要素: 构建子模块——__init()__拼接子模块——forward() 一个module可以有多个module; 一个module相当于一个运算,都必须实现forward函数; 每一个mod…

Android--java实现手机亮度控制

文章目录 1、开发需求2、运行环境3、主要文件4、布局文件信息5、手机界面控制代码6、debug 1、开发需求 需求:开发一个Android apk实现手机亮度控制 2、运行环境 Android studio最新版本 3、主要文件 app\src\main\AndroidManifest.xml app\src\main\res\layou…

Matlab 和 R 语言的数组索引都是从 1 开始,并且是左闭右闭的

文章目录 一、前言二、主要内容三、小结 🍉 CSDN 叶庭云:https://yetingyun.blog.csdn.net/ 一、前言 在早期的计算机科学中,数组索引从 1 开始是很常见的。例如,Fortran 和 Pascal 等编程语言也采用了从 1 开始的索引。 这种索引…

【优选算法】复写零

链接:1089. 复写零 - 力扣(LeetCode) 算法原理: 解法:双指针算法 根据“异地”操作,然后优化成双指针下的“就地”操作 1.先找到最后一个“复写”的数 1.先判断 cur 位置的值 2.决定 dest 向后移动一步或…

鸿蒙之路的坑

1、系统 Windows 10 家庭版不可用模拟器 对应的解决方案【坑】 升级系统版本 直接更改密钥可自动升级系统 密钥找对应系统的(例:windows 10专业版) 升级完之后要激活 坑1、升级完后事先创建好的模拟器还是无法启动 解决:删除模拟…