【干货】TensorFlow实战——图像分类神经网络模型
Learn how to classify images with TensorFlow
使用TensorFlow创建一个简单而强大的图像分类神经网络模型
by Adam Monsen
▌引言
由于深度学习算法和硬件性能的快速发展,研究人员和各大公司在图像识别,语音识别,推荐引擎和机器翻译等领域取得了长足的进步。六年前,在计算机视觉领域首先出现重大突破,这其中以CNN模型在ImageNet数据集上的成功为代表。两年前,Google Brain团队开源TensorFlow,使得我们可以灵巧快速地开发自己的深度学习模型。 目前来看, TensorFlow已经超越许多其他深度学习的工具库。
TensorFlow可以赋予你强大的能力,其具有良好的易用性,使你轻松实现各种复杂功能。
本文由两部分组成,我将解释如何快速创建用于实际图像识别的卷积神经网络。当然该网络还可以对视频中的逐帧图像进行分析,从而扩展基于时间序列的视频分析。
本文提供你最需要的干货,你只需要了解一些命令行和Python的基础知识就行了。 本系列目的在于让你快速动手,并激励你创造属于自己的新项目。限于篇幅,我不会深入探讨TensorFlow的工作原理,但如果你想了解更多,我会提供大量额外的参考资料。本系列中的所有库和工具都是免费的、开源的。
▌它是怎么工作的
我们在本教程中的目标是:通过一个命令给出一个新图像属于哪个类别,我们将按照以下步骤操作:
1.标注(Labeling)是对训练数据进行管理的过程。比如对于花卉,为了根据需要挑选出不同类别的花朵,我们要将雏菊的图像归入“雏菊”类,将玫瑰归入“玫瑰”类等等。当然如果我们不给任何图像贴上“蕨类植物”的标签,分类器将永远不会返回“蕨类植物”。因此这个过程需要每个类型的很多例子,故而是很重要并且耗时的一步。(我们将从已经标记的数据着手,这使我们处理数据的速度更快。)
2.训练(Training)的过程是在我们标注的数据(图像)的基础上,使用某种工具随机抓取其中的一些数据(图像),然后输入到模型中,再使用模型来猜测每种花的类型并且测试猜测的准确性,重复这一过程直到大部分训练数据都被使用。最后一批未使用的图像(测试集)用于检验训练模型的准确性。
3.分类(classification)使用模型分类新图像。例如,输入:IMG207.JPG,输出:雏菊。这是最快,最简单的一步。
▌训练和分类
在本教程中,我们将训练一个图像分类器来识别不同类型的花朵。 深度学习需要大量的训练数据,所以我们需要大量的不同种类的花的图像。值得庆幸的是,已经有人在收集和分类图像方面做得非常出色,所以我们将使用整理好的数据集,采取一个现有的,完全训练的图像分类模型,并重新训练模型的最后一层,来做我们想要的任务。 这种技术被称为迁移学习(transfer learning)。
我们正在重新训练的模型叫做Inception v3,这个模型在2015年12月的论文"Rethinking the Inception Architecture for Computer Vision."中首次提出。
模型训练之前我们不知道如何从雏菊分辨出郁金香,训练模型大约花费了20分钟。 这是深度学习的“学习”部分。
- 安装
第一步,机器感知:在您选择的平台上安装Docker。在许多TensorFlow教程中,安装Docker都被认为是最合理的选择。 我也喜欢这种安装TensorFlow的方法,因为它不安装一堆依赖项从而保持主机的清洁。
- TensorFlow向导
安装Docker后,我们准备启动一个TensorFlow容器进行训练和分类。在您的硬盘驱动器上创建一个有2G空闲空间的工作目录。另外再创建一个名为local的子目录,并记下该目录的完整路径。
docker run -v /path/to/local:/notebooks/local --rm -it --name tensorflow
tensorflow/tensorflow:nightly /bin/bash
下面是该命令的详细解释。
-v / path / to / local:/ notebooks / local将刚刚创建的本地目录装载到容器中合适的位置。 如果使用RHEL,Fedora或其他支持SELinux的系统,请附加Z到刚才的位置从而允许容器访问目录。
--rm告诉Docker在完成后删除容器。
-它附加我们的输入和输出,与容器交互。
--name tensorflow给我们的容器命名tensorflow,而不是sneaky_chowderhead或其他我们随机选择的名字。
tensorflow / tensorflow:nightly,从Docker Hub(一个公共图像库)运行tensorflow / tensorflow的nightly图像,而不使用最新的图像(默认情况下,使用最近构建的/可用的图像)。
我们之所以使用nightly图像而不是最近获得的图像,是因为最近获得的图像包含一个bug导致TensorBoard出问题,其中TensorBoard又是一个数据可视化工具,我们稍后会介绍。
/ bin / bash表示不要运行Bash shell这个默认命令。
- 训练模型
在容器内,运行下面的命令下载和检查训练数据。
curl -O http://download.tensorflow.org/example_images/flower_photos.tgz
echo 'db6b71d5d3afff90302ee17fd1fefc11d57f243f flower_photos.tgz' | sha1sum -c
如果你没有看到flower_photos.tgz:OK的消息,那么你就没有得到正确的文件。 如果上述curl或sha1sum步骤失败,请手动下载并分解本地目录中的训练数据tarball(SHA-1 checksum: db6b71d5d3afff90302ee17fd1fefc11d57f243f)。
现在把训练数据放在原处,然后下载并且检查再训练的脚本。
mv flower_photos.tgz local/
cd local
curl -O https://raw.githubusercontent.com/tensorflow/tensorflow/10cf65b48e1b2f16eaa82
6d2793cb67207a085d0/tensorflow/examples/image_retraining/retrain.py
echo 'a74361beb4f763dc2d0101cfe87b672ceae6e2f5 retrain.py' | sha1sum -c
为了确认retrain.py的内容是否正确。你应该看到:retrain.py: OK. 当看到这个命令时,说明成功了。
最后,该进行模型学习了! 运行再训练脚本。
python retrain.py --image_dir flower_photos --output_graph output_graph.pb
--output_labels output_labels.txt
如果遇到下面这个错误,请忽略它:
TypeError: not all arguments converted during string formatting Logged from file
tf_logging.py, line 82.
随着retrain.py的进行,训练图像会自动分成训练、测试和验证数据集。
在输出中,我们希望高的“训练准确性”和“验证准确性”,以及低的“交叉熵”。 有关这些术语的详细解释,请参阅How to retrain Inception's final layer for new categories。在最新硬件上的训练需要大约30分钟。
注意你控制台输出的最后一行:
INFO:tensorflow:Final test accuracy = 89.1% (N=340)
这说明我们已经有了一个模型,有近九成的把握猜出给定图像是五种花型中的哪一种。 由于训练过程中数据输入的随机性,您的准确性可能会有所不同。
- 分类:
再加上一个脚本,我们可以将新的花朵图像添加到模型中,并输出它的类别。这是图像分类过程。
将以下内容命名为classify.py并保存在主机的local目录中:
import tensorflow as tf, sys
image_path = sys.argv[1]
graph_path = 'output_graph.pb'
labels_path = 'output_labels.txt'
# Read in the image_data
image_data = tf.gfile.FastGFile(image_path, 'rb').read()
# Loads label file, strips off carriage return
label_lines = [line.rstrip() for line
in tf.gfile.GFile(labels_path)]
# Unpersists graph from file
with tf.gfile.FastGFile(graph_path, 'rb') as f:
graph_def = tf.GraphDef()
graph_def.ParseFromString(f.read())
_ = tf.import_graph_def(graph_def, name='')
# Feed the image_data as input to the graph and get first prediction
with tf.Session() as sess:
softmax_tensor = sess.graph.get_tensor_by_name('final_result:0')
predictions = sess.run(softmax_tensor,
{'DecodeJpeg/contents:0': image_data})
# Sort to show labels of first prediction in order of confidence
top_k = predictions[0].argsort()[-len(predictions[0]):][::-1]
for node_id in top_k:
human_string = label_lines[node_id]
score = predictions[0][node_id]
print('%s (score = %.5f)' % (human_string, score))
为了测试你的图像,把图片保存为test.jpg到你的local目录,并运行python classify.py test.jpg。 输出结果如下所示:
sunflowers (score = 0.78311)
daisy (score = 0.20722)
dandelion (score = 0.00605)
tulips (score = 0.00289)
roses (score = 0.00073)
模型表明有78.311%把握确定图像中的花是向日葵。 较高的分数表示匹配正确的可能性越大。 注意,这里只能匹配上一个标签多标签分类需要使用其他的方法。
更多详细信息,请查看classify.py的更多解释。
分类器脚本中的图像加载代码不能使用了,所以我用了graph_def = tf.GraphDef()代码来加载图像。
我们使用少量的代码创造了一个合适的花朵图像分类器,在笔记本电脑上每秒处理大约五个图像。
在下周发布的这个系列的第二部分中,我们将使用这些信息来训练一个不同的图像分类器,然后用TensorBoard来查看分类器内的内容。 如果你想尝试TensorBoard,那就需要确保docker运行没有停止。
原文链接:https://opensource.com/article/17/12/tensorflow-image-classification-part-1!
- 译文 | 在使用过采样或欠采样处理类别不均衡数据后,如何正确做交叉验证?
- 花式解释AutoEncoder与VAE
- 用CNN做句子分类:CNN Sentence Classification (with Theano code)
- MySQL与Python的交互
- 实时Android语音对讲系统架构
- ElasticSearch优化系列二:机器设置(内存)
- Tensorflow之 CNN卷积神经网络的MNIST手写数字识别
- 你听过算法也是可以贪心的吗?
- 前后端分离ueditor富文本编辑器的使用-Java版本
- Golang语言社区--Go语言基础第六节函数
- Golang语言社区--理解 go interface 的 5 个关键点
- 得到一个物种所有基因的TSS(转录起始位点)区域的bed文件。
- 如何选择聚类模块数目
- 谁能告诉我,这数据测毁了么?
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- ubuntu配置tftp服务的步骤小结
- CentOS7下GitLab跨大版本升级的方法
- 解决Linux system v 共享内存问题
- Linux下core文件的使用方法详解
- 使用Kubeadm在CentOS7.2上部署Kubernetes集群的方法
- linux systemctl命令详解
- CentOS7使用dnf安装mysql的方法
- Linux中crontab定时任务不执行的原因
- Linux系统为什么要吃掉我的“内存”
- 教你如何修改Linux远程登录欢迎提示信息
- 详解linux 定时任务 crontabs 安装及使用方法
- 解决Centos7安装nginx后提示“Welcome to nginx on Fedora!”,conf.d目录下无default.conf文件
- 详解Linux中PostgreSQL和PostGIS的安装和使用
- 检测ip和port是否可连接的方法
- Linux关机时执行指定脚本功能实现