9.7.2 运行测试代码
robust-ml提供了测试代码,下载路径为:
在测试代码中attack.py文件实现了pgd和fgsm攻击算法,攻击对象是inceptionv3模型。其中pgd算法是一个轻量级的攻击算法,基本思路是基于迭代优化,但是每次迭代更新时,会根据预先设置的阈值进行数据裁剪,我们结合代码详细介绍pgd算法的实现。首先继承robustml.attack.attack类实现pgd算法。
class inceptionv3pgdattack(robustml.attack.attack):
在类的初始化函数中,输入的参数分别为:
#tensorflow的会话
self._sess = sess
#被攻击的模型
self._model = model
#每个像素允许的最大扰动,超过的将直接截断
self._epsilon = epsilon
#最大迭代次数,默认为100
self._max_steps = max_steps
#学习速率,默认为0.001
self._learning_rate = learning_rate
#debug开关,默认为false
self._debug = debug
然后定义对应的标签_label并转换成独热编码格式,损失函数定义为预测值与_label的交叉熵,并根据损失函数计算对应的梯度self._grad。
self._label = tf.placeholder(tf.int32, ())
one_hot = tf.expand_dims(tf.one_hot(self._label, 1000), axis=0)
self._loss = tf.nn.softmax_cross_entropy_with_logits_v2(logits=model.logits,
labels=one_hot)
self._grad, = tf.gradients(self._loss, model.input)
在robust-ml中,攻击算法的主要实现集中在run函数中。如果进行定向攻击,设置定向目标为target,反之为none。
def run(self, x, y, target):
mult = -1
if target is none:
target = y
mult = 1
计算图像扰动后的上限和下限,超过定义的最大扰动将被直接截断。迭代计算预测值、损失值和梯度值。
adv = np.copy(x)
lower = np.clip(x - self._epsilon, 0, 1)
upper = np.clip(x + self._epsilon, 0, 1)
for i in range(self._max_steps):
p, l, g = self._sess.run(
[self._model.predictions, self._loss, self._grad],
{self._model.input: adv, self._label: target}
)
如果满足退出条件即完成迭代,反之则使用梯度值和学习速率更新对抗样本。定向攻击时,预测标签与定向攻击目标一致时退出;无定向攻击时,预测标签与原分类标签不相同时退出。
if p != y:
break
adv += mult * self._learning_rate * np.sign(g)
adv = np.clip(adv, lower, upper)
攻击的模型为inceptionv3,需要下载tensorflow对应的预训练版本,可直接运行setup.sh。
sh setup.sh
downloading
http://download.tensorflow.org/models/inception_v3_2016_08_28.tar.gz
downloaded inception_v3.ckpt
调用攻击代码在run.py中进行,其中需要指定的参数主要为imagenet2012数据集的路径imagenet-path和攻击算法attack。默认情况下会攻击100张图片,如果希望修改攻击图片的范围,可以通过指定start和end来设置起始和结束的图片序号。
parser = argparse.argumentparser()
parser.add_argument('--imagenet-path', type=str, required=true,
help='directory containing `val.txt` and `val/` folder')
parser.add_argument('--start', type=int, default=0)
parser.add_argument('--end', type=int, default=100)
parser.add_argument('--attack', type=str, default='pgd', help='pgd | fgsm |
none')
args = parser.parse_args()
run.py会创建tensorflow会话并初始化inceptionv3模型。
# 创建tensorflow会话
sess = tf.session()
# 初始化模型
model = inceptionv3(sess)
robust-ml通过provider.imagenet封装了imagenet2012。整个攻击过程在robustml.evaluate.evaluate函数中调用并评估攻击和防御效果。其中需要特别指出的是deterministic参数表示是否随机打乱图片顺序和定向攻击的目标标签,如果想提高随机性可以设置为true,如果想让每次运行的结果保持稳定可以设置为false。
# 初始化imagenet图像文件的数据发生器
provider = robustml.provider.imagenet(args.imagenet_path, (299, 299, 3))
success_rate = robustml.evaluate.evaluate(model,attack,provider,
start=args.start,
end=args.end,
deterministic=true,
debug=true)
print('attack success rate: %.2f%% (over %d data points)' % (success_
rate*100, args.end-args.start))
运行fgsm攻击算法,攻击成功率为83%。
python run.py --imagenet-path ../data/ --attack fgsm
attack success rate: 83.00% (over 100 data points)
运行pgd攻击算法,攻击成功率为100%。
python run.py --imagenet-path ../data/ --attack pgd
attack success rate: 100.00% (over 100 data points)
robust-ml运行的算法是定向攻击还是无定向攻击,由模型的攻击模式决定。在evaluate函数的实现中可以发现。
https://github.com/robust-ml/robustml/blob/master/robustml/evaluate.py
evaluate函数会读取模型的攻击模式的targeted属性,默认都是无定向攻击。
threat_model = model.threat_model
targeted = threat_model.targeted
本例中使用的攻击模式为linf,为无定向攻击。
self._threat_model =robustml.threat_model.linf(epsilon=0.01)