请选择 进入手机版 | 继续访问电脑版

大蛇智能

 找回密码
 立即注册

扫一扫,访问微社区

搜索
热搜: 活动 交友 discuz
查看: 2234|回复: 4

连载三:用对抗样本攻击PNASNet模型(附源码)

[复制链接]

127

主题

308

帖子

989

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
989
发表于 2018-11-4 14:23:28 | 显示全部楼层 |阅读模式
FGSM生成样本来攻击PNASNet网络,令其将狗识别成盘子

本例通过使用FGSM的方式,来生成攻击样本。对PNASNet发起攻击,使其输出的识别结果,产生错误。

案例描述

先用一张哈士奇狗的照片,输入带有预编译模型PNASNet网络。观察其返回结果。
通过梯度下降算法训练一个模拟样本。待模拟样本生成完成之后,输入PNASNet令其输出识别结果为盘子。
该案例所实现的FGSM原理很简单:将输入的图片当作训练参数。通过优化器不断的迭代,来将图片逐渐改造成输入模型认为使盘子的样子。下面就来演示其实现过程。
代码实现:创建PNASNet模型
在代码“3-1  使用AI模型来识别图像.py”中,介绍了一个使用PNASNet网络的预编译模型,进行图片识别的例子。本案例就在该代码基础上实现。首先“3-1  使用AI模型来识别图像.py”代码文件的整个工作环境复制一份。并编写pnasnetfun函数,实现模型的创建。完整的代码如下:
在线性回归模型中添加指定节点到检查点文件
1 import sys                                         #初始化环境变量
2 nets_path = r'slim'
3 if nets_path not in sys.path:
4    sys.path.insert(0,nets_path)
5 else:
6    print('already add slim')
7
8 import tensorflow as tf                           #引入头文件
9 from nets.nasnet import pnasnet
10 import numpy as np
11 from tensorflow.python.keras.preprocessing import image
12
13 import matplotlib as mpl
14 import matplotlib.pyplot as plt
15 mpl.rcParams['font.sans-serif']=['SimHei']#用来正常显示中文标签  
16 mpl.rcParams['font.family'] = 'STSong'
17 mpl.rcParams['font.size'] = 15
18
19 slim = tf.contrib.slim
20 arg_scope = tf.contrib.framework.arg_scope
21
22 tf.reset_default_graph()                       
23 image_size = pnasnet.build_pnasnet_large.default_image_size       #获得图片输入尺寸
24 LANG = 'ch'                                                        #使用中文标签
25
26 if LANG=='ch':
27    def getone(onestr):
28        return onestr.replace(',',' ').replace('\n','')
29
30    with open('中文标签.csv','r+') as f:                             #打开文件               
31        labelnames =list( map(getone,list(f))  )
32        print(len(labelnames),type(labelnames),labelnames[:5])             #显示输出中文标签   
33 else:
34    from datasets import imagenet
35    labelnames = imagenet.create_readable_names_for_imagenet_labels()     #获得数据集标签
36    print(len(labelnames),labelnames[:5])                                       #显示输出标签
37
38 def pnasnetfun(input_imgs,reuse ):
39    preprocessed = tf.subtract(tf.multiply(tf.expand_dims(input_imgs, 0), 2.0), 1.0)
40    arg_scope = pnasnet.pnasnet_large_arg_scope()                         #获得模型命名空间
41
42    with slim.arg_scope(arg_scope):                                        #创建PNASNet模型
43        with slim.arg_scope([slim.conv2d,
44                             slim.batch_norm, slim.fully_connected,
45                             slim.separable_conv2d],reuse=reuse):
46
47            logits, end_points = pnasnet.build_pnasnet_large(preprocessed,num_classes = 1001, is_training=False)   
48            prob = end_points['Predictions']  
49    return logits, prob

代码13~17行在《深度学习之TensorFlow:入门、原理与进阶实战》9.7.4节也用过,是支持中文显示的作用。代码43行的作用,是支持PNASNet模型的变量复用功能。
注意:
在创建模型时,需要将其设为不可训练(代码47行)。这样才能保证,在后面12.2.3节通过训练生成攻击样本时,PNASNet模型不会有变化。
代码实现:搭建输入层并载入图片,复现PNASNet预测效果
在本案例中,没有使用占位符来建立输入层,而是使用了张量。使用tf.Variable定义的张量与占位符的效果一样,同样可以支持注入机制。这么做的目的是为了在后面制造攻击样本时使用。接着是载入图片、载入预编译模型、将图片注入到预编译模型中的操作。并最终可视化输出预测结果。完整的代码如下:
代码12-1  在线性回归模型中添加指定节点到检查点文件(续)
50 input_imgs = tf.Variable(tf.zeros((image_size, image_size, 3)))                        
51 logits, probs = pnasnetfun(input_imgs,reuse=False)   
52 checkpoint_file = r'pnasnet-5_large_2017_12_13\model.ckpt'   #定义模型路径
53 variables_to_restore = slim.get_variables_to_restore()
54 init_fn = slim.assign_from_checkpoint_fn(checkpoint_file, variables_to_restore,ignore_missing_vars=True)
55
56 sess = tf.InteractiveSession()         #建立会话
57 init_fn(sess)                             #载入模型
58
59 img_path = './dog.jpg'                #载入图片
60 img = image.load_img(img_path, target_size=(image_size, image_size))
61 img = (np.asarray(img) / 255.0).astype(np.float32)
62
63 def showresult(img,p):                #可视化模型输出结果
64    fig, (ax1, ax2) = plt.subplots(1, 2, figsize=(10, 8))
65    fig.sca(ax1)
66
67    ax1.axis('off')
68    ax1.imshow(img)
69    fig.sca(ax1)
70
71    top10 = list((-p).argsort()[:10])
72    lab= [labelnames[:15] for i in top10]
73    topprobs = p[top10]
74    print(list(zip(top10,lab,topprobs)))
75
76    barlist = ax2.bar(range(10), topprobs)
77
78    barlist[0].set_color('g')
79    plt.sca(ax2)
80    plt.ylim([0, 1.1])
81    plt.xticks(range(10), lab, rotation='vertical')
82    fig.subplots_adjust(bottom=0.2)
83    plt.show()
84
85 p = sess.run(probs, feed_dict={input_imgs: img})[0]
86 showresult(img,p)

代码运行后,如下结果:
[(249, '爱斯基摩犬 哈士奇    ', 0.35189062), (251, '哈士奇     ', 0.34352344), (250, '雪橇犬 阿拉斯加爱斯基摩狗  ', 0.007250515), (271, '白狼 北极狼    ', 0.0034629034), (175, '挪威猎犬     ', 0.0028237076), (538, '狗拉雪橇     ', 0.0025286602), (270, '灰狼     ', 0.0022800271), (274, '澳洲野狗 澳大利亚野犬    ', 0.0018357899), (254, '巴辛吉狗     ', 0.0015468642), (280, '北极狐狸 白狐狸    ', 0.0009330675)]
并得到可视化图片,如图12-1:
1.png
图12-1 PNASNet模型输出
图12-1中,左侧为输入的图片,右侧为其预测的结果。可以看到模型能够成功的预测出该图片内容是一只哈士奇狗。
代码实现:定义图片变化范围,并通过人工校验的方式调整参数
在制作样本时,不能让图片的变化太大。还要让图片在人眼看上去能够接收才行。这里需要手动设置阈值,限制图片的变化范围。然后将生成的图片显示出来,由人眼判断图片是否正常可用。确保没有失真。完整的代码如下:
代码12-1  在线性回归模型中添加指定节点到检查点文件(续)

1 def floatarr_to_img(floatarr):                                    #将浮点型转化为图片
2    floatarr=np.asarray(floatarr*255)
3    floatarr[floatarr>255]=255
4    floatarr[floatarr<0]=0
5    return floatarr.astype(np.uint8)
6
7 x = tf.placeholder(tf.float32, (image_size, image_size, 3))     #定义占位符
8 assign_op = tf.assign(input_imgs, x)                              #为input_imgs赋值
9 sess.run( assign_op, feed_dict={x: img})
10
11 below = input_imgs - 2.0/255.0                                  #定义图片的变化范围
12 above = input_imgs + 2.0/255.0
13
14 belowv,abovev = sess.run( [below,above])                        #生成阈值图片
15
16 plt.imshow(floatarr_to_img(belowv))                                #显示图片,用于人眼验证
17 plt.show()
18 plt.imshow(floatarr_to_img(abovev))
19 plt.show()

在代码第8行,为input_imgs赋值之后,才可以使用。因为到目前为止input_imgs还没有初始化,必须调用input_imgs.initializer或tf.assign为其赋值。这部分知识与《深度学习之TensorFlow:入门、原理与进阶实战》一书的3.3.8节相关。
这里设置的阈值是:每个像素上下变化最大不超过2(见代码11、12行)。经过代码运行后,输出的图片如图12-2、图12-3。
2.jpg
如图12-2、12-3所示,该图片完全在人类接收范围。一眼看去,就是一只哈士奇狗。
代码实现:用梯度下降方式生成攻击样本
与正常的网络模型训练目标不同,这里的训练目标不是模型中的权重,而是输入模型的张量。在12.2.1节中,生成模型的同时,已经将模型固定好(设为不可训练)。这样在模型训练的过程中,反向梯度传播的最终作用值就是输入的张量input_imgs了。
训练步骤与正常的网络模型一致,设定一个其它类别的标签。创建loss节点,令每次优化时,模型的输出都接近于设置的标签类别。完整的代码如下:
代码12-1  在线性回归模型中添加指定节点到检查点文件(续)

20 label_target = 880                                        #设定一个其它类别的目标标签
21 label =tf.constant(label_target)
22 #定义loss节点
23 loss = tf.nn.sparse_softmax_cross_entropy_with_logits(logits=logits, labels=[label])
24 learning_rate = 1e-1                                    #定义学习率
25 optim_step = tf.train.GradientDescentOptimizer(            #定义优化器
26    learning_rate).minimize(loss, var_list=[input_imgs])
27
28 #将调整后的图片,按照指定阈值截断
29 projected = tf.clip_by_value(tf.clip_by_value(input_imgs, below, above), 0, 1)
30 with tf.control_dependencies([projected]):
31    project_step = tf.assign(input_imgs, projected)
32
33 demo_steps = 400                                        #定义迭代次数
34 for i in range(demo_steps):                                #开始训练
35    _, loss_value = sess.run([optim_step, loss])
36    sess.run(project_step)
37
38    if (i+1) % 10 == 0:                                    #输出训练状态
39        print('step %d, loss=%g' % (i+1, loss_value))
40        if loss_value<0.02:                                #达到标准后,提前结束
41            break
代码运行后,输出如下结果:
step 10, loss=5.29815
step 20, loss=0.00202808
代码显示,仅迭代20次。模型即可达到了标准。在实际运行中,由于选用的图片,和指定的其它类别不同。迭代次数有可能不同。
代码实现:用生成的样本攻击模型
接下来就是最有意思的环节了。用训练好的攻击样本来攻击模型。实现起来非常简单,直接将input_imgs最为输入,运行模型。具体代码如下:
代码12-1  在线性回归模型中添加指定节点到检查点文件(续)

42 adv = input_imgs.eval()                         #获取图片
43 p = sess.run(probs)[0]                            #得到模型结果
44 showresult(floatarr_to_img(adv),p)                #可视化模型结果
45 plt.imsave('dog880.jpg',floatarr_to_img(adv))    #保存模型

代码运行后,如下结果:
[(880, '伞     ', 0.9981244), (930, '雪糕 冰棍 冰棒   ', 0.00011489283), (630, '唇膏 口红    ', 8.979097e-05), (553, '女用长围巾     ', 4.4915465e-05), (615, '和服     ', 3.441378e-05), (729, '塑料袋     ', 3.353129e-05), (569, '裘皮大衣     ', 3.0552055e-05), (904, '假发     ', 2.2152075e-05), (898, '洗衣机 自动洗衣机    ', 2.1341652e-05), (950, '草莓     ', 2.0412743e-05)]
并得到可视化图片,如图12-4:
3.jpg
图12-4 模型识别攻击样本的结果
从输出结果和图12-4的显示可以看出。模型已经把哈士奇当作了伞。

连载3.rar (1.21 MB, 下载次数: 76)
回复

使用道具 举报

匿名  发表于 2019-3-22 17:02:11
初一看感觉数据源如果被污染了那就太可怕了。
仔细一想这也是网络进化的动力。
如此想来以后数据集的训练不仅仅直接训练了
如果不加入对抗训练很危险啊,如果model泄露了就悲剧了
鉴于目前基本上都是在现有的model上微调的。
攻击应该具有普片意义。胡言乱语几句勿喷!
回复

使用道具

127

主题

308

帖子

989

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
989
 楼主| 发表于 2019-7-25 07:21:51 来自手机 | 显示全部楼层
游客 222.66.93.x 发表于 2019-3-22 17:02
初一看感觉数据源如果被污染了那就太可怕了。
仔细一想这也是网络进化的动力。
如此想来以后数据集的训练不 ...

是的。在这本书里还有更多的例子。可以看到模型还是很脆弱的。
来自: 微社区
回复

使用道具 举报

127

主题

308

帖子

989

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
989
 楼主| 发表于 2019-7-25 07:23:44 来自手机 | 显示全部楼层
除了这种白盒攻击。黑箱攻击更为可怕。书里也给出了一个代码演示。这种技术对于用ai来做权限管理的场景是致命的。
来自: 微社区
回复

使用道具 举报

127

主题

308

帖子

989

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
989
 楼主| 发表于 2019-8-1 05:36:57 | 显示全部楼层
微信群链接已经失效。请加微信:elexment  申请进入微信群
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

Archiver|手机版|小黑屋|大蛇智能 ( 京ICP备 18026897 号 )

GMT+8, 2020-2-27 08:48 , Processed in 0.040432 second(s), 27 queries .

Powered by Discuz! X3.4

© 2001-2017 Comsenz Inc.

快速回复 返回顶部 返回列表