论文原文:DeepFool: a simple and accurate method to fool deep neural networks arXiv:1511.04599 [cs.LG]
思路
deepfool提出两种产生对抗样本的算法,二分类和多分类情况。并实验比较EOT、FGSM和deepfool三种算法的鲁棒性。
1、二分类器
- 符号函数k^(x) = sign(f(x)) 其中 f(x) = wx + b。对样本添加扰动使得样本分类到距离最近的类。
- r:样本到分类边界的最短距离*法线方向的单位向量
2、多分类器
- k^(x)= fk(x),fk(x) 是向量f(x)的第k个维度,即第k个子分类器。
- 计算样本到各个类的最小距离,取最近的一类,L为距离超平面最近的一类。
3、评估鲁棒性
通过扰动所占样本的比值来评估鲁棒性。下表为deepfool,EOT,FGSM三种算法的鲁棒性和运行时间对比
4、论文复现-多分类结果:
- Evaluating on clean data
loss: 0.0294 acc: 0.9900 - Evaluating on adversarial data
loss: 1.6897 acc: 0.1145
def _deepfool2(model, x, epochs, eta, clip_min, clip_max, min_prob):
"""DeepFool二分类情况
干净样本和对抗样本输出: +1/-1
"""
y0 = tf.stop_gradient(tf.reshape(model(x), [-1])[0])
y0 = tf.to_int32(tf.greater(y0, 0.0))
def _cond(i, z):
xadv = tf.clip_by_value(x + z*(1+eta), clip_min, clip_max)
y = tf.stop_gradient(tf.reshape(model(xadv), [-1])[0])
y = tf.to_int32(tf.greater(y, 0.0))
return tf.logical_and(tf.less(i, epochs), tf.equal(y0, y))
def _body(i, z):
xadv = tf.clip_by_value(x + z*(1+eta), clip_min, clip_max)
y = tf.reshape(model(xadv), [-1])[0]
g = tf.gradients(y, xadv)[0]
dx = - y * g / (tf.norm(g) + 1e-10) # 1范数:norm(1)
return i+1, z+dx
_, noise = tf.while_loop(_cond, _body, [0, tf.zeros_like(x)],
name='_deepfool2', back_prop=False)
return noise
def _deepfoolx(model, x, epochs, eta, clip_min, clip_max, min_prob):
"""DeepFool多分类情况.
分类到最大概率的标签.
"""
y0 = tf.stop_gradient(model(x))
y0 = tf.reshape(y0, [-1])
k0 = tf.argmax(y0)
ydim = y0.get_shape().as_list()[0]
xdim = x.get_shape().as_list()[1:]
xflat = _prod(xdim)
def _cond(i, z):
xadv = tf.clip_by_value(x + z*(1+eta), clip_min, clip_max)
y = tf.reshape(model(xadv), [-1])
p = tf.reduce_max(y)
k = tf.argmax(y)
return tf.logical_and(tf.less(i, epochs),
tf.logical_or(tf.equal(k0, k),
tf.less(p, min_prob)))
def _body(i, z):
xadv = tf.clip_by_value(x + z*(1+eta), clip_min, clip_max)
y = tf.reshape(model(xadv), [-1])
gs = [tf.reshape(tf.gradients(y[i], xadv)[0], [-1])
for i in range(ydim)]
g = tf.stack(gs, axis=0)
yk, yo = y[k0], tf.concat((y[:k0], y[(k0+1):]), axis=0)
gk, go = g[k0], tf.concat((g[:k0], g[(k0+1):]), axis=0)
yo.set_shape(ydim - 1)
go.set_shape([ydim - 1, xflat])
a = tf.abs(yo - yk)
b = go - gk
c = tf.norm(b, axis=1)
score = a / c
ind = tf.argmin(score)
si, bi = score[ind], b[ind]
dx = si * bi
dx = tf.reshape(dx, [-1] + xdim)
return i+1, z+dx
_, noise = tf.while_loop(_cond, _body, [0, tf.zeros_like(x)],
name='_deepfoolx', back_prop=False)
return noise