state-farm-distracted-driver-detection (Kaggle 比赛总结)

最近参加了Kaggle上的比赛state-farm-distracted-driver-detection,写一下近期比赛的收获,做一个总结。
对于图像的分类问题,几乎是离不开卷积神经网络,但是想要做好还是有很多讲究在里面。最开始我们根据论坛里的教程选用了VGG16的网络进行训练,不过VGG16的模型参数较多,训练速度太慢,一次训练需要好几个小时。而且由于参数较多,如果不基于Pre-training进行训练,基本上是没法收敛。认真阅读VGG的论文VERY DEEP CONVOLUTIONAL NETWORKS FOR LARGE-SCALE IMAGE RECOGNITION,有很多细节还是很有收获,VGG也不是直接训练得来的,是通过网络深度不断增加,每一次使用之前训练的较浅层网络来初始化参数,逐渐的加深网络得来。文中还提到了扩大图像尺寸的方法,在caffe中可以看到,VGG网络的输入是224x224,输入图片一般会缩放到256x256,然后通过看源码的这一段可以知道,在训练过程中是随机的从图片中截取224x224的大小进行训练,输出一般是取中间部分输出。

if (phase_ == TRAIN) {
      h_off = Rand(img_height - crop_size + 1);
      w_off = Rand(img_width - crop_size + 1);
    } else {
      h_off = (img_height - crop_size) / 2;
      w_off = (img_width - crop_size) / 2;
    }

对于这次比赛,图片的有效信息一般在右侧,所以我在开始的时候输出部分修改了一下位置,没有选择中间。后来朋友告诉我看到有论文说,输出的时候也随机选取区域,再对结果做平均效果会更好,修改了代码,实验确实有效果,不过输出真的是慢,TITANX做30次输出一共要1个小时左右。VGG的论文里还有提到用384x384,512x512的网络进行训练,然后再融合模型来提高精度,这个也确实很有用,不论是否选用VGG。比赛中我主要选择的Googlenet网络,增加了384x384的输入,效果比较明显,类似于256x256,网络的输入参数大小为336x336,和256x256一样,随机截取作为输入,第一个卷积层把stride改为3就可以。512x512的网络由于输入图片太大,只做了两次实验,一次是卷积大小依旧7x7,stride改为4,不成功。一次是加入两个5x5,stride为2的卷积层,依旧不行,然后就没再实验。
这次比赛主要使用的googlenet网络,之所以选这个是因为相对于VGG网络,googlenet收敛速度很快,计算量较小。基于Pre-training训练,基本上不用半小时就可以收敛,而且由于网络参数较少,googlenet可以不像VGG一样,直接训练也可以快速达到收敛。
开始训练googlenet的时候走了些弯路,因为valid test的选择不够准确,valid test几乎没有效果,所以没法很好的把握网络训练的情况,是否真的过拟合,是否是较好的输出点,都没法较好的观察。后来认真看了比赛题目,交叉验证集选取的时候根据每位驾驶员来分割,这样可以保证交叉验证集里的数据完全没有在训练集中出现,可以达到较好的效果。
googlenet为了加快反向传播的速度,在训练时取了三层输出计算loss值,当然在预测结果的时候也可以将这三层都作为输出,可以发现一般情况下第二层的输出结果较好,这说明训练集太少,对于深层的网络已经出现了比较严重的过拟合。通过修改caffe中data_transformer.cpp的代码,我增加了旋转缩放以及模糊的处理作为Data Augmentation 的方法,不过并没有达到非常明显的效果。这里只是说这些常规的方法效果不明显,Data Augmentation是必须的。后来看到大神分享的黑科技,他们将两幅同一类的图片随机左右切割,然后拼在一起作为训练数据,还有镜像数据等方式,单模型的输出竟然可以达到LB 0.15。感觉还是自己对神经网络的理解不够,有些数据扩大的方法一直没法理解。不过后来看了Learning Deep Features for Discriminative Localization这篇文章,这篇文章有点趣味性,他的将网络的最后几层做了修改,可以输出热成像图,这样可以观察到网络是根据那部分信息得到最后的分类结果。不过这部分其实意义并不大,论文提到将max pooling 层修改为average pooling,可以提高网络的localization能力,所以我修改了后面几层的网络结构开始训练,将训练的结果再放回到原来的GoogleNet中初始化权重,并且freeze了前几层的网络,最后单个模型的输出可以达到LB 0.2+的结果(没有做bagging,一次输出,单层结果)。GoogleNet的最后一个pooling层本来就是average pooling,不过大小是7x7,这篇论文中取了较浅层的输出,然后使用了14x14的average pooling,还是有一定区别。
后来也试过用三层的结果做平均,可以达到较好的效果,但是要对一个模型做bagging的话还是不要这样输出,会影响bagging的结果,但是如果要做一次输出,比如在一些实时性要求较高的问题中可以通过多层输出做平均来提高精度,而且计算时间也没有明显增多。
记得之前有看到论文说使用一个差不多较好的模型去预测测试集中的结果,并使用一小部分测试集结果中较好的部分加入到训练集中训练,通过这种方法来扩大数据集,尝试了之后对精度有一定提升,感觉这样做有点小作弊的嫌疑。后来对错误情况做了分析,发现10类的分类问题,主要有3类比较容易出错,而且即使是人去看有些也确实比较难分辨,所以对这几类做了单独的训练,不过可能是投入时间太少,效果并不好,没有继续尝试。
在模型融合方面主要参考了这篇文章,先后使用了平均,投票,投票再平均,最后的结论是平均效果最好。还是要多去看比赛规则,今天看了比赛规则,发现之前有些尝试根本就是没必要的。The submitted probabilities for a given image are not required to sum to one because they are rescaled prior to being scored (each row is divided by the row sum).
模型融合的时候对同一个模型做bagging,然后得到的模型再做average就可以达到较好的效果。最后我使用了VGG16,CAM+GoogleNet,256GoogleNet,384GoogleNet四个模型融合,在这次比赛中排名49/1450.
看了top20的参赛者分享的方法,我之前提到的test数据集做训练应该叫pedsuo label,很多人都有使用,而且有一位参赛者表示效果非常明显。其中第十的参赛者先做了检测,然后用检测的样本做训练,这样准确率更高(就像人脸识别一样,先做检测,对齐),不过这位兄弟也够给力的,自己做了很多手工的检测样本,之前我也有这么想过,不过后来一直在做网络优化忘记了- -。最后吐槽一下,前几名融合的模型好多呀,下次也多弄几个模型,找几个帮手。

评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值