黑马程序员技术交流社区

标题: 【上海校区】深度有趣 | 09 Inception-v3图片分类 [打印本页]

作者: 不二晨    时间: 2018-9-25 10:09
标题: 【上海校区】深度有趣 | 09 Inception-v3图片分类
简介Inception-v3是由Google提出,用于实现ImageNet大规模视觉识别任务(ImageNet Large Visual Recognition Challenge)的一种神经网络


Inception-v3反复使用了Inception Block,涉及大量的卷积和池化,而ImageNet包括1400多万张图片,类别数超过1000
因此手动在ImageNet上训练Inception-v3,需要耗费大量的资源和时间
这里我们选择加载pre-trained的Inception-v3模型,来完成一些图片分类任务
准备预训练好的模型共包括三个部分
例如,169对应n02510455,对应giant panda, panda, panda bear, coon bear, Ailuropoda melanoleuca
图片分类加载库
# -*- coding: utf-8 -*-import tensorflow as tfimport numpy as np复制代码整理两个映射文件,得到从类别编号到类别名的对应关系
uid_to_human = {}for line in tf.gfile.GFile('imagenet_synset_to_human_label_map.txt').readlines():        items = line.strip().split('\t')        uid_to_human[items[0]] = items[1]node_id_to_uid = {}for line in tf.gfile.GFile('imagenet_2012_challenge_label_map_proto.pbtxt').readlines():        if line.startswith('  target_class:'):                target_class = int(line.split(': ')[1])        if line.startswith('  target_class_string:'):                target_class_string = line.split(': ')[1].strip('\n').strip('\"')                node_id_to_uid[target_class] = target_class_stringnode_id_to_name = {}for key, value in node_id_to_uid.items():        node_id_to_name[key] = uid_to_human[value]复制代码加载模型
def create_graph():        with tf.gfile.FastGFile('classify_image_graph_def.pb', 'rb') as f:                graph_def = tf.GraphDef()                graph_def.ParseFromString(f.read())                _ = tf.import_graph_def(graph_def, name='')复制代码定义一个分类图片的函数
def classify_image(image, top_k=1):        image_data = tf.gfile.FastGFile(image, 'rb').read()        create_graph()        with tf.Session() as sess:                # 'softmax:0': A tensor containing the normalized prediction across 1000 labels                # 'pool_3:0': A tensor containing the next-to-last layer containing 2048 float description of the image                # 'DecodeJpeg/contents:0': A tensor containing a string providing JPEG encoding of the image                softmax_tensor = sess.graph.get_tensor_by_name('softmax:0')                predictions = sess.run(softmax_tensor, feed_dict={'DecodeJpeg/contents:0': image_data})                predictions = np.squeeze(predictions)                top_k = predictions.argsort()[-top_k:]                for node_id in top_k:                        human_string = node_id_to_name[node_id]                        score = predictions[node_id]                        print('%s (score = %.5f)' % (human_string, score))复制代码调用函数进行图片分类,指定参数top_k可以返回最可能的多种分类结果
classify_image('test1.png')复制代码分类结果如下
定制分类任务Inception-v3是针对ImageNet图片分类任务设计的,因此最后一层全连接层的神经元个数和分类标签个数相同
如果需要定制分类任务,只需要使用自己的标注数据,然后替换掉最后一层全连接层即可
最后一层全连接层的神经元个数等于定制分类任务的标签个数,模型只训练最后一层的参数,其他参数保持不变
保留了Inception-v3对于图像的理解和抽象能力,同时满足定制的分类任务,属于迁移学习的一种典型应用场景
TensorFlow官方提供了如何在Inception-v3上进行迁移学习的教程
www.tensorflow.org/tutorials/i…
所使用的数据包括五种花的拍摄图片
去掉最后一层全连接层后,对于一张图片输入,模型输出的表示称作Bottleneck
事先计算好全部图片的Bottleneck并缓存下来,可以节省很多训练时间,因为后续只需计算和学习Bottleneck到输出标签之间的隐层即可
TensorFlow官方提供了重训练的代码
github.com/tensorflow/…
在命令行中使用,一些可选的命令行参数包括
跑一下代码
python retrain.py --image_dir flower_photos --output_graph output_graph.pb --output_labels output_labels.txt --summaries_dir summaries_dir --model_dir .. --bottleneck_dir bottleneck_dir复制代码此处对于视频中内容的勘误
在校验集、测试集上的分类准确率分别为91%、91.2%
在我的笔记本上一共花了55分钟,其中44分钟花在了Bottleneck缓存上,但如果不缓存的话,训练过程中每次迭代都必须重复计算一遍
summaries_dir目录下的训练日志可用于TensorBorad可视化
tensorboard --logdir summaries_dir复制代码然后在浏览器中访问http://localhost:6006,即可看到可视化的效果,包括SCALARS、GRAPHS、DISTRIBUTIONS、HISTOGRAMS四个页面


如果需要完成其他图片分类任务,整理相应的标注图片,并以标签名作为子文件夹名称即可
如果要使用训练好的模型,参照以下代码即可
# -*- coding: utf-8 -*-import tensorflow as tfimport numpy as nplabels = []for line in tf.gfile.GFile('output_labels.txt').readlines():        labels.append(line.strip())def create_graph():        graph = tf.Graph()        graph_def = tf.GraphDef()        with open('output_graph.pb', 'rb') as f:                graph_def.ParseFromString(f.read())        with graph.as_default():                tf.import_graph_def(graph_def)        return graphdef read_image(path, height=299, width=299, mean=128, std=128):        file_reader = tf.read_file(path, 'file_reader')        if path.endswith('.png'):                image_reader = tf.image.decode_png(file_reader, channels=3, name='png_reader')        elif path.endswith('.gif'):                image_reader = tf.squeeze(tf.image.decode_gif(file_reader, name='gif_reader'))        elif path.endswith('.bmp'):                image_reader = tf.image.decode_bmp(file_reader, name='bmp_reader')        else:                image_reader = tf.image.decode_jpeg(file_reader, channels=3, name='jpeg_reader')        image_np = tf.cast(image_reader, tf.float32)        image_np = tf.expand_dims(image_np, 0)        image_np = tf.image.resize_bilinear(image_np, [height, width])        image_np = tf.divide(tf.subtract(image_np, [mean]), [std])        sess = tf.Session()        image_data = sess.run(image_np)        return image_datadef classify_image(image, top_k=1):        image_data = read_image(image)        graph = create_graph()        with tf.Session(graph=graph) as sess:                input_operation = sess.graph.get_operation_by_name('import/Mul')                output_operation = sess.graph.get_operation_by_name('import/final_result')                predictions = sess.run(output_operation.outputs[0], feed_dict={input_operation.outputs[0]: image_data})                predictions = np.squeeze(predictions)                top_k = predictions.argsort()[-top_k:]                for i in top_k:                        print('%s (score = %.5f)' % (labels, predictions))classify_image('test.jpg')复制代码参考


链接:https://juejin.im/post/5ba258ec5188255c38535a80




作者: 不二晨    时间: 2018-10-10 11:45
奈斯
作者: 魔都黑马少年梦    时间: 2018-11-1 16:36





欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2