【算法】Sign-Opt Attack算法手稿

原文链接及源码链接

原文:https://arxiv.org/abs/1909.10773
源码:https://github.com/cmhcbb/attackbox

类型

这里分析Untargeted Attack,l2攻击

算法

输入

攻击的模型:model
原始的样本及其标签:x0,y0
迭代次数:1000
查询次数:20000
alpha:0.02
beta:0.001

初始化

随机生成num_directions=100个高斯噪声$\boldsymbol{u}$,并在这100个方向中找到最好的初始攻击方向。
最好的初始攻击方向,在这个方向上,g(θ)的值是最小的。
g(θ)的含义:当搜索方向为θ时,对应的到决策边界最近的对抗样本与原图像的距离为g(θ)(失真度)。
g(θ)的求法:细粒度搜索+二分查找

梯度下降

  • 1000次迭代以内

    • 在x0+theta处进行梯度估计,使用sign_grad_v1(详见下一小节)来进行梯度估计,然后使用这个不完美的梯度来更新搜索方向theta。

    • 线性搜索来寻找梯度下降的步长

    • 初始化:min_theta=之前初始化最好的theta;min_g2之前初始化最好的g_theta;min_vg=0向量只用于动量mpmentum)

    • part 1:循环【每一次 通过一步SGD(随机梯度下降法)来更新theta】 【跨大步直到直到找到new_g2>=min_g2】

      • 通过动量判断更新的theta及其对应的g(θ)值暂存于new_theta和new_g2中。

      • 逐渐增大步长 alpha = alpha * 2

      • 如果new_g2<min_g2,更新min_theta和min_g2

        • 如果momentum>0,更新new_vg
      • 否则 结束part 1

    • part 2 循环【如果part 1失败了,即以来就结束了part 1,说明alpha初始化过大,要尝试小一点的alpha。】 【跨小步直到找到new_g2 < gg】

      • 通过动量判断更新的theta及其对应的g(θ)值暂存于new_theta和new_g2中。

      • 逐渐缩小步长 alpha = alpha * 0.25

      • 如果new_g2<gg,更新min_theta和min_g2

        • 如果momentum>0,更新new_vg ,并且 结束part 2
    • part 3 如果part 2 part 3全失败了,都没能更新min_theta和min_g2,即意味着没有移动,执行part 3

      • alpha重置为1 并输出提示”Warning: not moving”
      • beta = beta * 1
      • 如果beta < 1e-8 结束整个1000次迭代
    • part 4【更新xg,gg,vg】

    • 如果part 1 part 2全失败了,min_theta,min_g2将会是当前theta值,当前g2值(即没有移动)。

    • part 5 【如果查询次数query_count > 查询限制 query_limit,结束整个1000次迭代。】

  • 迭代结束 返回对抗样本

sign_grad_v1

通过以下公式估计梯度的符号:
$ sign(g) = 1/Q [ \sum_{q=1}^Q sign( g(theta+h*u_i) - g(theta) )u_i]$

image-20211003132818992

sign_gif

判断:在以原来长度(g(θ)值)为半径的球面,x0从另一个方向(new_tℎeta)生成对抗样本,该样本是否依然落在决策边界外(即保持对抗性)!
如果仍然保持对抗性(即≠y0),则新方向(new_tℎeta)到决策边界距离较小,从而给出较小的g值(即g_new(小) - g(大) < 0),表明$u$是最小化优化问题下降的方向!把这些随机的$u$加起来求平均来近似估计g的梯度。(是一种不精确的梯度估计,但是减少了查询量)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
def sign_grad_v1(self, x0, y0, theta, initial_lbd, h=0.001, D=4, target=None):
"""
Evaluate the sign of gradient by formulat
sign(g) = 1/Q [ \sum_{q=1}^Q sign( g(theta+h*u_i) - g(theta) )u_i$ ]
"""
K = self.k # 200个随机方向 (用来估计梯度)
sign_grad = np.zeros(theta.shape) #初始化
queries = 0
### 使用正交变换
#dim = np.prod(sign_grad.shape)
#H = np.random.randn(dim, K)
#Q, R = qr(H, mode='economic')
for iii in range(K): # for each u
# # Code for reduced dimension gradient
# u = np.random.randn(N_d,N_d)
# u = u.repeat(D, axis=0).repeat(D, axis=1)
# u /= LA.norm(u)
# u = u.reshape([1,1,N,N])

u = np.random.randn(*theta.shape); u /= LA.norm(u) #随机一个U方向,并单位化
new_theta = theta + h*u; new_theta /= LA.norm(new_theta) #新的theta:new_theta=theta + h*u,并将new_theta单位化
sign = 1

# Targeted case. 定向攻击 的设置
if (target is not None and
self.model.predict_label(x0+torch.tensor(initial_lbd*new_theta, dtype=torch.float)) == target):
sign = -1

# Untargeted case 非定向攻击 的设置
# preds.append(self.model.predict_label(x0+torch.tensor(initial_lbd*new_theta, dtype=torch.float)).item())
if (target is None and
self.model.predict_label(x0+torch.tensor(initial_lbd*new_theta, dtype=torch.float)) != y0): # success
sign = -1 # 依旧保持对抗性,说明下降的方向正确

queries += 1
sign_grad += u*sign

sign_grad /= K

return sign_grad, queries

总结

使用单次查询来估计梯度的方向,而不使用有限差分来直接估计梯度。

友情链接

文献笔记:【文献笔记】SIGN-OPT-A-QUERY-EFFICIENT-HARD-LABEL