2-6月以来密集的项目实践的总结

  • 2-4月做了三件事,为MICCAI会议投稿论文准备一些实验,打了个超分辨率比赛NTIRE,得了大概是第7名/200多个参赛队伍,做了一个新冠病毒相关肺部图像诊断的项目;4-6月以来做了三件事情,写了一份(实际上算两份)综述,跑了好几份代码做了个测试报告,还有就是现在仍在进行时的智能车创意赛线上赛,趁现在代码都在运行中,先做个总结。
  • 2-4月的三件事,关于代码的已经做了总结并且上传了代码,4-6月的,由于已经有两篇文字的结果,代码相关等比赛结束会上传,所以现在总结的是更为宏观的一些经验,就按顺序一件件来吧。
  • 首先是MICCAI的一些实验,当时是先完成了后半部分的实验并且验证了我们的猜想,想当然认为我们一定能够成功,所以提交了论文的题目和构思并且开始赶ddl做实验,写论文。但是反而是前半部分不成功,最后发现我们的猜想的验证有个缺陷,最后无疾而终,论文也没有写出来因为实验不成功,效果并没有比前人的好。在这件事中得到的经验有以下几点:
    • 并不是过拟合就说明只要解决了过拟合就一定能够成功的,我们在训练集上loss下降得很漂亮,并且预测出来的分割图和GT的几乎一样,但是在测试集上表现极差。后来我们做了很足量的数据增强,但是这时loss不下降了,也就是模型只有两个极端,过拟合或者不拟合。
    • 在实验中发现了一个现象:按官方给的划分去训练,loss下降得很平稳,但是如果你自己划分,loss振荡得很厉害,打个比方,loss的区间是1-0,那么在不同的batch之间loss相差大约在0.7左右。但是虽然自己划分loss振荡得很厉害,在自己划分的测试集上表现却和训练集差不多,而按官方划分的去训练,在测试集上差别却很大。猜测是官方数据集划分有问题,两个数据集的组成不够相近,也就是说明数据集中存在相差较大的样本,这个问题后来也没有解决,因为我们的模型不够好
    • 还发现一个现象,分割训练的时候最初十几个epoch loss完全没有下降的迹象,从某个epoch开始loss突然开始下降,loss随时间变化呈现断崖式的曲线。
    • 训练时代码尽量加上tensorboard可视化训练过程,包括中间的预测结果和整体的loss曲线,是有助于你判断问题的。
    • 如果模型由两部分分开的处理过程组成,那么很可能你两部分的效果是乘积得到最终结果而不是加和。也就是说,如果满分是1分,现有最佳效果是0.8,也就意味着你两部分都达到0.8是不够的,至少要两部分都达到0.9才可以超过现有模型,所以在构思一个两部分的处理过程的时候,一定要先考虑这一点,估计一下你的两部分是否能够达到这样的效果,或者至少要达到怎样的效果,从而能够事先评估你的想法的可行性,不至于浪费时间。
    • 虽然做实验是必须的,有时候可能突然就行了而你无法从理论上去解释,所谓“玄学”和“炼丹”,不要轻易放弃,但是实验很花时间,不要蛮干,虽然深度学习有点实验科学的味道,但是如果你在理论分析上做得比别人多和足,多花点时间在实验前做理论分析,绝对好过蛮干,这并不是还没做先怕,而是理智,要给自己从理论上否决自己的机会和思考时间。
    • 安排集中的时间抛开所有事情打代码效率会很高很高,有时候一天就能完成几天的工作量,所以如果你有集中的大段时间,不要低估你的完成量,但是如果你的时间比较零碎,也不要高估你的完成量。
    • 计划是必须的,你必须计划什么时候做什么事情,今天做什么事情,才不会一眼看上去只看到一共要做多少事情然后被吓到,觉得自己完不成。并且当你同时需要进行多件事情的时候,你会感到压力和烦躁,不知道现在该做哪一件,计划可以解决这些问题,静下心来计划好,明天早上做什么,明天下午做什么,比如你同时进行两个项目A,B,那么你可以这样,明天早上进行A的第一部分,明天下午进行B的第一部分。一旦你完成短期的合理计划,那么就可以忘记你一共有多少事情要做,只记住现在应该做什么,做眼前的事情,只要按计划做一定能够完成,可以很大程度减轻压力和焦虑感,因为这些压力和焦虑感实际上是被放大的,你在眼前看到了整个事情,所以一时手足无措,害怕事情完不成,如果你在眼前看到眼前该做什么,并且知道我现在做好眼前的事情,就不会有什么事情完不成,你有安全感,所以可以很大程度减轻压力和焦虑感。当你又有焦虑感和压迫感的时候,就再做一次计划,然后抛开一切只看今天甚至这几个小时内应该做什么,然后做就行了什么都别想。
  • 接下来是NTIRE比赛的经验
    • 我犯的第一个错误是自以为对SR足够了解,真正到比赛的时候才发现,SR的问题有很多种,有分好几个问题,如大倍率放大,我们参加的就是x16的,小的也有x4的,如没有对应的SR标签并且采取的是主观评分的,等等。我们只准备了有监督学习,没有想到有无监督学习的项目,这是第一点失误,以后在比赛前一定一定要做全面的了解,不一定要深入到多少,但是要全面,这样才可以知道在哪一点深入而不会漏。
    • 第二个错误是一直停留在理论上,如果是参加比赛一定要尽快完成一个完整的流程,效果不完美没关系,要的是先完成再完善,而不能想着一点点推进,因为你不知道在哪一步就会卡到,不好把握在哪一步要花多少精力,最后可能导致完不成。
    • 第三个错误是找了个训练比较慢的模型,调参浪费了很多时间,因为训练比较慢,所以参加比赛尽量找训练快的模型
    • 第四个失误是,没有及时沟通,导致大家都不怎么花时间在这上面,在长期的项目中如果大家不够自觉,最好是一周开一次组会,并且每个人给出自己下周计划,这样每周每个人都会按计划去做,但是也不要逼得太死,像一天一次报告就很浪费时间,会引起抵触
  • 第三件事是新冠的经验:
    • 如果你并不是很着急要完成这个项目,或者并不想全部时间花在这上面,但是随时会有问题出现需要你做点事情的时候,要学会延迟。并不是问题一出现,或者任务以来,然后你没有急事,就必须去回应这个问题或者任务,你可以说,我今晚处理,然后在晚上专门拿出一个小时来处理堆积的问题和任务,处理完,再有问题,第二天晚上再设一个时间段来处理,这样就不会被这种随时出现的任务占据你一天多数时间并且引起反感,总觉得一个问题解决又出现一个,明明不是很想花时间在这个上面但是一整天都在解决问题,虽然不是连续的,但是断断续续,一两个小时给你一个任务你也很烦,就算你只需要几分钟就可以解决,但是毕竟是打扰。
    • 做这个课题之前,先考虑这个课题创新性是否达到你的预期,如果没有,即使它可行,也不要去做,只是浪费时间。
    • 当你需要做很多很多个实验的时候,即使代码是同一份,最好还是分开文件夹做,也就是每个实验有它自己的一份代码副本,并且文件夹命名清楚,并且随时做好笔记,哪个文件夹里面做的是什么实验。
    • 数据增强不要覆盖到原来的数据集文件夹中。
    • 数据集划分不要用划分图片到不同文件夹的方式,也不要用在线随即划分的方式,用两个json文件记录训练集测试集的各个图片路径的方式,方便重新划分数据集和同一个划分复用,后者通常为了比较不同参数和模型。
  • 第四件事是综述的经验:
    • 做综述前,多找一下此前有没有人写过综述,是很有帮助的。
    • 在IEEE上搜索相关论文,一次性看几篇的introduction,基本就可以对该领域的方法形成基本概念
    • 从一篇论文的intro找到其它论文,然后接着找下去一直到再找都是找过的,也就是存在反复被引用的论文,这样的论文比较重要。
    • 通常一开始并不需要看完篇,看摘要和introduction,然后看看图表,基本就有大概印象,然后做好笔记,这是最快的粗读,再进一步可以搜一下类似CSDN上有没有人读过这篇论文做了翻译或者总结和介绍之类的,这是一定程度的粗度。等你通过大范围的粗读找到大量相关论文并且形成大量笔记时,可以开始对该领域存在的问题和解决方法进行分类,形成结构性的综述,然后可以对每个问题和解决方法的论文进行精读。深入理解,最终形成你的综述。一定要做好归类笔记,可以的话读一段时间就整理一下笔记,再接着读,是一个动态整理的过程而不是一次性读完一次性写。
    • 了解一下该领域的权威会议有助于判断某些论文的重要程度。
    • 只有你真正花一个月做过一次综述,读过百来篇论文,才能说你入门了某个领域,在形成全面而结构性的综述之前,我的观点是很片面的,想到的很多所谓“new idea”在做完综述发现其实已经有人做过了。
  • 第五件事是测试报告的经验:
    • 高估实验的难度没有好处,如果觉得实验很多很难在时限内做不完,只需要按自己的能力计划好明天后天以至一周内做什么,别的别想,做一步看一步。再说,只要你每次计划都按自己的能力来计划,就能够尽力完成这件事情,做到什么样就是什么样了。通常做到一半才会知道事情的真实难度。
    • 别人的repos即使star很多也未必就是完善的没有bug的,但是bug是可以解决的,相信自己可以找到问题所在然后解决,我就发现了两份代码的bug并且自己解决了。即使是cupy相关的cpp文件,也是看得懂并且能够修改的,只要你做了就会发现这并不难。
    • 每天抽出20分钟下楼跑步可以缓解不适感和长期的任务带来的焦虑和压力,听歌也有用。不要拒绝运动和睡眠,长期任务中每次短任务的效率很重要,通常来说你以为你会每天都要花好多时间做好多事情,然后你发现你只是每天都要花一点时间来做一点事情,所以这点时间的工作质量如何取决于你的状态,是否精神饱满心情愉悦。
  • 第六件事是智能车创意赛的经验:
    • 不要一开始就搭一个复杂完善的模型,最好是从简单的一点点加上去,加上去比原来效果提升了,就加上去,否则容易出现复杂模型效果很差试了很多方法最后没办法去掉一些trick发现效果反而提升了。
    • 当发现loss不下降时,可以打印出来某些参数的梯度看看,要是梯度是None,就是你代码有问题,可以避免不必要的调参时间,先确定代码没问题再想别的方法。要是梯度是None,可以在某个中间变量调用backward,然后在上游查梯度,一点点缩小范围,一般梯度断掉可能是某个变量名写错了导致动态图某部分断掉了或者某个变量被其它变量覆盖了导致传不到前面去。
    • 其实最好就是不要等到出了问题再去检查,从一开始就应该主动检查。除了检查梯度,还要检查dataloader 加载出来送进模型的数据是否有问题,可能有时候dataloader写错了,不要怕麻烦,一定要检查好再进行其它优化。
    • 检查中发现梯度不是None但是很快变成0的情况,一般是初始化有问题,用Xavier初始化不容易出这个问题,用正态随机初始化容易出这个问题,特别是方差小的时候,很容易导致梯度弥散,这样梯度传到前面来就都是0了,所以如果loss不下降也可以检查一下是不是弥散掉了,采取相应的解决方法。
    • 很多框架是有github源码的,是可以看的。如果你想实现自己的卷积层,比如pytorch和飞桨动态图中都没有提供的自适应same padding的conv,你可以找到卷积层的源码,copy过来,定义自己的conv,然后修改它的forward。学会看甚至修改框架的源码可以解决很多问题,其实不难的 ,基本看得懂,而且有时候未必要完全看懂,只要照着做,或者copy过来加上自己的需求就不会影响它原本的梯度传导等功能。文档很多时候不会给全,但是源码是完整的,对你没有隐藏,善用源码可以实现很多API实现不了的事情。
    • 时刻观察自己的状态,避免自己陷入过度的焦虑和易怒的状态,如果进入这个状态了,就休息一下,否则会影响其他人。

你可能感兴趣的:(项目经验,深度学习)