本教程主要参考并大部分(代码全参考)知乎作者活鱼眼的教程,接下来还会有更多参考该作者学的东西。很棒的作者,在他的Github上有源码,以及YouTube视频教程
该篇参考代码:https://zhuanlan.zhihu.com/p/27017772
原作者Github地址:https://github.com/Hvass-Labs/TensorFlow-Tutorials
这里会用到作者之前写的一些代码,所以去Github下载的时候建议全部下载,如果你比较懒,可以去我的CSDN下载所有包。
----------------------------------进入主题------------------------------------------------------------
目的:
这篇教程演示了如何用一个预训练好的深度神经网络Inception v3来进行图像分类。
Inception v3模型在一台配有 8 Tesla K40 GPUs,大概价值$30,000的野兽级计算机上训练了几个星期,因此不可能在一台普通的PC上训练。我们将会下载预训练好的Inception模型,然后用它来做图像分类。
Inception v3模型大约有2500万个参数,分类一张图像就用了50亿的乘加指令。在一台没有GPU的现代PC上,分类一张图像转眼就能完成。
这篇教程隐藏了TensorFlow代码,因此可能不要求很多的TensorFlow经验,当然从之前的教程中学到一些对TensorFlow的基本理解还是很有帮助的,特别是在你想学习inception.py文件中的实现细节时。
流程图:
下面的流程图显示了Inception v3模型中的数据流向,这是一个带有许多层的,有着复杂结构的卷积神经网络。这篇论文里有Inception模型如何构造,以及为什么这么设计的更多细节。但作者也承认他们并不完全明白模型的工作原理。具体的结构可以参考文章点击打开链接
注意,Inception模型有两个softmax输出。一个是在训练神经网络时使用(Mixed-6e阶段使用),另一个是训练结束之后,在图像分类时使用,即推断阶段(inference)。
显示网络结构:这是在Jupyter下写的代码,并且要在你下载的代码包的位置打开Jupyter,如图:
在下载的文件里,有一个images文件,里面07是改网络的结构图,把它显示出来
from IPython.display import Image, display
Image('images/07_inception_flowchart.png') #在同一个目录下才可以不写绝对路径,否则出错
导入包:
%matplotlib inline
import matplotlib.pyplot as plt
import tensorflow as tf
import numpy as np
import os
# Functions and classes for loading and using the Inception model.
import inception
#这个inception文件也在同一目录下
顺便检查一下tensorflow版本号
tf.__version__
#检查tensorflow版本号
下载Inception模型
从网上下载Inception模型。这是你保存数据文件的默认文件夹。如果文件夹不存在就自动创建
inception.data_dir = 'inception/'
inception.maybe_download() # 下载V3模型包以及解压
#注意,这里如果下载出错,可以直接把文件复制进去(在其他地方已经下载好的)
Downloading Inception v3 Model ... Data has apparently already been downloaded and unpacked.
载入Inception模型
载入模型,为图像分类做准备。注意这些warning信息,以后可能会导致程序运行失败
model = inception.Inception()
我们可以去看一下inception.py文件里有些什么功能。
----------------以下代码分析作者写的inception文件里的功能,算是插入,不要带进你自己的代码--------------
1.从网上获取Google 预训练好的Inception下载地址,将下载好的数据保存在data_dir文件夹里边
data_url = "http://download.tensorflow.org/models/image/imagenet/inception-2015-12-05.tgz"
data_dir = "inception/"
# File containing the mappings between class-number and uid. (Downloaded) # 包含类号和uid之间的映射的文件。 path_uid_to_cls = "imagenet_2012_challenge_label_map_proto.pbtxt" # File containing the mappings between uid and string. (Downloaded) # 包含人类标签和uid之间的映射的文件。 path_uid_to_name = "imagenet_synset_to_human_label_map.txt" # File containing the TensorFlow graph definition. (Downloaded) # 包含TensorFlow 图文件 path_graph_def = "classify_image_graph_def.pb"
2.有一个maybe_download()函数,会调用download.py文件的下载方法,从而把inception网络下载下来。读者需要分清我们这个inception.py文件和Inception网络的区别,后者才是我们要进行图像分类的。
3.一个NameLookup的类,这个类(class)主要作用是查找每一类(共1000类)名字,因为文件里边将1000类都定义一个编号,我们需要输出的是名字而不是编号,最后得到3个映射关系:编码到类别、类别到编码、编码到名字之间的映射关系,
4.inception类
这一类主要就是调用原始模型进行分类,输出预测值等。其他的类暂不介绍。
------------------------------------------------继续---------------------------------------------------------
构造分类函数
# 分类以及绘制图像的帮助函数这,是一个简单的封装函数,它可以展示图像,然后用Inception模型进行分类,最终打印出分类评分。
def classify(image_path):
# Display the image.
display(Image(image_path))
# Use the Inception model to classify the image.
pred = model.classify(image_path=image_path)
# Print the scores and names for the top-10 predictions.
model.print_scores(pred=pred, k=10, only_first_name=True)
用自己的图去预测
# 对熊猫进行分类
#Inception数据文件中包含了这张熊猫图像。Inception模型相当确定这张图片上展示了熊猫,
#分类评分达到了89.23%,第二高的代表大狐猴的分数只有0.86%,这是另外一种外来动物。
image_path = os.path.join(inception.data_dir, 'cropped_panda.jpg')
classify(image_path)

分类评分的解释 Inception模型的输出是Softmax函数,这在之前教程中的神经网络中也有用到。
softmax输出有时也称为概率分布(probabilities),因为它介于零到一之间,然后相加为一,与概率分布相同。但它们并不是传统语义上的概率分布,因为并不是由重复试验得来。
将神经网络的输出值称为分类评分或排名可能会更好,因为结果显示了神经网络认为输入图像是每个可能分类的强度。
在上面的熊猫样本中, Inception模型给熊猫类型很高的分数—89.23%,同时其它999种类别的分数都在1%以下。这表示Inception模型十分确信图像展示了一只熊猫,而剩下1%以下的应该视为噪声。比如,排名第十高的分数是0.05%,代表电子手表,但它更可能是由于神经网络的不精准而不是暗示着图像看起来有点像电子手表。
有时Inception模型不确定图像属于哪一个分类,因此结果中并没有一个特别高的分数。下面会展示这种样本
#鹦鹉(原始图像)
#Inception模型十分确定(评分97.30%)这张图像展示了一种叫金刚鹦鹉的鹦鹉。
classify(image_path="images/parrot.jpg")

#鹦鹉(调整图像)
#Inception使用于299 x 299像素的输入图像。上面的鹦鹉图像实际上是320像素宽、785像素高的,因此它将由Inception模型自动缩放。
#现在我们想看看被Inception模型调整过的图像。
#首先我们实现一个帮助函数,用来从Inception模型内部获取调整过的图像。
def plot_resized_image(image_path):
# Get the resized image from the Inception model.
resized_image = model.get_resized_image(image_path=image_path)
# Plot the image.
plt.imshow(resized_image, interpolation='nearest')
# Ensure that the plot is shown.
plt.show()
现在画出调整过的鹦鹉图。这是Inception模型中神经网络的真正输入图像。 我们可以看到它被压缩成正方形,并且分辨率降低了,因此图像看起来更像素化和锯齿状。 这种情况下,图像仍然清晰地展示了一只鹦鹉,但一些图像经过(模型内)原生的调整后会变得扭曲,因此你可能会想自己调整图像大小,再输入到Inception模型。
plot_resized_image(image_path="images/parrot.jpg")

鹦鹉(裁剪图像,上方) 鹦鹉图像被手动裁剪成299 x 299像素大小,然后输入到Inception模型中,这时(模型)还是很确信(评分97.52%)输入图展示了一只鹦鹉(金刚鹦鹉)
classify(image_path="images/parrot_cropped1.jpg")
鹦鹉(裁剪图像,中间) 这是鹦鹉图的另一张裁剪图像,这次展示了鹦鹉的躯干,不包含头部和尾巴。Inception模型仍然很确定(评分94.22%)这是一只金刚鹦鹉。
classify(image_path="images/parrot_cropped2.jpg")

鹦鹉(裁剪图像,底部) 这次的裁剪图像只显示了鹦鹉的尾巴。现在Inception模型相当困惑,认为图像可能显示的是一只鶲鴷(评分26.11%),这是另一种外来鸟,也可能是一只草蜢(评分10.61%)。
Inception模型还认为图像有可能是一只钢笔(评分2%)。但这是一个很低的分数,应该解释成不可靠的噪声。
classify(image_path="images/parrot_cropped3.jpg")
鹦鹉(填充图像) 对Inception模型来说最好的输入图像方式,是先将图像填充成正方形,然后调整至299 x 299像素,在这样的鹦鹉样本中,模型正确分类并且评分达到96.87%。
classify(image_path="images/parrot_padded.jpg")

Elon Musk (299 x 299 像素) 这张图像展示了Elon Musk——活着的传奇,超级-书呆子-英雄。但Inception模型对图像显示的东西很困惑,它预测图像可能是一件运动衫(评分19.73%),或者是一件阿拉伯长袍(评分16.82)。它也认为图像可能是一个乒乓球(3.05%)或一个棒球(评分1.86%)。Inception模型很困惑,并且分类评分不可靠
classify(image_path="images/elon_musk.jpg")

之前下载的包里还有很多图片,感兴趣的可以都去做一下,这里就不举例了。最后
关闭TensorFlow会话现在我们已经用TensorFlow完成了任务,关闭session,释放资源。注意,TensorFlow-session是在模型内部的,因此我们通过模型来关闭它。
# This has been commented out in case you want to modify and experiment
# with the Notebook without having to restart it.
model.close()
总结
本教程说明了如何使用预训练的Inception v3模型。它在一台野兽级电脑上花了好几周才训练好。但我们可以从网上下载完成的模型,然后在一台普通PC上用它来做图像分类。
不幸的是,Inception模型对识别人物很有问题。这可能是所使用训练集的原因。新版的Inception模型也已经发布了,但它可能也是在同样的训练集上训练,对于识别人物还是有问题。希望未来的模型会训练来识别常见的物体,比如人类。
这篇教程中我们在inception.py文件中隐藏了TensorFlow的实现细节,因为它有点凌乱,我们可能在之后的教程中仍然会复用这个。希望TensorFlow的开发者会标准化、简单化API,使得更简单地载入这些预训练模型,这样,每个人只需要几行代码就能使用一个强大的图像分类器。