了解如何使用 TensorFlow 对图像进行分类

创建一个简单而强大的神经网络,使用开源 TensorFlow 软件库对图像进行分类。
566 位读者喜欢这篇文章。
3 cool machine learning projects using TensorFlow and the Raspberry Pi

Opensource.com

深度学习算法和硬件性能的最新进展,使研究人员和公司能够在图像识别、语音识别、推荐引擎和机器翻译等领域取得巨大进步。六年前,首次实现了视觉模式识别方面的超人性能。两年前,Google Brain 团队发布了 TensorFlow,巧妙地将应用深度学习推广到大众。TensorFlow 的发展速度超过了许多用于深度学习的复杂工具。

借助 TensorFlow,您将可以访问功能强大且复杂的功能。其强大功能的核心在于 TensorFlow 的易用性。

在一个分为两部分的文章系列中,我将解释如何快速创建一个用于实际图像识别的卷积神经网络。计算步骤是极易并行化的,可以部署用于逐帧视频分析,并扩展用于时序感知的视频分析。

本系列文章直接切入最引人入胜的内容。只需对命令行和 Python 有基本的了解,您就可以在家中跟着操作。本系列旨在帮助您快速入门,并激发您创建自己的精彩项目。我不会深入探讨 TensorFlow 的工作原理,但如果您渴望了解更多,我将提供大量额外的参考资料。本系列中的所有库和工具都是免费/自由/开源软件。

工作原理

本教程的目标是获取一张新颖的图像,该图像属于我们训练过的类别,并运行一个命令,告诉我们该图像属于哪个类别。我们将遵循以下步骤

opensource.com

  1. 标记是管理训练数据的过程。对于花卉,雏菊的图像被拖入“daisies”文件夹,玫瑰的图像被拖入“roses”文件夹,以此类推,可以根据需要标记多种不同的花卉。如果我们从不标记蕨类植物,分类器将永远不会返回“蕨类植物”。这需要每种类型的大量示例,因此这是一个重要且耗时的过程。(我们将使用预先标记的数据开始,这将使速度更快。)
  2. 训练是指我们将标记的数据(图像)馈送到模型。工具将抓取随机批次的图像,使用模型猜测每张图像中的花卉类型,测试猜测的准确性,并重复此过程,直到使用大部分训练数据。最后一批未使用的图像用于计算训练模型的准确性
  3. 分类是在新颖的图像上使用模型。例如,输入:IMG207.JPG,输出:daisies。这是最快、最简单的步骤,并且易于扩展。

训练和分类

在本教程中,我们将训练一个图像分类器,以识别不同类型的花卉。深度学习需要大量的训练数据,因此我们需要大量的已排序花卉图像。值得庆幸的是,另一位好心人出色地完成了收集和排序图像的工作,因此我们将使用此已排序数据集和一个巧妙的脚本,该脚本将采用现有的、完全训练好的图像分类模型,并重新训练模型的最后一层,使其仅执行我们想要的操作。这种技术称为迁移学习

我们正在重新训练的模型称为 Inception v3,最初在 2015 年 12 月的论文“Rethinking the Inception Architecture for Computer Vision”中指定。

在我们进行此训练之前,Inception 不知道如何区分郁金香和雏菊,这需要大约 20 分钟。这是深度学习的“学习”部分。

安装

迈向机器智能的第一步:在您选择的平台上安装 Docker

第一个也是唯一的依赖项是 Docker。这在许多 TensorFlow 教程中都是如此(这应该表明这是一个合理的入门方法)。我也更喜欢这种安装 TensorFlow 的方法,因为它通过不安装一堆依赖项来保持您的主机(笔记本电脑或台式机)的清洁。

引导 TensorFlow

安装 Docker 后,我们就可以启动 TensorFlow 容器进行训练和分类了。在您的硬盘驱动器上的某个位置创建一个工作目录,其中有 2 GB 的可用空间。创建一个名为 local 的子目录,并记下该目录的完整路径。

docker run -v /path/to/local:/notebooks/local --rm -it --name tensorflow 
tensorflow/tensorflow:nightly /bin/bash

以下是该命令的分解。

  • -v /path/to/local:/notebooks/local 将您刚刚创建的 local 目录挂载到容器中的一个方便位置。如果使用 RHEL、Fedora 或其他启用 SELinux 的系统,请附加 :Z 以允许容器访问该目录。
  • --rm 告诉 Docker 在我们完成时删除容器。
  • -it 连接我们的输入和输出,使容器具有交互性。
  • --name tensorflow 为我们的容器命名为 tensorflow,而不是 sneaky_chowderhead 或 Docker 可能为我们选择的任何随机名称。
  • tensorflow/tensorflow:nightly 表示运行 Docker Hub(公共镜像仓库)中 tensorflow/tensorflownightly 镜像,而不是 latest(默认情况下,是最近构建/可用的镜像)。我们使用 nightly 而不是 latest 是因为(在撰写本文时)latest 包含一个错误,该错误破坏了 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,则表示您没有正确的文件。如果上述 curlsha1sum 步骤失败,请手动下载并解压 训练数据 tarball (SHA-1 校验和:db6b71d5d3afff90302ee17fd1fefc11d57f243f) 到主机上的 local 目录中。

现在将训练数据放入到位,然后下载并健全性检查重新训练脚本。

mv flower_photos.tgz local/
cd local
curl -O https://raw.githubusercontent.com/tensorflow/tensorflow/10cf65b48e1b2f16eaa826d2793cb67207a085d0/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:并非所有参数都在字符串格式化期间转换 从文件记录
tf_logging.py,第 82 行
.

随着 retrain.py 的进行,训练图像会自动分为训练、测试和验证数据集的批次。

在输出中,我们希望获得较高的“训练准确率”和“验证准确率”以及较低的“交叉熵”。有关这些术语的详细说明,请参阅如何为新类别重新训练 Inception 的最后一层。预计在现代硬件上训练大约需要 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 run 未终止,以保持此容器运行。

bust photo of Adam Monsen, technology professional
Adam Monsen 是 C-SATS 的工程副总裁,他在那里领导所有硬件和软件工作,以评估和改进医疗保健专业人员。Adam 也是 SeaGL(西雅图 GNU/Linux 会议)的联合创始人。个人博客 Twitter GitHub 工作

15 条评论

我尝试获取 retrain.py 脚本,但收到“No such file or directory”消息。
此外,“labeling”一词似乎被误用了。这似乎是通过将图像分配到特定目录来对图像进行分类,但图像未被标记。当我使用 Shotwell 并将标签附加到图像时,那才是标记。

嗨,Greg,感谢阅读我的文章。您是否在容器内运行了“curl”命令?

关于标记,将目录本身视为“标签”或“标记”。概念相同。

我不知道那是什么意思,也不知道为什么会有所不同。另一个 curl 命令运行没有问题。据我所知,curl 应该可以独立工作,无论有没有容器。

回复 作者 meonkeys

我找到了问题所在。获取 retrain.py 的 curl 命令中间有一个换行符,这意味着您无法复制它,然后将其粘贴到命令行并使其正常工作。我必须将其粘贴到文本编辑器中,然后将行合并为一行,然后再复制该行。

回复 作者 meonkeys

嗨,Adam,

感谢您的文章...我对以下命令有点困惑
docker run -v /path/to/local:/notebooks/local --rm -it --name tensorflow
这是否意味着“/path/to/local:/notebooks/local”是我的本地计算机上“local”文件夹的路径?当我运行该命令时,它会拉取 tensorflow 镜像并将我定位在临时名称下(例如 root@b4d5c077eecc:/notebooks#),如果我尝试通过以下方式将包含花卉图像的存档移动到“local folder”:
mv flower_photos.tgz local/
它告诉我没有这样的目录....

可能是什么问题?..
提前感谢...

嗨,Oleksiy,我们尝试使用“-v”参数执行的操作是将主机上的目录映射到容器内的目录。“/path/to/local”是您应该更改为您的主机上名为“local”的目录的实际绝对路径。“/notebooks”是您 exec 进入容器时最终到达的位置,“/notebooks/local”将在容器和主机上同时可用。这有帮助吗?

回复 作者 Oleksiy (未验证)

嗨,Oleksiy,不客气!感谢阅读。

-v 参数用于指定 Docker 卷挂载。它由两部分组成,用冒号分隔。HOST_PATH:CONTAINER_PATH。

将“/path/to/local”更改为您在主机上创建的“local”目录的绝对路径。如果您的当前工作目录是“/home/user”并且您在其中创建了一个“local”目录,则您的 docker run 命令行将包含“-v /home/user/local:/notebooks/local”。

请注意,您还必须从容器内部下载 flower_photos.tgz tarball。请参阅“训练模型”中的此步骤。

我在以下位置遇到错误:
curl -O https://raw.githubusercontent.com/tensorflow/tensorflow/10cf65b48e1b2f1…
6d2793cb67207a085d0/tensorflow/examples/image_retraining/retrain.py
echo 'a74361beb4f763dc2d0101cfe87b672ceae6e2f5 retrain.py' | sha1sum -c

...我手动输入了这些内容(没有遗漏任何字母或数字),并在 retrain.py 之前尝试了不同的空格...

为什么路径如此像机器代码般难以理解...它来自哪里?

因此,卡在这里一直令人失望,因为我的目标是自始至终跟随操作。请指教

期待第 2 部分,我想现在应该已经发布了...

当我在我的 Macbook 中尝试时,docker 默认会设置 2G 内存,这不足以运行训练。在我的笔记本电脑中,docker 在运行训练时会重启。所以我将 docker 内存设置为 3.5G,似乎一切正常。
感谢这篇文章。

感谢这个良好的起点。我应该在跟随操作之前阅读评论,因为我被 path_to_local 部分绊倒了,并且不知道我的路径最终在哪里,所以我无法复制测试图像以与 classify.py 一起使用

训练似乎运行良好。

我必须重复它。在我这样做之前,有没有办法获得一个像样的主机名和容器名称,而不是类似:cca8370680ae 的名称

容器名称将是“tensorflow”,因为我们将其传递给“--name”参数。我不知道如何控制 Docker 容器主机名或 ID。

回复 作者 wb greene (未验证)

知识共享许可协议本作品根据知识共享署名-相同方式共享 4.0 国际许可协议获得许可。
© . All rights reserved.