百度分狗大赛总结

某渣的闲时娱乐

Posted by XI Changzun on 2017-08-15

TL;DR

距离放弃比赛已经过去一周了,这一周真是过得浑浑噩噩:)

前言

从7.25到8.9号正式放弃比赛,前后三个礼拜,最终的成绩定格在0.189上:这是由一个0.192的inceptionV2的两个checkpoint和一个0.22的Densenet模型进行投票得到的结果。这个成绩实在说不上好,我自己也觉得还能更高。不过懒病发作,再加上多次改进看不到效果带来的挫败感让我早早放弃了比赛···虽然有遗憾,但是比赛重在参与,花在比赛上的这三个礼拜我觉得十分值得。乘着还没有把学到的经验全部忘掉的时候,赶紧记录一下这次百度分狗比赛的收获。

用过的模型和方法

图像分类比赛都是从寻找一个优秀的CNN网络开始的,可以说我60%的工作都花费在了这上面。起初情况还算顺利,师兄在TF上用slim库训练了一个InceptionV2,直接达到了0.192的单模型准确率(万万没想到这也是我们得到的最好的单模型······)从其他参赛队伍的反馈来看,一个单纯的特征提取CNN能达到这样的精度,已经很不错了。这个模型是我们直接使用inceptionV2的预训练模型在整个数据集上放开所有层进行微调得到的。使用Adam优化方法,1e-4的L2规则化项,133个类(即不做映射,其中33个类别无训练样本,实际仍为100类。),只对输入进行299的随即剪裁。随后我们又对InceptionV2的训练方案进行过多次调整,包括增加训练批次,对类别进行映射,对输入进行归一化,手动筛除噪声样本等等。结果····用这些方式训练得到的模型效果竟然都比第一次的差。也就是说,初始的的200个epoch是一个比较好的停止位置,过拟合并不严重。至于归一化,可能是数据量足够大,现在的CNN里又有大量的BN层,所以没有明显的影响。由于效果不好,我们又将噪声样本放回了训练集。

这一系列实验之后,师兄就退出战线找工作去了,鉴于我对TF不了解,之后所有的实验都在pytorch上进行了。可能是近两年大家的注意力都转向更加复杂的任务了,我对最新CNN的架构还停留在两年前名噪一时的Resnet和Inception上。结果发现这之后又出现了ResNext,DenseNet,和DPN等通用的CNN架构,于是好好恶补了一下。最后因为pytoch提供DenseNet的实现和与训练模型,我用DenseNet进行了试验(虽然DenseNet的pytorch实现叫人看不懂···)。初步的试验采用了和师兄相似的训练方案,不过由于我是坚定的SGD党,优化方法我采用了带动量和Nestov的SGD进行训练,并手动调整学习率。这也是大多数实现和论文中使用的优化方法,(之前在训练InceptionV2的时候也想说服师兄用SGD的方法,虽然没有成功)不过从这次的结果看来,两者的差别并不明显。Densenet模型最终的错误率停留在了0.22。不过叫人尴尬的是,训练集进度始终停留在0.92,无论增加epoch还是衰减学习率都无法再提高···起初我以为是模型能力不够(笑),狠狠地吐槽了一下Densenet的性能(其实还是训练地不充分)。从参赛群的反馈来看,这种精度的差异主要来自于Inception系列模型的原始输入较大,保留了更多的信息。这就是最终用于投票的三个模型的产生。因为不信任pytorch的实现,我又利用torch训练了官方实现的Densenet。torch版本的DenseNet也叫人失望,从验证集的精度看,和pytorch的结果没有明显的差别,所以也就没有进行测试上传(其实只是懒得写测试脚本···)。不满足于0.189的成绩,我又尝试了Dual Path Networks。本来对这个模型给予了很高的期望,无奈使用的是pytorch实现,并没有预训练模型,训练集加验证集一共又只有1w多张样本,训练了200个epoch后训练集精度仍然停留在88%的准确度上···到这里所有的单模型尝试算是彻底结束了,利用之前的结果做了投票模型之后,差不多就想放弃了。然而群里又放出了0.163的多模型融合的方法,让我又燃起了希望。虽然之前也查了多模型融合的一些方法,但是我仍然只尝试了最简单的投票模型。这个方法使用的是特征融合,效果居然如此的好。相较训练整个模型而言,这个方法只需要用预训练模型做特征提取,再训练一个简单的全链接层做分类就行,时间效率很高。我兴冲冲地用之前训练得到的DenseNet模型和DPN模型做融合,虽然在充满噪声的训练集上精度能轻松达到0.99,可线上结果却惨不忍睹。之后又相继融合了InceptionV3和Resnet的特征,精度虽然有所提高,却始终无法突破0.22的错误率。多模型融合后的特征有6k+维之多,一共60W+的参数,模型能够轻松的过拟合。所以我又尝试在特征之后加入0.05的超稀疏激活,每次只有约5%的特征(约300个特征)被传到全链接层。可是结果仍然是冰冷的0.22···而原作者叶发现无论是加DropOut,增加非线性性,做类别平衡,都没有明显的提升。仔细看了该方法后,发现原作者不仅仅是融合了特征,Inception模型和VGG都是融合得分类结果,经群里人的点拨后,这才知道原来多模型融合有这么多奇技淫巧,这里送上一篇有MSRA郑宇写的多模型融合的文章,读过文章后,我发现原来这种融合分类结果的方式叫做模型的语义融合。以上就是我参加比赛进行的所有尝试,写成文字,以作纪念。

比赛收获

  • 数据集较小时,应只训练模型的最后几层,即节省时间,又能降低训练难度。
  • 对于细粒度分类任务来说,越大的输入图像意味着保留越多的细节,能对精度有一定提高。
  • 图像分类问题应首先考虑集成学习。现在提供的预训练模型很多,集成模型的效果会在单模型的基础上有很大的提升。
  • 集成学习的方式包括特征融合,语义融合等等。可以直接在预训练模型上进行,无需针对数据集进行微调。
  • Batch Size不是越大越好,Batch Size过大会导致各个方向上的剃度相互抵消,使得收敛变慢,也使得模型无法拟合地更好。
  • 写程序一定要注意可维护性,方便以后的调试和修改。即使是做实验,如果一开始写得程序不够灵活,会极大地影响后续挑优的心情(也许我该去看看设计模式了)