Skip to main content

PyTorch 的对抗性攻击

项目描述

对抗性攻击-PyTorch

麻省理工学院许可证 皮皮 最新发布的 文件状态

Torchattacks是一个 PyTorch 库,它提供对抗性攻击以生成对抗性示例。它包含类似于 PyTorch 的界面和功能,使 PyTorch 用户更容易实施对抗性攻击 ( README [KOR] )。

易于实施

import torchattacks
atk = torchattacks.PGD(model, eps=8/255, alpha=2/255, steps=4)
adv_images = atk(images, labels)

易于修改

from torchattacks.attack import Attack
class CustomAttack(Attack):
    def __init__(self, model):
        super().__init__("CustomAttack", model)

    def forward(self, images, labels=None):
        adv_images = # Custom attack method
        return adv_images

有用的功能

atk.set_mode_targeted_least_likely(kth_min)  # Targeted attack
atk.set_return_type(type='int')  # Return values [0, 255]
atk = torchattacks.MultiAttack([atk1, ..., atk99])  # Combine attacks
atk.save(data_loader, save_path=None, verbose=True, return_verbose=False)  # Save adversarial images

快速计算

请参阅性能比较

目录

  1. 要求和安装
  2. 入门
  3. 性能比较
  4. 引文
  5. 贡献
  6. 推荐站点和套餐

要求和安装

:剪贴板:要求

  • PyTorch 版本 >=1.4.0
  • Python 版本 >=3.6

:hammer: 安装

pip install torchattacks

入门

:warning: 注意事项

  • 在用于攻击之前,所有图像都应该使用 transform[to.Tensor()] 缩放到 [0, 1]。为了便于使用对抗性攻击,攻击过程中不包括反向规范化。要应用输入规范化,请向模型添加规范化层。请参考代码nbviewer
  • (N, C)所有模型都应该只返回一个where向量C = number of classes考虑到torchvision.models中的大多数模型返回一个向量(N,C),其中N是输入的数量,C是类的数量,torchattacks也只支持有限的输出形式。请仔细检查模型输出的形状。在模型返回多个输出的情况下,请参考demo
  • torch.backends.cudnn.deterministic = True获得具有固定随机种子的相同对抗样本GPU [讨论]上的浮点张量的某些操作是不确定的。如果您想使用相同的输入获得相同的结果,请运行torch.backends.cudnn.deterministic = True[ref]

:rocket: 演示

给定模型图像标签,对抗性图像可以生成如下:

import torchattacks
atk = torchattacks.PGD(model, eps=8/255, alpha=2/255, steps=4)
adv_images = atk(images, labels)

Torchattacks 支持以下功能:

目标模式

  • 随机目标标签:
# random labels as target labels.
atk.set_mode_targeted_random(n_classses)
  • 最不可能的标签:
# label with the k-th smallest probability used as target labels.
atk.set_mode_targeted_least_likely(kth_min)
  • 通过自定义函数:
# label from mapping function
atk.set_mode_targeted_by_function(target_map_function=lambda images, labels:(labels+1)%10)
  • 返回默认值:
atk.set_mode_default()

返回类型

  • 返回具有整数值 (0-255) 的对抗性图像。
atk.set_return_type(type='int')
  • 返回具有浮点值 (0-1) 的对抗性图像。
atk.set_return_type(type='float')

保存对抗性图像

# Save
atk.save(data_loader, save_path="./data/sample.pt", verbose=True)

# Load
import torch
from torch.utils.data import DataLoader, TensorDataset
adv_images, labels = torch.load("./data/sample.pt")

# If set_return_type was 'int',
# adv_data = TensorDataset(adv_images.float()/255, labels)
# else,
adv_data = TensorDataset(adv_images, labels)
adv_loader = DataLoader(adv_data, batch_size=128, shuffle=False)

攻击期间的训练/评估

# For RNN-based models, we cannot calculate gradients with eval mode.
# Thus, it should be changed to the training mode during the attack.
atk.set_training_mode(model_training=False, batchnorm_training=False, dropout_training=False)

进行一组攻击

  • 强力攻击
atk1 = torchattacks.FGSM(model, eps=8/255)
atk2 = torchattacks.PGD(model, eps=8/255, alpha=2/255, iters=40, random_start=True)
atk = torchattacks.MultiAttack([atk1, atk2])
  • Binary serach for CW
atk1 = torchattacks.CW(model, c=0.1, steps=1000, lr=0.01)
atk2 = torchattacks.CW(model, c=1, steps=1000, lr=0.01)
atk = torchattacks.MultiAttack([atk1, atk2])
  • Random restarts
atk1 = torchattacks.PGD(model, eps=8/255, alpha=2/255, iters=40, random_start=True)
atk2 = torchattacks.PGD(model, eps=8/255, alpha=2/255, iters=40, random_start=True)
atk = torchattacks.MultiAttack([atk1, atk2])

这是火炬攻击的演示。

  • 使用 ImageNet 进行白盒攻击代码nbviewer):使用torchattacks使用ImageNet 数据集制作对抗性示例来欺骗 ResNet-18。
  • 使用 CIFAR10 进行传输攻击代码nbviewer):此演示提供了具有两种不同模型的黑盒攻击示例。首先,使用 CIFAR10 从holdout 模型制作对抗性数据集,并将其保存为torch 数据集。其次,使用对抗性数据集攻击目标模型。
  • 使用 MNIST 进行对抗训练代码nbviewer):此代码显示了如何使用此存储库进行对抗训练。此代码中使用了 MNIST 数据集和自定义模型。使用 PGD 进行对抗训练,然后应用 FGSM 来评估模型。

Torchattacks 还支持与其他攻击包的协作。

傻瓜

https://github.com/bethgelab/foolbox

from torchattacks.attack import Attack
import foolbox as fb

# L2BrendelBethge
class L2BrendelBethge(Attack):
    def __init__(self, model):
        super(L2BrendelBethge, self).__init__("L2BrendelBethge", model)
        self.fmodel = fb.PyTorchModel(self.model, bounds=(0,1), device=self.device)
        self.init_attack = fb.attacks.DatasetAttack()
        self.adversary = fb.attacks.L2BrendelBethgeAttack(init_attack=self.init_attack)
        self._attack_mode = 'only_default'

    def forward(self, images, labels):
        images, labels = images.to(self.device), labels.to(self.device)

        # DatasetAttack
        batch_size = len(images)
        batches = [(images[:batch_size//2], labels[:batch_size//2]),
                   (images[batch_size//2:], labels[batch_size//2:])]
        self.init_attack.feed(model=self.fmodel, inputs=batches[0][0]) # feed 1st batch of inputs
        self.init_attack.feed(model=self.fmodel, inputs=batches[1][0]) # feed 2nd batch of inputs
        criterion = fb.Misclassification(labels)
        init_advs = self.init_attack.run(self.fmodel, images, criterion)

        # L2BrendelBethge
        adv_images = self.adversary.run(self.fmodel, images, labels, starting_points=init_advs)
        return adv_images

atk = L2BrendelBethge(model)
atk.save(data_loader=test_loader, save_path="_temp.pt", verbose=True)

对抗性鲁棒性工具箱 (ART)

https://github.com/IBM/adversarial-robustness-toolbox

import torch.nn as nn
import torch.optim as optim

from torchattacks.attack import Attack

import art.attacks.evasion as evasion
from art.classifiers import PyTorchClassifier

# SaliencyMapMethod (or Jacobian based saliency map attack)
class JSMA(Attack):
    def __init__(self, model, theta=1/255, gamma=0.15, batch_size=128):
        super(JSMA, self).__init__("JSMA", model)
        self.classifier = PyTorchClassifier(
                            model=self.model, clip_values=(0, 1),
                            loss=nn.CrossEntropyLoss(),
                            optimizer=optim.Adam(self.model.parameters(), lr=0.01),
                            input_shape=(1, 28, 28), nb_classes=10)
        self.adversary = evasion.SaliencyMapMethod(classifier=self.classifier,
                                                   theta=theta, gamma=gamma,
                                                   batch_size=batch_size)
        self.target_map_function = lambda labels: (labels+1)%10
        self._attack_mode = 'only_default'

    def forward(self, images, labels):
        adv_images = self.adversary.generate(images, self.target_map_function(labels))
        return torch.tensor(adv_images).to(self.device)

atk = JSMA(model)
atk.save(data_loader=test_loader, save_path="_temp.pt", verbose=True)

:fire: 已实施论文列表

括号中的距离度量。

姓名 评论
FGSM
(林夫)
解释和利用对抗性示例(Goodfellow 等人,2014 年
BIM
(林夫)
物理世界中的对抗性示例(Kurakin 等人,2016 年 基本迭代方法或迭代-FSGM
顺时针
(L2)
评估神经网络的鲁棒性(Carlini 等人,2016 年
RFGSM
(林夫)
集成对抗训练:攻击和防御(Tramèr 等人,2017 年 随机初始化 + FGSM
PGD
​​ (Linf)
迈向抵抗对抗性攻击的深度学习模型(Mardry 等人,2017 年 投影梯度法
PGD
​​L2 (L2)
迈向抵抗对抗性攻击的深度学习模型(Mardry 等人,2017 年 投影梯度法
MIFGSM
(林夫)
用 Momentum 提升对抗性攻击 ( Dong et al., 2017 ) : heart_eyes: 贡献者zhuangzi926 huitailangyz
TPGD
(林夫)
稳健性和准确性之间的理论上原则性权衡(Zhang 等人,2019 年
EOTPGD
(Linf)
评论“Adv-BNN:通过鲁棒贝叶斯神经网络改进对抗防御”(Zimmermann,2019 年 EOT +PGD
APGD
(Linf, L2)
使用各种无参数攻击的集合对对抗鲁棒性进行可靠评估(Croce 等人,2020
APGDT
(Linf, L2)
使用各种无参数攻击的集合对对抗鲁棒性进行可靠评估(Croce 等人,2020 有针对性的APGD
FAB
(Linf, L2, L1)
具有快速自适应边界攻击的最小失真对抗样本(Croce 等人,2019 年
广场
(Linf,L2)
方形攻击:通过随机搜索进行的高效查询黑盒对抗攻击(Andriushchenko 等人,2019 年
自动攻击( Linf
,L2)
使用各种无参数攻击的集合对对抗鲁棒性进行可靠评估(Croce 等人,2020 APGD+APGDT+FAB+方形
深愚者
(L2)
DeepFool:一种简单而准确的欺骗深度神经网络的方法(Moosavi-Dezfooli 等人,2016 年
单像素
(L0)
一种欺骗深度神经网络的像素攻击(Su et al., 2019
稀疏傻瓜
(L0)
SparseFool:几个像素就有很大的不同(Modas 等人,2019 年
DIFGSM
(林夫)
通过输入多样性提高对抗性示例的可迁移性 ( Xie et al., 2019 ) :heart_eyes: 投稿人淘白
TIFGSM
(林夫)
通过平移不变攻击规避对可转移对抗样本的防御(Dong 等人,2019 年 :heart_eyes: 投稿人淘白
抖动
(Linf)
探索鲁棒神经网络的错误分类以增强对抗性攻击 ( Schwinn, Leo, et al., 2021 )
像素
(L0)
Pixle:一种基于重新排列像素的快速有效的黑盒攻击(Pomponi, Jary, et al., 2022

性能比较

为了公平比较,使用了Robustbench。至于比较包,选择了当前更新和引用最多的方法:

  • Foolbox242次引用,最后更新 2021.06。
  • ART96次引用,最后更新 2021.06。

在 CIFAR10 的前 50 张图像上,对每次攻击和经过时间的稳健准确度。对于 L2 攻击,记录对抗图像和原始图像之间的平均 L2 距离。所有实验均在 GeForce RTX 2080 上完成。最新版本请参考这里(代码nbviewer)。

攻击 包裹 标准 黄2020Fast Rice2020过拟合 评论
FGSM(林夫) 火炬攻击 34%(54 毫秒) 48% (5ms) 62%(82 毫秒)
傻瓜* 34%(15 毫秒) 48% (8ms) 62%(30 毫秒)
艺术 34%(214 毫秒) 48%(59 毫秒) 62%(768 毫秒)
PGD​​ (Linf) 火炬攻击 0%(174 毫秒) 44%(52 毫秒) 58%(1348 毫秒) :crown:最快
傻瓜* 0%(354 毫秒) 44%(56 毫秒) 58%(1856 毫秒)
艺术 0%(1384 毫秒) 44% (437ms) 58%(4704 毫秒)
CW †  (L2) 火炬攻击 0% / 0.40
(2596ms)
14% / 0.61
(3795ms)
22% / 0.56
(43484ms)
:crown:最高
成功率:crown:最快
傻瓜* 0% / 0.40
(2668ms)
32% / 0.41
(3928ms)
34% / 0.43
(44418ms)
艺术 0% / 0.59
(196738ms)
24% / 0.70
(66067ms)
26% / 0.65
(694972ms)
PGD​​ (L2) 火炬攻击 0% / 0.41 (184ms) 68% / 0.5
(52ms)
70% / 0.5
(1377ms)
:crown:最快的
傻瓜* 0% / 0.41 (396ms) 68% / 0.5
(57ms)
70% / 0.5
(1968ms)
艺术 0% / 0.40 (1364ms) 68% / 0.5
(429ms)
70% / 0.5
(4777ms)

*请注意,Foolbox 同时返回准确率和对抗性图像,因此生成对抗性图像的实际时间可能比记录短。

考虑到 const 的二进制搜索算法c可能很耗时,torchattacks 支持 MutliAttack 进行网格搜索c

引文

如果你使用这个包,请引用以下 BibTex ( SemanticScholar , GoogleScholar ):

@article{kim2020torchattacks,
  title={Torchattacks: A pytorch repository for adversarial attacks},
  author={Kim, Hoki},
  journal={arXiv preprint arXiv:2010.01950},
  year={2020}
}

贡献

任何形式的贡献总是受欢迎的!:脸红:

如果您有兴趣在此 repo 中添加新的攻击或修复一些问题,请查看CONTRIBUTING.md

推荐站点和套餐

项目详情