《AI安全之对抗样本入门》—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/并在载入模型时自动载入。
图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]))
- 点赞
- 收藏
- 关注作者
评论(0)