《AI安全之对抗样本入门》—3.6 使用预训练模型

举报
华章计算机 发表于 2019/06/17 18:23:13 2019/06/17
【摘要】 本节书摘来自华章计算机《AI安全之对抗样本入门》一书中的第3章,第3.6节,作者是兜哥。

3.6 使用预训练模型

在对深度学习模型生成对抗样本时,我们会经常使用预训练好的模型。主流的深度学习框架为了方便用户使用,都积极开放了经典模型以供下载。其中最多的还是机器视觉相关的图像分类与目标识别模型,比如:

ResNet50

VGG16

InceptionV3

下面我们将举例介绍如何使用预训练模型对指定的图片进行分类预测,预测的主角是一头小猪(见图3-9)。

from IPython.display import Image,display

path = "../picture/pig.jpg"

display(Image(filename=path))

1. 使用Keras进行图片分类

Keras的应用模块Application提供了带有预训练权重的Keras模型,这些模型可以用来进行预测、特征提取。模型的预训练权重将下载到~/.keras/models/并在载入模型时自动载入。

 image.png

图3-9 小猪示例图片

加载需要的Python库,并对图像进行预处理。使用基于Imagenet数据集训练的ResNet50模型,图片大小转换成(224, 224),由于是彩***片,事实上输入模型的图片形状为(224, 224, 3)。

from keras.applications.resnet50 import ResNet50

from keras.preprocessing import image

from keras.applications.resnet50 import preprocess_input, decode_predictions

import numpy as np

model = ResNet50(weights='imagenet')

img_path = path

img = image.load_img(img_path, target_size=(224, 224))

x = image.img_to_array(img)

x = np.expand_dims(x, axis=0)

x = preprocess_input(x)

对图片进行预测,打印top3的预测结果,预测概率最大的是hog,即猪。

preds = model.predict(x)

print('Predicted:', decode_predictions(preds, top=3)[0])

Predicted:

[('n02395406', 'hog', 0.98398596),

('n02396427', 'wild_boar', 0.0074134255),

('n03935335', 'piggy_bank', 0.006954492)]

2. 使用PyTorch进行图片分类

PyTorch通过torchvision库封装了对预训练模型的下载和使用,这些模型可以用来进行预测、特征提取。模型的预训练权重将下载到~/.torch/models/并在载入模型时自动载入。

加载需要的Python库,并对图像进行预处理。使用基于Imagenet数据集训练的ResNet50模型,图片大小转换成(224, 224),由于是彩***片,并且PyTorch在处理图片格式时信道放在第一个维度,所以事实上输入模型的图片形状为(3, 224, 224)。需要特别指出的是,PyTorch加载预训练模型后默认是训练模式,所以在进行图片预测时需要手工调用eval方法进入预测模式,关闭反向传递。

import os

import numpy as np

import torch

import torch.nn

import torchvision.models as models

from torch.autograd import Variable

import torch.cuda

import torchvision.transforms as transforms

from PIL import Image

#手工调用eval方法进入预测模式

resnet50=models.resnet50(pretrained=True).eval()

img=Image.open(path)

img=img.resize((224,224))

img = np.array(img).copy().astype(np.float32)

在Keras处理图片时,我们没有进行任何标准化的处理,这是因为这一步被Keras的keras.applications.resnet50.preprocess_input封装了,而在PyTorch中需要我们手工进行标准化。

mean = [0.485, 0.456, 0.406]

std = [0.229, 0.224, 0.225]

img /= 255.0

img = (img - mean) / std

img = img.transpose(2, 0, 1)

img=np.expand_dims(img, axis=0)

img = Variable(torch.from_numpy(img).float())

对图片进行预测,预测标签索引是341,对应的是hog,即猪。

label=np.argmax(resnet50(img).data.cpu().numpy())

print("label={}".format(label))

label=341

预测的标签与分类物体名称的对应关系可以参考下列内容。

https://s3.amazonaws.com/deep-learning-models/image-models/imagenet_class_index.json

也可以使用PyTorch的API完成从分类标签值到物品名称之间的转换。

print('Predicted:', decode_predictions(resnet50(img).data.cpu().numpy(),

top=3)[0])

Predicted:

[('n02395406', 'hog', 15.661886),

('n02396427', 'wild_boar', 10.353137),

('n03935335', 'piggy_bank', 10.098382)]

3. 使用MXNet进行图片分类

MXNet通过gluon库封装了对预训练模型的下载和使用,这些模型可以用来进行预测、特征提取。模型的预训练权重将下载到~/.mxnet/models/并在载入模型时自动载入,更多模型可以参考以下链接。

http://mxnet.incubator.apache.org/versions/master/api/python/gluon/model_zoo.html

加载需要的Python库,并对图像进行预处理。使用基于Imagenet数据集训练的ResNet50模型,图片大小转换成(224, 224),由于是彩***片,并且MXNet在处理图片格式时信道放在第一个维度,所以事实上输入模型的图片形状为(3, 224, 224)。

from mxnet import gluon

import mxnet as mx

from mxnet.gluon import nn

from mxnet import ndarray as nd

from mxnet import autograd

import numpy as np

resnet=mx.gluon.model_zoo.vision.resnet50_v2(pretrained=True)

img=Image.open(path)

img=img.resize((224,224))

img = np.array(img).copy().astype(np.float32)

MXNet对图像的预处理与Pytorch一样需要手工进行。

mean = [0.485, 0.456, 0.406]

std = [0.229, 0.224, 0.225]

img /= 255.0

img = (img - mean) / std

img = img.transpose(2, 0, 1)

对图片进行预测,预测标签索引是341,对应的是hog,即猪。

img=np.expand_dims(img, axis=0)

array = mx.nd.array(img)

outputs=resnet(array).asnumpy()

label = np.argmax(outputs)

print(label)

4. 使用TensorFlow进行图片分类

TensorFlow的模型多以pb文件形式保存。以Inception为例,模型文件为pb格式,其中的classify_image_graph_def.pb 文件就是训练好的Inception模型,imagenet_synset_to_human_label_map.txt是类别文件。

 

wget

http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz

tar -zxvf inception-2015-12-05.tgz

x classify_image_graph_def.pb

x cropped_panda.jpg

x imagenet_2012_challenge_label_map_proto.pbtxt

x imagenet_synset_to_human_label_map.txt

x LICENSE

图片数据的预处理在Inception的计算图中完成。

path = "../picture/pig.jpg"

image_data = tf.gfile.FastGFile(path, "rb").read()

加载pb文件,在会话中还原完整的计算图以及网络中的各层参数。

session=tf.Session()

def create_graph(dirname):

    with tf.gfile.FastGFile(dirname, 'rb') as f:

        graph_def = session.graph_def

        graph_def.ParseFromString(f.read())

        _ = tf.import_graph_def(graph_def, name='')

create_graph("models/classify_image_graph_def.pb")

session.run(tf.global_variables_initializer())

获取输入节点和输出节点,运行计算图获得结果,预测标签是hog,即猪。

logits=session.graph.get_tensor_by_name('softmax/logits:0')

x = session.graph.get_tensor_by_name('DecodeJpeg/contents:0')

predictions=session.run(logits,feed_dict={x:image_data})

predictions = np.squeeze(predictions)

top_k = predictions.argsort()[-3:][::-1]

for node_id in top_k:

      human_string = node_lookup.id_to_string(node_id)

      score = predictions[node_id]

      print('%s (score = %.5f)' % (human_string, score))

以下代码展示了一个技巧,可以把pb文件的结构打印出来,有利于识别整个计算图的输入/输出。

tensorlist=[n.name for n in session.graph_def.node]

print(tensorlist)

TensorFlow还提供了大量ckpt格式的预训练模型,也需要手工下载后加载使用。ckpt文件相当于只保存了网络的参数,如果要完整使用,需要自行定义网络的结构。

wget http://download.tensorflow.org/models/resnet_v2_50_2017_04_14.tar.gz

tar -zxvf resnet_v2_50_2017_04_14.tar.gz

TensorFlow提供了大量工具函数便于使用预训练模型,需要单独安装并设置到系统路径。

git clone https://github.com/tensorflow/models/

通常设置系统路径最简单的方式是在代码里指定,比如:

sys.path.append("models/models/research/slim/")

TensorFlow通过slim定义了大量常见的网络结构,以resnet为例,就在slim/nets/resnet_v2完成了其网络定义。

from nets import resnet_v2

slim对数据预处理以及归一化做了封装,可以直接调用相应的API完成。TensorFlow的预训练模型在预测时需要显式指定is_training=False来关闭反向传递。

path = "../picture/pig.jpg"

image = tf.image.decode_jpeg(tf.gfile.FastGFile(path,'rb').read(), channels=3)

image_size = resnet_v2_50.default_image_size

processed_image = inception_preprocessing.preprocess_image(image, image_size,

image_size, is_training=False)

processed_images  = tf.expand_dims(processed_image, 0)

使用tf.train.Saver从ckpt文件中加载网络参数值,需要指出的是resnet_v1版本是从Caffe转换得来的,resnet_v2版本是Google自己训练的,物体类别不是1000而是1001。

with slim.arg_scope(resnet_v2.resnet_arg_scope()):

    logits, _ = resnet_v2.resnet_v2_50(processed_images, num_classes=1001,

is_training=False)

probabilities = tf.nn.softmax(logits) 

saver=tf.train.Saver()

with tf.Session() as sess:

     saver.restore(sess,'models/resnet_v2_50/resnet_v2_50.ckpt')

然后输入图像数据,运行计算图进行预测。

np_image, probabilities = sess.run([image, probabilities])

probabilities = probabilities[0, 0:]

sorted_inds = [i[0] for i in sorted(enumerate(-probabilities), key=lambda x:x[1])]

输出对应的预测结果,预测为猪的概率为99.08%。

Probability 99.08% => [hog, pig, grunter, squealer, Sus scrofa]

Probability 0.84% => [piggy bank, penny bank]

Probability 0.03% => [wild boar, boar, Sus scrofa]

Probability 0.01% => [French bulldog]

Probability 0.01% => [hippopotamus, hippo, river horse, Hippopotamus amphibius]

值得一提的是,slim封装了将标签数据转换成物体名称的操作,省去了手工解析的过程。

names = imagenet.create_readable_names_for_imagenet_labels()

for i in range(5):

    index = sorted_inds[i]

print('Probability %0.2f%% => [%s]'

                  % (probabilities[index] * 100,  names[index]))


【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

举报
请填写举报理由
0/200