Kaggle竞赛方案分享:如何分辨杂草和植物幼苗

1,109 阅读8分钟
原文链接: mp.weixin.qq.com
来源:Medium 编译:Bing

编者按:本文是Kaggle的一项挑战赛——Plant Seedings Classification的解决方案,作者Kumar Shridhar最终排名第五。其中的方法非常通用,可以用在其他图像识别任务上。

任务概览

你能分清楚杂草和庄稼苗吗?

如果能高效识别杂草,就能有效地提高粮食产量,更好地管理环境。Aarhus University Signal Processing和University of Southern Denmark共同合作,发布了一份含有12种植物的数据集,其中共有将近960棵植株,分别处于不同的生长阶段。

其中一个样本植物

该数据集目前已经公开,其中的RGB图像都经过了标注,其中物理分辨率大约为每毫米10像素。下面是数据集中12种植物的样本示例:

要将每张图片分到各自的类别中,这一任务可以分成5步:

第一步

首先,机器学习中最重要的任务是分析数据集,在开始着手设计算法前,理解数据集的复杂程度是非常重要的。

数据集中各类图片的分布如下所示:

如之前所提到的,这里总共有12种植物的类型,总共有4750张照片。然而,从上图我们可以看出各种植物的分类并不平均,有些种类里有654张图片,而有的只有221张。这充分说明了数据是不平衡的,在第三步时我们会解决这一问题。

图片种类分布

现在将图片进行可视化能更好地理解数据。下面的图片将每类植物都挑选了12张,互相对比看看它们之间都有什么差别。

图中的各种植物看起来都长得很像,只看图片也没什么特别之处。所以我决定用可视化技术t-SNE对图像分类进行处理。

t-SNE是适用于高维数据集的降维技术,它可以通过Barnes-Hut技术应用到大型真实数据集上。论智君也曾报道过相关资讯:

数据集的t-SNE可视化

通过近距离观察,我们很难看出各类之间的差异。所以重要的是弄清楚数据只是对人来说难以分辨还是对机器学习模型也很难分辨。所以我们需要为此制定一个基础标准。

训练和验证集

在开始对模型设定基础标准之前,我们需要把数据分成训练集和验证集两部分。一般来说,模型首先在训练集上训练,之后在验证集上测试,并随着时间在验证集上不断提高性能。当我们得到满意的验证集的结果后,就可以将模型应用到真实的测试集上,看模型是否过度拟合或欠拟合,从而进行调整。

我们将数据集中的4750张图片中的80%用作训练集,20%用作验证集。

第二步

有了训练集和验证集,我们就开始设立数据集的基准。在这一任务中,我们将用到卷积神经网络架构。如果你是个初学者,建议先阅读有关深度学习基础知识的文章:深度学习入门笔记

创建CNN模型的方法有很多,我们选择了Keras深度学习库。从头开始训练一个CNN效率非常低,所以我们选择了一个在ImageNet上进行预训练的模型权重,将其进行微调后加以训练。其中顶层是用来学习简单基础特征的,所以无需训练可以直接应用。需要注意的是,我们要检查一下我们的数据集和ImageNet之间的相似性,以及我们的数据集有多大。这两个特征将决定着我们应该如何进行调整。可以阅读Andrej Karpathy的文章了解更多细节:cs231n.github.io/transfer-learning/

在本次任务中,我们的数据集较小,但是和ImageNet很相似。所以我们首先可以直接用ImageNet的权重,然后在最后加入一个带有12种植物种类的输出层,得出第一个基准。之后我们再解锁下面的几层并进行训练。

我们用Keras建立最初的基准,因为Keras能提供一些预训练模型,我们选择其中的ResNet50和InceptionResNetV2。

同样,我们可以根据在ImageNet数据集上检测这些模型的性能和各模型参数的数量来选择基准模型。

对于第一个基准,我删除了最后的输出层,加上了一个有12个种类的输出层。具体如下所示:

模型经历了10次迭代,在第6次后结果达到饱和。训练精确度达到了88%,验证精确度达到了87%。

为了进一步提高性能,有一些底部的层没有被锁定,其中的学习速率呈指数衰减。最终将性能提高了两个百分点。

以下是这一过程中使用的超参数:

第三步

有了基础标准之后,我们就要基于此改善模型。我们可以从增强更多数据开始,从而增加数据集中图像的数量。毕竟数据是机器学习之本。

但是之前我们提到,数据是不平衡的,我们需要对其进行处理。

真实的数据集从来都是不平衡的,而模型在小型种类上的表现并不会很好。所以将少数种类中的数据错分为正常样本所付出的代价比正常分类错误要更高。

所以为了让数据平衡,通常有以下两种方法:

1.ADASYN算法。ADASYN可以对拥有较少样本的种类合成数据,其核心思想是对不同的拥有少数样本的种类根据学习难易程度进行加权分布,其中学习难度更高的种类合成的数据越多,容易学习的种类数据越少。因此,ADASYN方法用两种改变数据分布的方式提升了学习性能:(1)减少分类不平衡引起的偏差,(2)自适应地将分类决策边界移向困难的样本。

2.SMOTE算法。SMOTE算法是对少类进行过采样或者下采样来得到最佳结果。通过对少数样本进行过采样,同时对多数类别进行下采样可以让分类器得到最佳水平。

在这一情况下,SMOTE比ADASYN表现得更好。数据集平衡后,我们可以进行数据增强处理,所用方法有以下几种:

  • 尺度变换

  • 裁剪

  • 翻转

  • 旋转

  • 平移

  • 添加噪声

  • 改变光线条件

  • GAN

第四步

为了进一步提高性能,我们要对学习率进行改进。在这之前,首先需要找到模型的最佳学习速率是多少。这就需要在学习速率和损失函数之间绘图,看看损失从哪开始减少。

在我们的案例中,1e-1看上去是完美的学习速率,但是当我们越来越接近全局最小值,我们就想迈出更小一步。其中一个方法是学习速率退火(learning rate annealing),但是我用的是热重启(warm restart)。同样,优化器从Adam换成了SGD,并安装了SGDR。

现在,我们要用以上技术训练多个架构,然后将结果融合在一起,这被称为模型集成。虽然这种方法已经很普遍了,但是却十分耗费计算量。所以我决定用快照集成法(snapshot ensembling),即训练单个神经网络进行集成,并让它在优化过程中收敛到几个局部最小值,节省模型参数。

搞定了学习速率方法后,我开始调整图像尺寸。我训练了一个模型,其中图像尺寸为64×64(在ImageNet上进行微调),解锁一些图层后,应用了循环学习速率和快照集成,取模型的权重,将尺寸改变成299×299,再根据64×64的权重进行微调,之后进行快照集成和热重启。

第五步

最后一步是将结果进行可视化从而确定哪一种类有最佳表现(或最差表现),还需要做些其他调整来提高结果。理解结果的一种好方法是建立一个混淆矩阵。

我们可以看到模型预测的标签和真实标签的不同,我们可以慢慢改善这一状况。我们还可以做更多数据增强的工作,让模型学习更多种类。

方案提交后,我的排名位列第一(但随着竞赛展开,目前位列第五)。

原文地址:medium.com/neuralspace/kaggle-1-winning-approach-for-image-classification-challenge-9c1188157a86