>综合>狗狗>

狗狗的品种分类:使用深度学习对狗狗品种进行分类

时间:2024-09-13 17:35:22/人气:288 ℃

斯坦福狗品种数据集的图片预览

问题介绍

几天前,我发现了由Kaggle主办的一个“狗狗品种识别”挑战赛。 这个比赛的目标是建立一个模型,使能够通过“观察”狗狗的图像来对狗进行品种分类。 我开始思考一些可行的建模方法以及这些模型可能实现的准确度。 据我所知,利用像TensorFlow这样的流行机器学习框架、开源数据集以及用于图像识别的预训练模型,可以很好地完成这个任务,而不需要花费太多的时间和资源。 我将再次分享我使用TensorFlow构建狗狗品种分类器的端到端流程。

训练数据集

一个好的训练数据集能帮助我们向建立稳健模型迈出重要的一步。 我们手头拥有的数据是斯坦福大学的狗狗数据集,包含120个品种的狗的共20K张图像。 数据集中的每个图像都被标注了一种狗的品种。 但是正如我们注意到,仅仅120个不同品种共20K个图像(相当于每个品种约200个图像)是不足以用来训练深度神经网络的。 尽管卷积神经网络(CNN)是目前用于图像分类的最好的机器学习模型,在这种情况下,没有足够的训练样例来训练它,我们是无法从这个数据集中通过机器学习得到足够的通用模型来识别不同的犬种。这很有可能导致模型对少量训练样例的过度拟合,因此测试集的准确性会很低。 针对这种情况,我们有两种可行的方法来减轻训练样例过少带来的不足:

  1. 将狗狗数据集与另一个更大的图像数据集(比如ImageNet),并用这些合并后的样例来训练一个CNN。

  2. 取一个已经预先用更大数据集训练好的深度神经网络模型,在其中附加一个额外的“分类标头”,即额外的几个带有Softmax层的完全连接层 。

第一种方法有两大缺点:需要我们进行分析的数据量比原始数据集要大得多,对这个新的大数据集的训练需要占用更多的时间和资源。

第二种方法似乎更有可能实现,模型的训练需要用原始数据集进行,并且由于只有几个完全连接层的“分类标头”,模型的训练将不需要占用大量时间和资源。

以上这种将有带“分类标头”的预训练模型附加到较小的数据集上的方法,我们称为转移学习。

简而言之,利用大数据集训练的深层神经网络的底层层级可以捕获一个图像的低级图元(例如轮廓和简单形状),它学到的这些知识对于所有图像是通用的并且可以被“转移”到任何图像识别问题中。

神经网络模型

最终的神经网络模型如下:

假设一个图像被输入到Inception模型中。 Inception模型的输出经过几个完全连接(FC)层,最后经由softmax输出该图像属于每一个类别的概率。 只有FC层代表“分类标头”必须接受训练。 而初始模型在已经预定义的模型参数下保持冻结。

下载并准备数据

下一步是下载狗狗数据集,并通过Google Inception模型进行预训练。 从repo的根目录处执行setup/setup.sh脚本命令将帮助我们下载所有内容,提取并放入适当的目录。 一旦下载并提取狗狗数据集,我们将会得到一组包含图像和注释的文件夹。 TensorFlow有一个漂亮的数据集API,可以更好地帮助我们处理TF记录数据格式问题。 这个想法是把所有的训练样例和他们的注释一起保存在一个文件中,所有的例子都以protobuf序列化的形式存储。 TensorFlow数据集API可以高效地处理这种数据格式,并在训练过程中尽可能多地加载所需的示例,同时使用最少的磁盘I / O操作和内存要求。 有一个python脚本,可以将原始的狗狗数据集转换为TF记录文件,准备用于训练:

这个命令必须从repo的根目录执行。数据集转换可能需要约1小时。每个图像都被输入到Inception模型中,并且输出的图像将与其他图像和其他注释一起存储。 这简化了训练,因为我们不需要在训练期间为每个例子计算初始输出,而是已经预先计算好以便使用。 TF记录文件的结果将在data/stanford.tfrecords中。 setup.sh脚本还会下载并提取TensorFlow图形的Google Inception模型并将其冻结。 冻结意味着模型中所有的变量都被替换为常量并嵌入到图形本身中,因此不需要将检查点文件与图形一起携带,就可以将模型加载到TensorFlow会话中并开始使用它。 Inception模型可用于frozen/inception/classify_image_graph_def.pb.

模型训练

下一步是实际执行培训。 首给模型起一个独一无二的名字。 其次应该配置这些层级中完整连接的层数和单元数量。 这些都可以在src/common/consts.py模块中配置。

默认情况下一般有2个完全连接的层级分别为1024单元和120单元。输入层有2048个单位,与Inception模型最后一层的单位数相等。

我们可以实用src/training/train.py中的代码进行培训。 学习速度,时代数量和每批量大小可以在脚本中配置:

此外,我们可以启动TensorBoard对训练进行监控:

这里有三个可用的度量标准:

成本,测试集上的错误以及训练集上的错误。

默认情况下,错误率是按照训练集中有3000个例子来计算的。我用了以下的超参数训练模型:

小批量大小= 64

学习率= 0.0001

时代数= 5000

以下是我在TensorBoard获得的这三个指标的数字:

成本

测试集错误

训练集错误

执行5K个时期需要约1小时。 训练结束后,指标具有以下值:

成本= 0.1

测试错误= 2.7%

训练错误= 2.5%

在测试和训练集中,这两个错误都相当低。 由于训练集上的误差与测试集上的误差大致相同,因此训练集没有明显的过度训练现象。

冻结模型

一旦模型被训练好,其优化参数就存储在./checkpoints目录中的检查点文件中。 为了有效地重新使用该模型进行推断分析,将其作为一个冻结的TensorFlow图,再将参数嵌入到图本身中是非常好的。 这可以使用src/freeze/freezy.py来完成:

这个脚本按以下顺序做了几件事情:

将Inception模型和“分类标头”模型加载到同一个TensorFlow会话中,并将它们组合到一个单一的计算图中,以便将来自Inception模型的输出直接输入到“分类标头”模型的输入中。 绑定完成后,脚本会将文件系统中图形中的复合模型序列化。 此时,由于在训练期间计算的模型参数仍然位于检查点文件中,所以图表还没有被冻结。

使用TensorFlow freeze_graph函数冻结上一步生成的图形。 它实际上从检查点文件中取出模型参数并将它们注入到图形变量中。 图形变量轮流转换为常量。 生成的文件将转到带有模型名称的./frozen目录。

推断分析

一旦冻结的模型准备好,我们就可以对任意图像进行分类了。src/inference/classify.py脚本能够对存储在文件系统上的狗图像进行分类,或者可以将其用作HTTP资源。 在幕后,它加载冻结图并将图像输入到该图中。 这里有两个例子说明如何推理“Airedale Terrier”(万能㹴)和“Shih-Tzu”(西施犬、狮子狗):

Airedale Terrier

Shih-Tzu

如果你只是想了解推理分析是如何进行的,有一个docker container <https://hub.docker.com/r/kirillpanarin/dog_breed_classification/> 包含了所有的代码和冷冻模型包装。 它使用Python笔记本做推断。 它实际上拥有所有的设置,甚至在docker container本身进行培训。 可以使用以下命令启动:

一旦container开始导航到浏览器<http://localhost:8888/notebooks/Inference.ipynb>,你将能够进行你自己的图像分类。

错误分析

我提议我们应该仔细研究机器学习模型未能正确进行分类的例子。

脚本src/analysis/training_perf_analysis.py能够为所有训练实例生成具有预测和实际品种的CSV文件

通过从training_confusion.csv加载数据,可以绘制混淆矩阵:

在这里对如此多品种进行详细的分析是困难的。 让我们试着找出30个错误分类的品种(Confusion.ipynb提供了一个如何做到这一点的例子):

可以看出,这对“Silky Terrier / Yorkshire Terrier”(丝毛梗/约克夏梗)在错误分类数量方面领先。如果我们看看这两种狗的样子,就能够理解这是为什么了:

Yorkshire Terrier

Silky Terrier

你是个爱狗人士吗?

如果你认为自己是一个爱狗人士,你可以问问你的模型你是什么品种的狗 : )

在我的情况下,我得到了以下答案:

迷你杜宾犬

结论

正如我们所看到的,即使你没有足够的训练图像和/或计算资源,如果你有预训练好的深度神经网络和像TensorFlow一样的现代机器学习库,你也可以训练出稳健的图像分类器。

免责声明:转载自网络 不用于商业宣传 版权归原作者所有 侵权删

首页/电脑版/地图
© 2024 CwBaiKe.Com All Rights Reserved.