需要源码请点赞关注收藏后评论区留言私信~~~
白盒攻击
根据攻击者对模型的了解程度,对抗攻击可分为白盒攻击和黑盒攻击。
白盒攻击是指攻击者掌握包括模型结构与系数在内的所有信息。
黑盒攻击是指攻击者对模型结构与参数不了解,仅能够对模型进行输入试探以获得对应的输出响应。
FGM算法
算法流程图如下
在定向攻击时,误差是用前向传播的输出与攻击目标y_target进行比较计算得到的,因此,扰动的目标是使该误差变小,因此,扰动r沿梯度的相反方向计算得到。
在非定向攻击时,误差是用前向传播的输出与实际标签进行比较计算得到的,因此,扰动的目标是使该误差变大,因此,扰动r是沿梯度的真实方向计算得到,即按所谓的梯度上升法进行优化。
记样本为x=(x^(1),x^(2),…,x^(n))。 记损失函数对样本特征变量的梯度为:g=(g^(1),g^(2),…,g^(n))
其中,g^(i)为误差对x^(i)的梯度。 FGM算法的调整样本扰动r为:
其中,‖g‖_2是g的L2范数,即进行了正则化操作。ϵ常量是步长。
输出结果如下 可见198次预测时结果为1.成功达到了扰乱模型判断能力的目的
FGSM
FGSM是在FGM的基础上,将样本特征变量的梯度g的符号作为扰动r:
加入扰动之后,对抗样本被模型错误识别为miniature_poodle类型,但实际上它是一直贵宾犬
FGSM算法比较简单,生成的样本具有迁移性好的特点。在FGSM算法的基础上,发展出了I-FGSM和MI-FGSM等算法。
DeepFool算法
DeepFool算法是一种基于梯度的可自动调整步长的对抗样本生成算法。从攻击线性二分类模型推广到攻击一般多分类模型。 在攻击线性二分类模型时,扰动r为:
在f(x)=0时表示分割空间的超平面,超平面的两侧分别表示不同的类别。在二维平面上,它是一条直线,在三维立体空间中,它是一个平面。
把扰动r写成如下形式:
f(x)/‖g‖是空间中点到平面的距离,g/‖g‖是平面的单位法向量,因此,r可看作是从点x到平面的向量,它的方向垂直于平面并指向平面,长度等于它到平面的距离。
在攻击一般的非线性二分类模型时,采用迭代求解。最终扰动是每次迭代的扰动之和。
推广到攻击线性多分类模型时,扰动r是点x到各个超平面的向量中长度最短的那个。记第k个超平面为f_k(x)=0。记点x的原始预测概率最大函数为f_k ̂(x)。可以证明点x到第k个超平面的最短向量r_k为:
最优的扰动r是所有r_k中的最小值。推广到攻击一般的非线性多分类模型时,采用迭代求解,每次迭代中,取到每个超平面的扰动r_k的模最小者作为本次迭代调整样本的扰动r。最终扰动是所有迭代的扰动之和。
运行结果如下 可见最后一次将图片识别成了8,成功达到了扰动的目的
部分代码如下
def deepfool(img, label, model, epochs=1000): #epochs = 1000 # 最大迭代次数 overshoot = 0.02 # 加大一点扰动,越过分类超平面 input_shape = [28, 28, 1] w = np.zeros(input_shape) r_tot = np.zeros(img.shape) # 记录累积扰动 orig_label = np.argmax(label) output = model(img) adv = img for epoch in range(epochs): scores = model(adv).numpy()[0] label = np.argmax(scores) print(epoch, ':', label, scores[label]) if label != orig_label: # 无定向攻击成功 break pert = np.inf grad_orig = compute_grad(tf.constant(adv), orig_label) for k in range(num_classes): if k == orig_label: continue cur_grad = compute_grad(tf.constant(adv), k) w_k = cur_grad - grad_orig f_k = (output[0, k] - output[0, orig_label]).numpy() #if np.linalg.norm(w_k) == 0: # print('norm==0', epoch, k, orig_label) pert_k = abs(f_k) / (np.linalg.norm(w_k) + 1e-5) if pert_k < pert: # 选择pert最小值 pert = pert_k w = w_k # 计算 r_i 和 r_tot r_i = (pert + 1e-8) * w / (np.linalg.norm(w) + 1e-5) # 本次迭代的扰动 r_tot = r_tot + r_i # 累积扰动 adv = img + (1 + overshoot) * r_tot # 原样本加上扰动 if epoch == epochs -1: succ = False else: succ = True return succ, adv, r_tot, epoch, label
创作不易 觉得有帮助请点赞关注收藏~~~