deepfool公式推导
时间: 2025-01-02 07:30:47 浏览: 6
### DeepFool算法公式详细推导过程及原理
#### 一、DeepFool基本概念
DeepFool是一种迭代方法,用于寻找最小的扰动使得输入样本被错误分类。其核心在于通过线性化决策边界来估计最接近当前类别的其他类别之间的距离。
对于给定的一个初始图像\(x\)属于真实标签\(y\),目标是最小化添加到此图像上的噪声大小,使网络将其预测为另一个不同的类别\[ \min_{r} \| r \|_2 : f(x+r) ≠ y \][^1]
#### 二、多分类情况下的DeepFool实现
考虑一个多分类问题,假设存在C个可能的目标类别,则可以构建一个超平面方程组表示各个类间的分隔面:
\[ w_i·x+b_i=0,\quad i∈{1,...,C}\]
这里\(w_i\)代表第i个类对应的权重向量而bi则是偏置项。当面对非线性的神经网路时,这些参数来自于softmax层之前的激活值。
为了简化计算,通常会采用局部近似的方式处理复杂的非线性映射关系。具体来说就是把每一个类视作是由前一层特征空间里的加权求和所形成的简单仿射变换结果。因此,在每一步迭代过程中都可以得到一组新的\(W=[w_1;... ;w_C]\),以及相应的b向量[b1;…;bc]。
此时,如果要找到离原始点最近的那个误分类区域的话,就需要解下面这个优化问题:
\[ min ||δ||_p s.t.\space sign(f(x))≠sign(f(x+δ)), p≥1\]
即寻找能够改变模型输出符号所需的最小范数扰动δ。由于直接解决上述约束条件较为困难,所以转而去寻求满足下述不等式的最小正实数值ε :
\[ (f_j(x)-f_k(x))^T δ ≥ ε , j,k ∈ {1,…, C},j≠k\]
这实际上意味着我们要找的是那个能使任意两个不同类别得分差变得尽可能大的方向。进一步地,考虑到实际情况中我们更关心L2范数形式下的最优解,于是乎就得到了最终版本的DeepFool更新规则:
\[ δ^{(t)}=\frac{|f_k(x_t)-max_{j≠k}(f_j(x_t))|}{\|\nabla_xf_k(x_t)-∇xf_l(x_t)\|^2 }(\nabla_xf_k(x_t)-∇xf_l(x_t))\]
其中l是指除开最大响应外第二高的分数对应的位置索引号。随着循环次数增加,累加每次产生的微调增量直到成功翻越某个临界阈值为止即可完成整个攻击流程的设计[^2].
```python
def deepfool(image, net):
"""
Implementation of the DeepFool algorithm.
Parameters:
image: Input image to be attacked
net: Pre-trained neural network model
Returns:
perturbed_image: Adversarial example generated from input image
"""
num_classes = 10 # Number of classes in classification task
max_iter = 50 # Maximum number of iterations allowed
x = Variable(image.clone(), requires_grad=True).cuda()
f_image = net.forward(x).data.cpu().numpy().flatten()
I = (np.array(f_image)).argsort()[::-1]
label = I[0]
input_shape = image.size()
pert_image = image.clone()
r_tot = np.zeros(input_shape)
k_i = label
for ii in range(max_iter):
x = Variable(pert_image.clone(), requires_grad=True).cuda()
fs = net.forward(x)
fs_list = [fs[0,I[k]] for k in range(num_classes)]
_, grads = torch.autograd.grad(fs_list[I], inputs=x,retain_graph=True, create_graph=False)
grad_orig = grads.data.cpu().numpy().copy()
target_class = None
w = np.squeeze(grads.data.cpu().numpy().copy())
f_multiclass = fs.data.cpu().numpy().flatten()
I_new = np.argsort(f_multiclass)[::-1]
if(I_new[0]!=I[0]):
break
else:
for j in range(len(I)):
if(j==0):continue
w_k = w[I[j]]
dist = abs((f_multiclass[I[j]]-f_multiclass[label]))/np.linalg.norm(w_k-w[I[0]])
if(target_class is None or dist<dist_min):
dist_min = dist
closest = w_k
r_i = (closest - w[I[0]]) * dist_min
r_tot += r_i
pert_image = image + (1+epsilon)*torch.from_numpy(r_tot).cuda()
pert_image =Variable(pert_image,requires_grad=False)
return pert_image
```
阅读全文