页面树结构

2017-11-09 ApacheCN 开源组织,第二期邀请成员活动,一起走的更远 : http://www.apachecn.org/member/209.html


MachineLearning 优酷地址 : http://i.youku.com/apachecn

转至元数据结尾
转至元数据起始

现代物体识别模型具有数百万个参数,可能需要几周才能完全训练。转移学习是一种技术,可以通过为一组类别(如ImageNet)采用训练有素的模型来快速完成此项工作,并从新课程的现有权重训练。在这个例子中,我们将从头开始重新培训最后一层,同时让所有其他层次不变。有关该方法的更多信息,您可以在Decaf上看到 本文

虽然它不如全面的训练运行,但对于许多应用来说,这是非常有效的,可以在笔记本电脑上运行三十分钟,而无需GPU。本教程将向您展示如何在自己的图像上运行示例脚本,并将介绍一些帮助控制培训过程的选项。

鲜花培训

 图片由Kelly Sikkema

在开始任何培训之前,您需要一组图像来教导网络了解您想要识别的新课程。稍后部分将介绍如何准备自己的图片,但为了方便我们创建一个创意公共档案,授权的花卉照片最初使用。要获取一组花卉照片,请运行以下命令:

cd ~
curl -O http://download.tensorflow.org/example_images/flower_photos.tgz
tar xzf flower_photos.tgz
一旦你拥有这些图像,你可以从你的TensorFlow源目录的根目录下建立这样的retrainer:
bazel build tensorflow/examples/image_retraining:retrain
如果您有一台支持AVX指令集的机器 (在过去几年生产的x86 CPU中常见),您可以通过构建该架构来提高重新培训的运行速度(在选择适当的选项之后configure):
bazel build --config opt tensorflow/examples/image_retraining:retrain
然后,retrainer可以像这样运行:
bazel-bin/tensorflow/examples/image_retraining/retrain --image_dir ~/flower_photos
该脚本加载预先训练的Inception v3模型,删除旧的顶层,并在您下载的花卉照片上列出一个新的。没有一个花种在原始的ImageNet类中完整的网络被训练了。转移学习的神奇之处在于,经过培训以区分某些对象的较低层可以重用于许多识别任务而无需任何更改。

 

瓶颈

根据机器的速度,脚本可能需要三十分钟以上才能完成。第一阶段分析磁盘上的所有映像,并计算其中每个映像的瓶颈值。“瓶颈”是我们经常用于实际进行分类的最终输出层之前的层的非正式术语。这个倒数第二层已被训练,以输出一组足够好的值,以便分类器用于区分所有被要求识别的类。这意味着它必须是一个有意义和紧凑的图像摘要,因为它必须包含足够的信息,使分类器在一个很小的值集合中做出了很好的选择。

因为每个图像在训练过程中被重复使用多次,所以每个瓶颈都需要花费大量的时间,因此可以加快缓存这些瓶颈,从而不必重复计算。默认情况下,它们存储在/tmp/bottleneck目录中,如果您重新运行脚本,那么它们将被重用,因此您不必再等待此部分。

 

训练

瓶颈一旦完成,网络顶层的实际训练便开始了。您将看到一系列步进输出,每个输出显示培训准确性,验证准确性和交叉熵。培训准确性显示当前培训批次中使用的图像的百分比是否以正确的类标记。验证精确度是来自不同集合的随机选择的图像组的精度。关键的区别在于训练准确性是基于网络能够学习的图像,因此网络可能会超过训练数据中的噪声。对网络性能的真正测量是测量其不包含在训练数据中的数据集的性能 - 这是通过验证精度来衡量的。如果火车的精度很高,但是验证精度仍然很低,那意味着网络过度拟合并且记住训练图像中更为普遍无益的特定特征。交叉熵是一种损失函数,可以看出学习过程进展情况如何。培训的目标是使损失尽可能小,所以您可以通过关注损失是否向下倾斜,忽略短期噪音来判断学习是否正常工作。

默认情况下,该脚本将运行4000个培训步骤。每个步骤从训练集中随机选择十个图像,从缓存中发现其瓶颈,并将它们馈送到最后一层以获得预测。然后将这些预测与实际标签进行比较,以通过反向传播过程更新最终层的权重。随着流程的继续,您应该看到报告的准确性提高,并且在所有步骤完成后,最终的测试精度评估运行在与培训和验证图片分开的一组图像上。该测试评估是对训练后的模型如何在分类任务上执行的最佳估计。您应该看到准确度在90%到95%之间,尽管由于训练过程中的随机性,确切的值会因运行而异。

 

用TensorBoard可视化再训练

该脚本包括TensorBoard摘要,使其更容易理解,调试和优化再培训。例如,您可以可视化图形和统计信息,例如训练过程中权重或准确度的变化。

要启动TensorBoard,请在重新培训期间或之后运行此命令:

tensorboard --logdir /tmp/retrain_logs
一旦TensorBoard运行,浏览您的网页浏览器localhost:6006来查看TensorBoard。

 /tmp/retrain_logs默认情况下,脚本将记录TensorBoard摘要。您可以使用该--summaries_dir标志更改目录。

TensorBoard README对TensorBoard使用了大量的信息,包括提示和技巧,和调试信息。

 

使用再培训模型

该脚本将写入一个Inception v3网络的版本,最后一个图层将再次引导到/tmp/output_graph.pb的类别,以及一个包含/tmp/output_labels.txt标签的文本文件。这些都是C ++和Python图像分类示例 可以读取的格式,因此您可以立即开始使用新模型。由于您已经替换了顶层,因此您需要在脚本中指定新名称,例如,--output_layer=final_result如果使用label_image,则使用该标志。

以下是一个示例,说明如何使用重新训练的图形来构建和运行label_image示例:

bazel build tensorflow/examples/label_image:label_image && \
bazel-bin/tensorflow/examples/label_image/label_image \
--graph=/tmp/output_graph.pb --labels=/tmp/output_labels.txt \
--output_layer=final_result \
--image=$HOME/flower_photos/daisy/21652746_cc379e0eea_m.jpg 
您应该看到一个花标签的列表,大多数情况下,雏菊位于顶部(尽管每个再培训的模型可能略有不同)。您可以--image使用自己的图像替换 参数,以尝试这些,并使用C ++代码作为模板与您自己的应用程序集成。

如果您想在Python程序中使用重新培训的模型,则@ eldor4do中的示例将显示您需要执行的操作

 

对自己的类别进行培训

如果您已经设法使脚本在花样例图像上工作,那么您可以开始考虑教导它来识别您关心的类别。理论上,你需要做的就是将它指向一组子文件夹,每个子文件夹都以你的类别命名,并且只包含该类别的图像。如果你这样做,并将子目录的根文件夹作为参数传递给 --image_dir,脚本应该像花朵一样训练。

以下是花档案的文件夹结构如何,给出您和脚本正在寻找的布局类型的示例:

在实践中,可能需要一些工作来获得所需的准确性。我会尝试引导您了解下面可能遇到的一些常见问题。

 

创建一套训练图像

开始的第一个方面是查看您收集的图像,因为我们看到的最常见的问题是来自所提供的数据。

为了训练好,你应该收集至少一百张你想要识别的物体的照片。您可以收集的越多,训练有素的模型的准确性越好。您还需要确保照片是您的应用程序实际遇到的很好的表示。例如,如果您将所有照片都放在空白的墙壁上,并且您的用户正在尝试在户外识别对象,则在部署时可能看不到很好的结果。

要避免的另一个缺陷是,学习过程将会拾取标签图像彼此共同的任何东西,如果您不小心可能是没有用的东西。例如,如果你在一个蓝色的房间里拍摄一种物体,另一种是绿色的,那么模型将最终基于背景颜色,而不是你实际关心的对象的特征。为避免这种情况,请尽可能在各种情况下,在不同的时间和不同的设备拍摄照片。如果您想了解更多有关此问题的信息,您可以阅读有关经典(或可能的伪造) 油罐识别问题

您可能还想考虑您使用的类别。这可能是将大量不同的物理形式分解成更具视觉特征的小类。例如,而不是“车”,您可以使用“汽车”,“摩托车”和“卡车”。还有一个值得考虑的是你是否有“封闭的世界”或“开放的世界”的问题。在一个封闭的世界里,唯一要被分类的东西就是你所知道的对象类。这可能适用于植物识别应用程序,您知道用户可能正在拍摄花朵,所以您只需确定哪些物种。相比之下,漫游机器人可能会在世界各地漫游时通过其相机看到各种不同的东西。在这种情况下,要让分类器报告是否不清楚它是看到的。这可能很难做到,但是如果您收集大量典型的“背景”照片,但没有相关对象,则可以将其添加到图像文件夹中的额外“未知”类。

还要检查以确保所有图像的标签正确。通常,用户生成的标签对于我们的目的是不可靠的,例如使用#daisy作为名为Daisy的人的照片。如果您浏览图像并清除任何错误,它可以为您的整体准确性做出奇迹。

训练步骤

如果您对图像感到满意,可以通过更改学习过程的详细信息来改善结果。最简单的尝试是 --how_many_training_steps。默认为4,000,但如果将其增加到8000,则会训练两倍。精确度的提高速度减慢了训练的时间,并且在某些时候将会停止,但是您可以尝试看到当您对模型的限制。

 

扭曲

改进图像训练结果的一个常见方法是以随机方式变形,裁剪或增亮训练输入。这具有扩展训练数据的有效大小的优点,这归功于相同图像的所有可能的变化,并且倾向于帮助网络学习应对在分类器的现实使用中将发生的所有失真。在我们的脚本中启用这些失真的最大缺点是瓶颈缓存不再有用,因为输入图像从不重复使用。这意味着培训过程需要更长的时间,因此,我建议您尝试将其作为微调您的模型的一种方法,只要您有一个您相当满意的模式。

您可以通过将启用这些扭曲--random_crop--random_scale并 --random_brightness给脚本。这些都是控制每个失真应用于每个图像的多少百分比值。开始每个5或10的值是合理的,然后尝试看看哪些帮助您的应用程序。--flip_left_right会随机地将一半的图像水平地镜像,只要这些反转可能在您的应用程序中发生,这是有道理的。例如,如果您尝试识别信件不是一个好主意,因为翻转它们会破坏它们的意义。

 

超参数

还有几个其他参数可以尝试调整,以查看它们是否帮助您的结果。该--learning_rate控件更新到最后一层的训练过程中的大小。直观地说,如果这个更小,那么学习将需要更长时间,但最终可以帮助整体精度。这并不总是这样,所以你需要仔细地进行实验,看看你的案例有什么作用。该--train_batch_size控制在一个训练阶段多少图像进行检查,而且由于每批次应用于学习率,你需要减少它,如果你有更大的批量获得相同的整体效果。

 

训练,验证和测试集

当您将其指向图像文件夹时,脚本在引擎盖下执行的任务之一是将其分成三组。最大的通常是训练集,训练集中的所有图像都在训练期间进入网络,结果用于更新模型的权重。你可能会想知道为什么我们不使用所有的图像进行训练?当我们进行机器学习时,一个很大的潜在问题是,我们的模型可能只是记住训练图像的无关细节,以得出正确的答案。例如,您可以想象一个网络在每张照片的背景中记录了一个模式,并使用它来将标签与对象相匹配。它可以在训练过程中看到的所有图像产生良好的结果,但是在新的图像上失败,因为它'

这个问题被称为过度拟合,为了避免这种情况,我们将我们的一些数据保留在训练过程之外,以便模型无法记住它们。然后我们使用这些图像作为支票,以确保没有发生过度配对,因为如果我们看到它们的准确性很好,这是一个很好的迹象,网络不会过度配套。通常的分割是将80%的图像放入主要训练集中,保持10%在训练期间经常进行验证,然后将最终10%的图像用作测试集,以预测实时图像,分类器的世界表现。这些比例可以使用 --testing_percentage--validation_percentage标志来控制。一般来说,您应该可以将这些值保留为默认值,因为您通常不会发现任何培训调整优势。

请注意,脚本使用图像文件名(而不是完全随机的函数)在训练,验证和测试集之间划分图像。这样做是为了确保图像不会在不同运行的训练和测试集之间移动,因为如果用于训练模型的图像随后在验证集中使用,那么这可能是一个问题。

您可能会注意到验证精度在迭代之间波动。这种波动的大部分原因在于,为每个验证精度测量选择验证集的随机子集。通过选择--validation_batch_size=-1使用整个验证集合来进行每个精度计算,可以大大降低波动,代价是增加训练时间 。

一旦训练完成,您可能会发现在测试集中检查错误分类的图像很有见地。这可以通过添加标志来完成 --print_misclassified_test_images。这可能有助于您获得哪种类型的图像最容易模糊的感觉,哪些类别最难区分。例如,您可能会发现特定类别的某些子类型或某些异常的照片角度特别难以识别,这可能会鼓励您添加更多的该类型的训练图像。通常,检查错误分类的图像也可能指向输入数据集中的错误,例如错误标签,低质量或不明确的图像。然而,应该通常避免点测试测试集中的各个错误,因为它们可能仅仅反映在(更大的)训练集中更一般的问题。

 

  • 无标签