来源:知乎
作者:@GaryLIU
图灵联邦编辑部
前言
本文作者@GaryLIU 从入坑kaggle到拿到GM仅用了一年多的时间,他表示自己的学习之路可以分成三个阶段,以下是他的经验分享。
Phase 1
去年9月中的时候,我刚上大四不久,之前一直对热衷于DL的我,其实都只是在自学一些理论知识,动手实践非常少,框架也只是会一些Tensorflow/Keras/sklearn之类的。
某一天无意只是想查一些项目的开源code,自己对着学习一下,就查到了kaggle,之前在kaggle也是有账号的,但只是为了下载Dog vs Cat的数据。
当时入坑的是TGS Salt Identification,一开始只能尝试着用keras去把开源kernel的代码跑一下,最后发现自己连改Unet换backbone都不会(之前都是白学了),就死皮赖脸的在讨论区发帖/水贴(参加过这个比赛的老师估计对我当时都有点印象),但幸运的是得到了许多非常热心的回答。慢慢地,对LB上分上了瘾。
从一点都不会用pytorch到学会用pytorch魔改Unet模型,自己一路上分到top20,真的是非常刺激。GPU机器都是自己花在校生活费在vast.ai上租的单卡1080ti。
有了第一次在TGS获取的top2%银牌,开始在一些老师脑海中留下了些印象,到了第二个比赛Doodle Recognition Challenge,当时就和杜老师在知乎上认识了,并且和吴老师也一起组上了队伍。当然,当时的我还是对很多都非常不懂的,只是在队伍里打打下手。
拿下第二个银牌升级为Expert title后,进入了华人Kagglers大群(当时expert是进群门槛,现在已经是master了),里面全是GM/Master/Expert大神,在群里向各位老师学习。后面寒假实习面试(鹅厂),遇到了Chen Joya师兄,虽然当时不match实习岗位,但是师兄挺欣赏我(师兄真的非常非常好人,感谢),私下给我提供4 * p40+4 * v100和我一起打比赛。
这个时候就是在Human Protein Atlas Image Classification和action(国内第一位本科应届生Grand Master)他们一起打了,拿下第一枚金牌。
kaggle Human Protein Atlas 比赛总结:
https://zhuanlan.zhihu.com/p/54743461
Phase 2
自己当时完全想不到自己有机会拿下金牌和Master title,在比赛里也认识到了涛哥(史上最快晋升GM的男人),杨老师等。在此阶段,和涛哥/action他们继续组队,或者和群里一些老师的讨论,主要是吸收/学习他们身上的一些调参和对数据的理解的经验。同时,自己也在相关岗位实习,做research,每天更是阅读许多论文,自己的能力在此阶段成长了许多。也在此阶段拿下了两块金牌,不过时间不等人,这个时候我刚好大学毕业了。
Phase 3
当觉得自己学习到一个程度,认为自己能够独当一面,可独立解决大部分问题的时候,这时我选择了solo,但发现solo确实是比组队辛苦很多的,无队友讨论,需要自己去挖掘idea等等。幸运的是,在此阶段拿下了一枚solo金和一枚team金,成功在一年后晋升自己以前想都不敢想的Grand Master。
分享初衷
1.鉴于国内竞赛的讨论氛围确实是非常的糟糕,同时不少小伙伴的英语阅读能力并非那么好,在kaggle经常阅读不太懂许多solution,或者不知道如何去使用kaggle,如何在这个平台上进行学习。
2.然后,希望能够分享自己在此期间学习到的一些皮毛知识给大家,让更多的小白能够很好的入门,也能拿到一枚金牌,回馈给社区。
All tricks:
1. 以下所有的一些方法,都是一些top选手常用的,如果你使用得当,银牌是非常稳的,然后自己再加把劲点,金牌都非常有机会的。可能不够全面或者有错误的,希望各位小伙伴一起观摩观摩,如有补充的,麻烦留下评论,或者私信我,我修改补充上去。
2. 基本都是CV任务下的经验,其它类型的任务可适当借鉴下。
常用框架
编程语言:python(⭐⭐⭐⭐⭐)
炼丹框架:Pytorch(⭐⭐⭐⭐⭐)、Keras(⭐⭐⭐⭐)、Mxnet(⭐⭐⭐)、Tensorflow(⭐)
必备框架:Apex(⭐⭐⭐⭐⭐)、Numpy、Opencv、PIL、Scikit-learn、albumentations、imgaug等
1. 个人看来,Pytorch的易用性其实是已经超越了另外几个框架,搭建/魔改模型都非常方便;
2. Apex可以让你只写几行代码,就可以轻松使用float16或者混合精度来训练模型,显存减少将近一半的情况下,训练速度也得到大幅度提升。3. 自写数据增强库,推荐使用Opencv;如果是封装好的数据增强库,推荐albumentations或imgaug(或torchvison.transforms),基本想得到的transform方式都包含。
apex使用example
实验pipeline(baseline)
如何提升搭建baseline的能力
对于参赛者而言,往往具有一个好的baseline,或有着一套属于自己风格的pipeline,其实是已经成功了一半。好的baseline等价于一个好的起点,后面的改进遇到的阻碍相对也会少非常多。但是,要把baseline写好,其实是需要不少场比赛下来的经验或者是已经有过相关项目的工作经验。
1.对于初学者,每场比赛,都会有许多kagglers将自己的baseline开源到kernel上,你所要做的是,不是直接copy,而是去学习,从多个kernel中取出其比较精妙的部分,再组合成自己的baseline;
2.在以前相关类型的比赛里,模仿top solution codes,整理出一个baseline。
3.多次实践下来,你基本掌握了自己动手写baseline的能力。
调参技巧
调参是比赛环节里最重要的一步(日常工作也都是一样离不开调参的),好的learning rate和learning rate schedule对比不合适的,得到的结果也是千差万别,optimizer的选取或许多比较fancy的finetune技巧也是类似的结果。
1.Adam: init_lr=5e-4(3e-4)(⭐⭐⭐⭐⭐),3e-4号称是Adam最好的初始学习率,有理有据,请看下图;SGD就更考验调参功力,这里就不详说(因为我也一般般)。
2. lr schedule
3. finetune,微调也是有许多比较fancy的技巧,在这里不做优劣比较,针对分类任务说明。
4. Find the best init_lr,前面说到3e-4在Adam是较优的init_lr,那么如何寻找最好的init_lr?
5. learing rate warmup,理论解释可以参考 zhihu.com/question/3380
6. 如果模型太大的同时你的GPU显存又不够大,那么设置的batch size就会太小,如何在有限的资源里提升多一点?
分类赛技巧
1.label smoothing
分类任务的标签是one-hot形式,交叉熵会不断地去拟合这个真实概率,在数据不够充足的情况下拟合one-hot容易形成过拟合,因为one-hot会鼓励正确类别与所属类别之间的差异性尽可能大,但其实有不少类别之间是极为相似的。label smoothing的做法其实就是将hard label变成soft label。
2. topk-loss(OHEM)
OHEM最初是在目标检测上提出来的,但其实思想是所有领域任务都通用的。意思就是提取当前batch里top k大的loss的均值作为当前batch的loss,进行梯度的计算和回传。其insight也很简单,就是一中hard mining的方法,一个batch里会有easy sample和hard sample,easy sample对网络的更新作用较小(loss值小,梯度也会小),而hard sample的作用会更大(loss值大,梯度值也会大),所以topk-loss就是提取hard sample。
3. weighted loss
weighted loss其实也算是一种hard mining的方法,只不过这种是人为地认为哪种类别样本更加hard,哪种类别样本更加easy。也就是说人为对不同类别的loss进行进行一个权重的设置,比如0,1类更难,设置权重为1.2,2类更容易,设置权重为0.8。
4. dual pooling
这种是在模型层进行改造的一种小trick了,常见的做法:global max/average pooling + fc layer,这里试concat(global max-pooling, global average pooling) + fc layer,其实就是为了丰富特征层,max pooling更加关注重要的局部特征,而average pooling试更加关注全局的特征。不一定有效,我试过不少次,有效的次数比较少,但不少人喜欢这样用。
5. margin-based softmax
6. Lovasz loss
分类赛技巧(openset/检索)
2. margin-based softmax(上面已经说到)
3. triplet loss + softmax loss
结合metric learning,对feature进行多个loss的优化,triplet loss也是可以有很多的花样,Batch Hard Triplet Loss,是针对triplet loss的一种hard mining方法。
4. IBN
切换带有IBN block的backbone,搜图(open-set)往往test和train是不同场景下的数据,IBN block当初提出是为了提高针对不同场景下的模型泛化性能,提升跨域(cross domain)能力,在reid下的实验,IBN表现优异。
5. center loss
6. Gem,generalized mean pooling
出自Fine-tuning CNN Image Retrieval with No Human Annotation,提出的是一种可学习的pooling layer,可提高检索性能。
7. global feature + local features
将全局特征和多个局部特征一起融合,其实就是一种暴力融合特征的方法,对提升精度有一定的帮助,就是耗时相对只使用global feature来说很多点,此种方法可参考在reid常用的PCB(Beyond Part Models: Person Retrieval with Refined Part Pooling)或MGN(Learning Discriminative Features with Multiple Granularities for Person Re-Identification)方法
8. re-ranking
一种在首次获取检索图的候选图里做一次重新排序,获得更加精准的检索,相对比较耗时间,不适合现实场景,适合比赛刷精度。
分割赛技巧
1. Unet Unet可以说是在kaggle的语义分割赛里的一个较优的选择,许多top solution都是使用了Unet,FPN也是一个非常不错的选择。
2. Unet的魔改
现在有个开源库其实是已经集成了许多不同分割网络,表现也是相对不错的,如果觉得自己修改比较困难,或者自己改得不够好,可以尝试使用这个库segmentation_models_pytorch
出自蛙神-Heng CherKeng
3. lovasz loss
之前在TGS Salt Identification的适合,lovasz对分割的效果的表现真的是出类拔萃,相比bce或者dice等loss可以提高一个档次。但是最近的分割赛这个loss的表现就一般,猜测是优化不同metric,然后不同loss就会带来不同的效果,又或者是数据的问题。
4. dice loss for postive,bce loss for negtive
主要就是将分割任务划分两个任务:
通用技巧
大部分都是牺牲推断速度来提高精度的方法,适合比赛,不适合现实场景。
1、TTA(Test Time Augmentation)
一种暴力测试的方法,将有效的增强方式得到多个不同的input,然后进行infer,得到多个结果进行融合,一般会比原始input会高不少。这种方法的缘由就是希望通过对input进行不同的变换方式获取多个不同的但重要的特征,然后可以得到多个具有差异性的预测结果。
2、多尺度训练、融合
在训练期间,随机输入多种尺度的图像进行训练,如(128128,196196,224224,256256,384*384等等)然后测试的时候可适当的选取其中某几个尺度表现优异的预测结果出来融合,这种方法其实就是为了提升模型对尺度的变换的鲁棒性,不易受尺度变换的影响。
3、Ensemble
4. 设计metric loss
许多小伙伴会有这样一个疑惑,比赛的评测metric往往和自己训练时所使用的loss优化方向不是那么一致。比如多标签分类里的metric是fbeta_score,但训练时是用了bce loss,经常可以看到val loss再收敛后会有一个反弹增大的过程,但此时val fbeta_score是还在继续提升的。这时就可以针对metric来自行设计loss,比如fbeta loss就有。
5. semi-supervised learning
from seutao
数据增强与预处理
数据增强往往都是调出来的,可以先在本地里对图像施加不同的变换方式,用肉眼观察其是否有效(肉眼观察和模型学习到的不一定对等),之后再扔进去网络里训练验证其是否有效。
1、h/v flip(水平垂直翻转),95%的情况下都是有效的,因为不怎么破坏图像空间信息。
2、random crop/center crop and resize,在原图进行crop之后再resize到指定的尺度。模型的感受野有限,有时会看不到图像中一些分布比较边缘或者是面积比较小的目标物体,crop过后其占比有更大,模型看到的机会也会更多。适用性也是比较大的。
3、random cutout/erasing(随机擦除),其实就是为了随机擦除图像中局部特征,模型根据有限的特征也可以判断出其属性,可提高模型的泛化性。
4、AutoAugment,自己设定一些规则policy,让模型自己寻找合适的数据增强方式,需要消耗比较多的计算资源。
5、mixup 一种与数据无关的数据增强方式,即特征之间的线性插值应导致相关标签之间的线性插值,扩大训练分布。意思是两个不同的label的样本进行不同比例的线性插值融合,那么其label也应该是相同比例关系进行线性融合。(上图)
6、Class balance 主要就是针对数据不平衡的情况下进行的操作,一般是针对采样方法,或者在loss上做处理,如focal loss、weighted loss等。
7、图像预处理,许多看似有效的预处理操作,但是并不一定有效,如在医学领域的图像,许多肉眼观察良好的预处理的方式,实际上是破坏了原图真实类别关联的特征,这种方面需要相关领域知识。
如何选择更好的backbone模型
建议与劝退
1、不要过拟合public lb,要在oof上看cv。一般来说,oof cv是比较准的,除非是遇到了private、public、train数据分布都不一致的必赛,这时就需要靠人品。
2、如果是小白入坑,一定要自己独立去完成一个比赛,尽量地去上分,从kernel,讨论区去挖掘有用的信息,如果你没一个比较好的基础名次,自己也不会有资本去和前排的大神一起组队。
3、劝退建议,希望大家都是在了以提高自身能力/兴趣浓厚的前提下来kaggle参加比赛,不要太功利性:如出发点为了找工作想来拿牌、申请好学校offer、带队拿牌并收取佣金和各种py交易来一起拿奖牌等等,当然前面两种无可厚非,在kaggle拿金确实是有一定的加分。我这里只是强调出发点。
4、没有坚持的魄力,如遇到一些代码上的难题(debug不通)或者无法上分,就直接放弃比赛或者是让自己变成伸手党等等,比赛期间是一个非常好的学习的过程,而且kaggle的讨论区也是非常热闹的,只要脸皮够厚,在讨论区发一下自己相关困惑的问题(只要不是非常SB的问题),一般都有人很热心的回答你。
5、充足的比赛时间,学生和上班族基本是一样的,白天上班上课,晚上才能有一些业余的时间来放在比赛里。我还在校时,经常在课堂里拿着ipad观察讨论区,看相关论文,也是为了能在白天积攒一些点子,晚上可以实施。
我经常会在比赛的后半段期,会在凌晨调好闹钟起床,观察刚刚运行完程序的log,然后思考再做对应的修改继续跑下一次,为了就是不想浪费时间(当然可能比不过工作时加班到半夜的小伙伴)。当然不提倡,休息还是很重要的。
6、如果不是很满足这些点,建议不要参加比赛哈,不要浪费这些时间,老老实实搬砖或者在校搞论文会更加好。
总结
Kaggle profile:kaggle.com/garybios
rank: 60/125547
原文链接:
https://zhuanlan.zhihu.com/p/93806755
视频点击预测大赛火热进行中
3万元奖金、证书、实习、就业机会已准备就位,快叫上小伙伴一起来组队参赛吧。
赛题:希望参赛者通过已有的用户信息、视频信息以及他们是否观看过某些视频,来预测我们推荐给这些用户的视频对方是否会观看。
个人、高等院校、科研单位、互联网企业、创业团队、学生社团等人员均可报名。
报名及组队时间:即日起至2020年2月1日
报名入口:
http://www.turingtopia.com/competitionnew/detail/e4880352b6ef4f9f8f28e8f98498dbc4/sketch