PGD(projected gradient descent)算法源码解析

2023-11-05 03:12

本文主要是介绍PGD(projected gradient descent)算法源码解析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

论文链接:https://arxiv.org/abs/1706.06083
源码出处:https://github.com/Harry24k/adversarial-attacks-pytorch/tree/master


源码

import torch
import torch.nn as nnfrom ..attack import Attackclass PGD(Attack):r"""PGD in the paper 'Towards Deep Learning Models Resistant to Adversarial Attacks'[https://arxiv.org/abs/1706.06083]Distance Measure : LinfArguments:model (nn.Module): model to attack.eps (float): maximum perturbation. (Default: 8/255)alpha (float): step size. (Default: 2/255)steps (int): number of steps. (Default: 10)random_start (bool): using random initialization of delta. (Default: True)Shape:- images: :math:`(N, C, H, W)` where `N = number of batches`, `C = number of channels`,        `H = height` and `W = width`. It must have a range [0, 1].- labels: :math:`(N)` where each value :math:`y_i` is :math:`0 \leq y_i \leq` `number of labels`.- output: :math:`(N, C, H, W)`.Examples::>>> attack = torchattacks.PGD(model, eps=8/255, alpha=1/255, steps=10, random_start=True)>>> adv_images = attack(images, labels)"""def __init__(self, model, eps=8/255,alpha=2/255, steps=10, random_start=True):super().__init__("PGD", model)self.eps = epsself.alpha = alphaself.steps = stepsself.random_start = random_startself.supported_mode = ['default', 'targeted']def forward(self, images, labels):r"""Overridden."""self._check_inputs(images)images = images.clone().detach().to(self.device)labels = labels.clone().detach().to(self.device)if self.targeted:target_labels = self.get_target_label(images, labels)loss = nn.CrossEntropyLoss()adv_images = images.clone().detach()if self.random_start:# Starting at a uniformly random pointadv_images = adv_images + torch.empty_like(adv_images).uniform_(-self.eps, self.eps)adv_images = torch.clamp(adv_images, min=0, max=1).detach()for _ in range(self.steps):adv_images.requires_grad = Trueoutputs = self.get_logits(adv_images)# Calculate lossif self.targeted:cost = -loss(outputs, target_labels)else:cost = loss(outputs, labels)# Update adversarial imagesgrad = torch.autograd.grad(cost, adv_images,retain_graph=False, create_graph=False)[0]adv_images = adv_images.detach() + self.alpha*grad.sign()delta = torch.clamp(adv_images - images, min=-self.eps, max=self.eps)adv_images = torch.clamp(images + delta, min=0, max=1).detach()return adv_images

解析

PGD算法(projected gradient descent)是在BIM算法的基础上的小改进,二者非常相近,BIM算法的源码解析在上一篇博客中,建议先看上一篇博客理解BIM算法的原理。

具体来说,在BIM算法开始迭代前,就先给图像加上扰动(在 ϵ \epsilon ϵ邻域内均匀分布)。换句话说,也就是图像开始迭代的起点随机,而不是像BIM算法一样从原始图像开始迭代。论文这么做的目的是为了研究从随机的起点开始迭代扰动,损失能够达到的不同的局部最大值的关系。

PGD算法的公式如下所示: X 0 a d v = X + η , X N + 1 a d v = C l i p X , ϵ { X N a d v + α s i g n ( ▽ x J ( X N a d v , y t r u e ) ) } X^{adv}_0=X+\eta,X^{adv}_{N+1}=Clip_{X,\epsilon}\{X^{adv}_N+\alpha sign(\triangledown_{x}J(X^{adv}_N,y_{true}))\} X0adv=X+η,XN+1adv=ClipX,ϵ{XNadv+αsign(xJ(XNadv,ytrue))}其中, η \eta η是一个随机扰动,在 ϵ \epsilon ϵ邻域内均匀分布。

eps:即 ϵ \epsilon ϵ,表示最大扰动。
alpha:即 α \alpha α,表示每次迭代中扰动的增加量(或减少量)。
steps:表示迭代次数。
random_start:迭代的起点是否随机,也就是是否要加随机扰动 η \eta η,若为False,则该算法就和BIM算法相同。
images = images.clone().detach().to(self.device)clone()将图像克隆到一块新的内存区(pytorch默认同样的tensor共享一块内存区);detach()是将克隆的新的tensor从当前计算图中分离下来,作为叶节点,从而可以计算其梯度;to()作用就是将其载入设备。
target_labels = self.get_target_label(images, labels):若是有目标攻击的情况,获取目标标签。目标标签的选取有多种方式,例如可以选择与真实标签相差最大的标签,也可以随机选择除真实标签外的标签。
loss = nn.CrossEntropyLoss():设置损失函数为交叉熵损失。

adv_images = adv_images + torch.empty_like(adv_images).uniform_(-self.eps, self.eps)
adv_images = torch.clamp(adv_images, min=0, max=1).detach()

以上两行代码作用即为添加随机扰动,torch.empty_like(adv_images)会返回一个形状同adv_images的空的Tensor,uniform_(-self.eps, self.eps)将Tensor中的值在 [ − ϵ , ϵ ] [-\epsilon,\epsilon] [ϵ,ϵ]范围内的均匀分布中随机取值。torch.clamp(adv_images, min=0, max=1)会将图像中大于1的值设为1、小于0的值设为0,防止超出范围。
adv_images.requires_grad = True:将requires_grad 参数设置为True,torch就会在图像的计算过程中自动计算计算图,用于反向梯度计算。
outputs = self.get_logits(images):获得图像的在模型中的输出值。
cost = -loss(outputs, target_labels):有目标情况下计算损失。
cost = loss(outputs, labels):无目标情况下计算损失。
grad = torch.autograd.grad(cost, images, retain_graph=False, create_graph=False)[0]costimages求导,得到梯度grad
adv_images = images + self.alpha*grad.sign():根据公式在图像上沿着梯度上升方向以步长为 α \alpha α增加扰动。

delta = torch.clamp(adv_images - images, min=-self.eps, max=self.eps)  # 得到改变量
adv_images = torch.clamp(images + delta, min=0, max=1).detach()  # 防止图像超出有效范围

以上两行代码就是裁剪的过程,同BIM算法中的 C l i p Clip Clip过程,防止图像超出 [ 0 , 1 ] [0,1] [0,1]范围。

这篇关于PGD(projected gradient descent)算法源码解析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/347039

相关文章

深入解析C++ 中std::map内存管理

《深入解析C++中std::map内存管理》文章详解C++std::map内存管理,指出clear()仅删除元素可能不释放底层内存,建议用swap()与空map交换以彻底释放,针对指针类型需手动de... 目录1️、基本清空std::map2️、使用 swap 彻底释放内存3️、map 中存储指针类型的对象

Java Scanner类解析与实战教程

《JavaScanner类解析与实战教程》JavaScanner类(java.util包)是文本输入解析工具,支持基本类型和字符串读取,基于Readable接口与正则分隔符实现,适用于控制台、文件输... 目录一、核心设计与工作原理1.底层依赖2.解析机制A.核心逻辑基于分隔符(delimiter)和模式匹

Java+AI驱动实现PDF文件数据提取与解析

《Java+AI驱动实现PDF文件数据提取与解析》本文将和大家分享一套基于AI的体检报告智能评估方案,详细介绍从PDF上传、内容提取到AI分析、数据存储的全流程自动化实现方法,感兴趣的可以了解下... 目录一、核心流程:从上传到评估的完整链路二、第一步:解析 PDF,提取体检报告内容1. 引入依赖2. 封装

深度解析Python yfinance的核心功能和高级用法

《深度解析Pythonyfinance的核心功能和高级用法》yfinance是一个功能强大且易于使用的Python库,用于从YahooFinance获取金融数据,本教程将深入探讨yfinance的核... 目录yfinance 深度解析教程 (python)1. 简介与安装1.1 什么是 yfinance?

99%的人都选错了! 路由器WiFi双频合一还是分开好的专业解析与适用场景探讨

《99%的人都选错了!路由器WiFi双频合一还是分开好的专业解析与适用场景探讨》关于双频路由器的“双频合一”与“分开使用”两种模式,用户往往存在诸多疑问,本文将从多个维度深入探讨这两种模式的优缺点,... 在如今“没有WiFi就等于与世隔绝”的时代,越来越多家庭、办公室都开始配置双频无线路由器。但你有没有注

Python中的sort()和sorted()用法示例解析

《Python中的sort()和sorted()用法示例解析》本文给大家介绍Python中list.sort()和sorted()的使用区别,详细介绍其参数功能及Timsort排序算法特性,涵盖自适应... 目录一、list.sort()参数说明常用内置函数基本用法示例自定义函数示例lambda表达式示例o

SpringBoot加载profile全面解析

《SpringBoot加载profile全面解析》SpringBoot的Profile机制通过多配置文件和注解实现环境隔离,支持开发、测试、生产等不同环境的灵活配置切换,无需修改代码,关键点包括配置文... 目录题目详细答案什么是 Profile配置 Profile使用application-{profil

MySQL的触发器全解析(创建、查看触发器)

《MySQL的触发器全解析(创建、查看触发器)》MySQL触发器是与表关联的存储程序,当INSERT/UPDATE/DELETE事件发生时自动执行,用于维护数据一致性、日志记录和校验,优点包括自动执行... 目录触发器的概念:创建触www.chinasem.cn发器:查看触发器:查看当前数据库的所有触发器的定

Java中的volatile关键字多方面解析

《Java中的volatile关键字多方面解析》volatile用于保证多线程变量可见性与禁止重排序,适用于状态标志、单例模式等场景,但不保证原子性,相较synchronized更轻量,但需谨慎使用以... 目录1. volatile的作用1.1 保证可见性1.2 禁止指令重排序2. volatile的使用

Python lambda函数(匿名函数)、参数类型与递归全解析

《Pythonlambda函数(匿名函数)、参数类型与递归全解析》本文详解Python中lambda匿名函数、灵活参数类型和递归函数三大进阶特性,分别介绍其定义、应用场景及注意事项,助力编写简洁高效... 目录一、lambda 匿名函数:简洁的单行函数1. lambda 的定义与基本用法2. lambda