One pixel 对抗攻击_学习笔记

本文记录One pixel对抗攻击算法学习过程。该算法是黑盒攻击,只改变一个像素点即可攻击,主要用差分进化算法。它具有有效性、半黑盒攻击、灵活性等优点,将对抗样本生成化为优化问题。文中还介绍了算法参数设置,给出代码链接。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

本篇博客出于学习交流目的,主要是用来记录自己学习中遇到的问题和心路历程,方便之后回顾。过程中可能引用其他大牛的博客,文末会给出相应链接,侵删!


One pixel 对抗攻击算法
特点:黑盒攻击,只改变一个像素点即可实现攻击
论文原文:One pixel attack for fooling deep neural networks

之前介绍的几篇对抗攻击算法几乎都是在整个图像所有像素点上做微小的扰动,以达到欺骗模型的目的,而这篇文章的思想是只改变较少的像素点,甚至只改变一个像素点就能获得较好的攻击效果。

正文

考虑极端攻击情况,只修改一个像素点,对图像几何特征和DNN模型在高维的行为有了新的洞察。主要扰动算法差分进化算法。

相较其他算法该算法具有以下优点
有效性: CIFAR-10数据集在三个常见DNN模型上无目标攻击欺骗率达68.71%,72.85%,63.53%,并且平均每个图像可扰动成1.9,2.3,1.7个其他类样本。ImageNet 数据集在BVLC AlexNet模型下无目标攻击有效性为41.22%。
半黑盒攻击:只需要返回黑盒的类标概率而不用网络的内部参数。
灵活性:可以攻击那些不可微或梯度难以计算的模型。

主要出发点
自然图像邻的分析:如通用扰动加一些小的变化可获得自然图像周围球形范围内的对抗样本,而只修改很少的像素点可以看做是对DNN高维空间切割成非常低维的输入空间。
可观察性的一种评估指标:没人能够保证前人的算法生成的扰动就一定不可观察,而最简单的方法就是限制修改的像素点,修改的越少,那么被看出来的概率也越低,并且在实际中,效果确实很好。

算法

问题描述


对抗样本生成形式化为含有限制条件的优化问题。
输入 n n 维图像x=(x1,,xn),图像每个像素看成是向量的一个分量;
f f ,分类器;
t,类别;
ft(x) f t ( x ) ,图像 x x 属于类别 t t 的概率;
e(x)=(e1,,en),对抗扰动向量;
L L ,最大修改器限制;
公式如下:

maximizee(x)fadv(x+e(x))

subjecttoe(x)L s u b j e c t t o ‖ e ( x ) ‖ ≤ L

单像素扰动的问题可以分解为两部分:1,扰动哪个扰动;2,扰动多少;那么问题就可以简化为
maximizee(x)fadv(x+e(x)) m a x i m i z e e ( x ) ∗ f a d v ( x + e ( x ) )
subjecttoe(x)0d s u b j e c t t o ‖ e ( x ) ‖ 0 ≤ d

单像素攻击,即 d=1 d = 1
注:传统的改变整个输入图像的方法控制尽量小的扰动,而这篇算法则是控制扰动的像素个数,对于修改的幅度则不作限制。
这里写图片描述
以原文中的图例解释,假如我们的输入是3像素,而我们的攻击的单像素的,那么我们的输入空间被切割为三根红黑线;如果攻击是两像素,则攻击输入空间是蓝色的平面部分,以此类推更多维的攻击;

差分进化算法


差分进化算法是很流行的解决多模优化问题的优化算法,一种常见的遗传算法,主要区别是变异向量是由父代差分向量生成。
优势:
高概率找到全局最优解;
不用计算梯度,需要更少的信息;
简易;

算法与参数设置


将扰动以数组形式,候选解需固定扰动像素点的数目。单像素攻击,以一个5元组表示,分别是x-y轴坐标,以及RGB各通道的扰动值。初始候选解为400,每次生成400候选后代解,依以下公式:

xi(g+1)=xr1(g)+F(xr2(g)+xr3(g)), x i ( g + 1 ) = x r 1 ( g ) + F ( x r 2 ( g ) + x r 3 ( g ) ) ,
r1r2r3 r 1 ≠ r 2 ≠ r 3

xi x i 是一个候选解, r1r2r3 r 1 , r 2 , r 3 是随机数, F F 是比例参数设为0.5,g是当前代。生成子代时,每个候选解将根据人口指数与相对应的父亲竞争,获胜者将在下一次迭代中生存下来。最大迭代次数设为100,或者,满足对于某些测试集的指定百分比时提前停止。初始化时,x-y坐标,CIFAR-10数据集用 U(1,32) U ( 1 , 32 ) 均匀分布,ImageNet数据集用 U(1,227) U ( 1 , 227 ) 均匀分布;各通道颜色幅度用高斯分布 N(µ=128,σ=127) N ( µ = 128 , σ = 127 )

实验结果

原文做了大量的实验,在不同数据集和限制不同像素点条件下,具体看原文吧。

代码链接https://github.com/Hyperparticle/one-pixel-attack-keras

以下是将给定的 MATLAB 代码转换为 PyTorch 代码的过程: ``` import torch import torch.nn.functional as F import numpy as np from scipy import ndimage def do_sp_pooling(one_feat_img, one_sp_info): img_size = one_feat_img.shape num_units = img_size[0] * img_size[1] dim = img_size[2] one_feat_img = one_feat_img.reshape(num_units, dim) img_size_org = one_sp_info['img_size'] pixel_ind_map = np.arange(num_units).reshape(img_size[0], img_size[1]) pixel_ind_map_org = ndimage.zoom(pixel_ind_map, [img_size_org[0]/img_size[0], img_size_org[1]/img_size[1]], order=0) pixel_ind_sps = one_sp_info['pixel_ind_sps'] num_sp = len(pixel_ind_sps) weight_pool_info = torch.zeros((num_sp, num_units), dtype=one_feat_img.dtype, device=one_feat_img.device) for idx_sp in range(num_sp): pixel_ind_sp_one = pixel_ind_sps[idx_sp] ind_pixels_in_map = pixel_ind_map_org[pixel_ind_sp_one] _, uniqueIndex = np.unique(ind_pixels_in_map, return_inverse=True) frequency = np.bincount(uniqueIndex) / len(ind_pixels_in_map) frequency = frequency.astype(one_feat_img.dtype) freq_one_sp = torch.zeros(num_units, dtype=one_feat_img.dtype, device=one_feat_img.device) freq_one_sp[ind_pixels_in_map] = torch.tensor(frequency, dtype=one_feat_img.dtype, device=one_feat_img.device) weight_pool_info[idx_sp, :] = freq_one_sp one_feat_sps = torch.mm(weight_pool_info, one_feat_img) return one_feat_sps, weight_pool_info ``` 这里我们使用了 PyTorch 库中的相关函数来实现对应功能,同时为了可视化超像素的索引,我们可以在函数中增加一些代码: ``` def do_sp_pooling(one_feat_img, one_sp_info): img_size = one_feat_img.shape num_units = img_size[0] * img_size[1] dim = img_size[2] one_feat_img = one_feat_img.reshape(num_units, dim) img_size_org = one_sp_info['img_size'] pixel_ind_map = np.arange(num_units).reshape(img_size[0], img_size[1]) pixel_ind_map_org = ndimage.zoom(pixel_ind_map, [img_size_org[0]/img_size[0], img_size_org[1]/img_size[1]], order=0) pixel_ind_sps = one_sp_info['pixel_ind_sps'] num_sp = len(pixel_ind_sps) weight_pool_info = torch.zeros((num_sp, num_units), dtype=one_feat_img.dtype, device=one_feat_img.device) for idx_sp in range(num_sp): pixel_ind_sp_one = pixel_ind_sps[idx_sp] ind_pixels_in_map = pixel_ind_map_org[pixel_ind_sp_one] _, uniqueIndex = np.unique(ind_pixels_in_map, return_inverse=True) frequency = np.bincount(uniqueIndex) / len(ind_pixels_in_map) frequency = frequency.astype(one_feat_img.dtype) freq_one_sp = torch.zeros(num_units, dtype=one_feat_img.dtype, device=one_feat_img.device) freq_one_sp[ind_pixels_in_map] = torch.tensor(frequency, dtype=one_feat_img.dtype, device=one_feat_img.device) weight_pool_info[idx_sp, :] = freq_one_sp # 可视化超像素的索引 img_sp = np.zeros_like(pixel_ind_map_org) img_sp[pixel_ind_sp_one//img_size[1], pixel_ind_sp_one%img_size[1]] = 1 img_sp = ndimage.binary_dilation(img_sp, iterations=1) img_sp = np.where(img_sp, idx_sp+1, 0) img_sp = ndimage.zoom(img_sp, [img_size[0]/img_size_org[0], img_size[1]/img_size_org[1]], order=0) plt.imshow(img_sp, cmap='jet', alpha=0.3, vmin=0, vmax=num_sp) one_feat_sps = torch.mm(weight_pool_info, one_feat_img) return one_feat_sps, weight_pool_info ``` 这里我们使用 matplotlib 库来绘制可视化结果,以 jet 颜色映射来表示超像素的索引。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值