6.1 单像素攻击算法
6.1 单像素攻击算法
单像素攻击(single pixel attack)是典型的黑盒攻击算法。nina narodytska和shiva prasad kasiviswanathan在论文《simple black-box adversarial perturbations for deep networks》中介绍了该算法。在白盒攻击中,我们根据一定的算法,在原始数据上叠加了精心构造的扰动,从而导致模型产生分类错误,而单像素攻击的基本思想是,可以通过修改原始数据上的一个像素的值,让模型产生分类错误。
以典型的图像分类模型为例,假设图像为i,分类标签为c(i),分类标签的集合表示为{1,…,c},图像i的通道数为l,通常的彩色相片的通道数为3,灰度图像为1,b为其中的通道序号,(b,x,y)就表示坐标为(x,y)的像素点的第b号通道,(*,x,y)表示坐标为(x,y)的像素点的全部通道。设图像的高为h,宽为w,lb为像素值的下限,ub为上限,那么有:
图6-1 通过修改一个像素点改变分类结果
定义攻击的模型为nn,nn的分类结果为:
nn(i)=(o1,…,oc)
其中oi表示图像i识别为第i个标签的概率。比如分类标签为{1,2,3,4},针对图像i的分类结果nn(i)={0.02,0.2,0.7,0.08},说明分类为标签3的概率最大。
定义π(nn(i),k)表示模型nn针对图像i分类的top k个标签,在图像分类任务中,经常使用分类概率最大的几个标签表示分类结果,典型的为top 3和top 5。比如π(nn(i),3)表示top 3的分类标签。当nn(i)={0.02,0.2,0.7,0.08},π(nn(i),3)={3,2,4},即top 3的分类标签分别为3、2和4。
假设存在某个关键的像素点(*,x,y),通过修改其值让图像i变成图像ip,nn的分类结果产生错误:
我们定义针对点(*,x,y)的扰动函数为pert(i,p,x,y),其中p表示扰动系数,那么扰动的方法为:
sign是符号函数,定义为:
其中扰动后的图像表示为。
单像素攻击算法可以用伪码描述为:
randadv(nn)
输入:图像i,分类标签为c(i)∈{1,…,c},扰动系数为p,迭代最大次数为u
i = 1, critical = 0
while i ≦ u do
随机选择点(*,x,y)
针对该点进行扰动,获得新图像ip(x,y)= pert(i,p,x,y)
if c(i)?π(nn(ip),1) then
critical= critical+1
end if
i=i+1
end while
目前advbox和foolbox均实现了单像素攻击算法,下面以advbox为例介绍单像素攻击算法的具体实现。
首先定义尝试的像素的个数max_pixels以及像素的取值范围。通常像素的取值范围为[0,1],[–1,1]或者[0,255]。
max_pixels=1000
min_, max_ = (0,255)
强制拷贝原始数据避免针对adv_img的修改影响到adversary.original。
adv_img = np.copy(adversary.original)
其中adversary对象的各个字段含义如下。
? adversary.original:原始数据。
? adversary.original_label:原始数据的标签。
? adversary.target_label:定向攻击的目标值。
? adversary.__adversarial_example:保存生成的对抗样本。
? adversary.adversarial_label:对抗样本的标签。
获取图像的宽w和高h,如果图像数据中无法解析宽和高的数据就直接退出。
axes = [i for i in range(adversary.original.ndim)
if i != self.model.channel_axis()]
#输入的图像必须具有高和宽属性
assert len(axes) == 2
h = adv_img.shape[axes[0]]
w = adv_img.shape[axes[1]]
从原始图像中随机提取max_pixels个点。
pixels = np.random.permutation(h * w)
pixels = pixels[:max_pixels]
numpy.random中随机排列数组的函数有两个,分别为permutation和shuffle,这两个函数的功能完全相同,但是permutation不影响原始数据而shuffle是直接在原始数据上修改。
遍历随机挑选的max_pixels个点,并根据原始图像的通道数self.model.channel_axis,组成像素点的具体坐标。
for i, pixel in enumerate(pixels):
x = pixel % w
y = pixel // w
location = [x, y]
location.insert(self.model.channel_axis(), slice(none))
location = tuple(location)
advbox在生成扰动值时,并没有完全参考论文中的实现,因为手工指定的扰动系数p会大大影响扰动效果。为了避免调参的烦琐过程,advbox通过从小到大遍历的方式自动尝试合适的扰动量。
for value in np.linspace(min_, max_, num=256):
perturbed = np.copy(adv_img)
#针对图像的每个信道的点[x,y]同时进行修改
perturbed[location] = value
f = self.model.predict(perturbed)
adv_label = np.argmax(f)
if adversary.try_accept_the_example(adv_img, adv_label):
return adversary
单像素攻击(single pixel attack)是典型的黑盒攻击算法。nina narodytska和shiva prasad kasiviswanathan在论文《simple black-box adversarial perturbations for deep networks》中介绍了该算法。在白盒攻击中,我们根据一定的算法,在原始数据上叠加了精心构造的扰动,从而导致模型产生分类错误,而单像素攻击的基本思想是,可以通过修改原始数据上的一个像素的值,让模型产生分类错误。
以典型的图像分类模型为例,假设图像为i,分类标签为c(i),分类标签的集合表示为{1,…,c},图像i的通道数为l,通常的彩色相片的通道数为3,灰度图像为1,b为其中的通道序号,(b,x,y)就表示坐标为(x,y)的像素点的第b号通道,(*,x,y)表示坐标为(x,y)的像素点的全部通道。设图像的高为h,宽为w,lb为像素值的下限,ub为上限,那么有:
图6-1 通过修改一个像素点改变分类结果
定义攻击的模型为nn,nn的分类结果为:
nn(i)=(o1,…,oc)
其中oi表示图像i识别为第i个标签的概率。比如分类标签为{1,2,3,4},针对图像i的分类结果nn(i)={0.02,0.2,0.7,0.08},说明分类为标签3的概率最大。
定义π(nn(i),k)表示模型nn针对图像i分类的top k个标签,在图像分类任务中,经常使用分类概率最大的几个标签表示分类结果,典型的为top 3和top 5。比如π(nn(i),3)表示top 3的分类标签。当nn(i)={0.02,0.2,0.7,0.08},π(nn(i),3)={3,2,4},即top 3的分类标签分别为3、2和4。
假设存在某个关键的像素点(*,x,y),通过修改其值让图像i变成图像ip,nn的分类结果产生错误:
我们定义针对点(*,x,y)的扰动函数为pert(i,p,x,y),其中p表示扰动系数,那么扰动的方法为:
sign是符号函数,定义为:
其中扰动后的图像表示为。
单像素攻击算法可以用伪码描述为:
randadv(nn)
输入:图像i,分类标签为c(i)∈{1,…,c},扰动系数为p,迭代最大次数为u
i = 1, critical = 0
while i ≦ u do
随机选择点(*,x,y)
针对该点进行扰动,获得新图像ip(x,y)= pert(i,p,x,y)
if c(i)?π(nn(ip),1) then
critical= critical+1
end if
i=i+1
end while
目前advbox和foolbox均实现了单像素攻击算法,下面以advbox为例介绍单像素攻击算法的具体实现。
首先定义尝试的像素的个数max_pixels以及像素的取值范围。通常像素的取值范围为[0,1],[–1,1]或者[0,255]。
max_pixels=1000
min_, max_ = (0,255)
强制拷贝原始数据避免针对adv_img的修改影响到adversary.original。
adv_img = np.copy(adversary.original)
其中adversary对象的各个字段含义如下。
? adversary.original:原始数据。
? adversary.original_label:原始数据的标签。
? adversary.target_label:定向攻击的目标值。
? adversary.__adversarial_example:保存生成的对抗样本。
? adversary.adversarial_label:对抗样本的标签。
获取图像的宽w和高h,如果图像数据中无法解析宽和高的数据就直接退出。
axes = [i for i in range(adversary.original.ndim)
if i != self.model.channel_axis()]
#输入的图像必须具有高和宽属性
assert len(axes) == 2
h = adv_img.shape[axes[0]]
w = adv_img.shape[axes[1]]
从原始图像中随机提取max_pixels个点。
pixels = np.random.permutation(h * w)
pixels = pixels[:max_pixels]
numpy.random中随机排列数组的函数有两个,分别为permutation和shuffle,这两个函数的功能完全相同,但是permutation不影响原始数据而shuffle是直接在原始数据上修改。
遍历随机挑选的max_pixels个点,并根据原始图像的通道数self.model.channel_axis,组成像素点的具体坐标。
for i, pixel in enumerate(pixels):
x = pixel % w
y = pixel // w
location = [x, y]
location.insert(self.model.channel_axis(), slice(none))
location = tuple(location)
advbox在生成扰动值时,并没有完全参考论文中的实现,因为手工指定的扰动系数p会大大影响扰动效果。为了避免调参的烦琐过程,advbox通过从小到大遍历的方式自动尝试合适的扰动量。
for value in np.linspace(min_, max_, num=256):
perturbed = np.copy(adv_img)
#针对图像的每个信道的点[x,y]同时进行修改
perturbed[location] = value
f = self.model.predict(perturbed)
adv_label = np.argmax(f)
if adversary.try_accept_the_example(adv_img, adv_label):
return adversary