步步为营!高手教你如何有效使用深度学习解决实际问题
来自法国 Capgemini Invent 公司的高级数据科学家 Ahmed BESBES 三个月前参加了一个其公司内部的比赛:使用机器学习方法帮助海洋科学家更好的识别鲸鱼,根据鲸尾页突的外观作为主要特征。
比赛要求对于每一幅测试图像模型要给出最相似的前20幅图像,这不是一个简单的分类任务而是相似检索任务。
最终,Ahmed获得了第三名,他把在此过程中搭建模型的全过程详细分享了出来,并附上了其在各个步骤使用的开源工具,相信对那些想要使用深度学习解决实际问题的朋友肯定有帮助。
第一种方法:分类
简单的做法是使用分类分数作为相似性排序的依据,但很不幸的是,这样做难以得到好的相似性排序结果。
这提醒我们,如果要体现个体之间的相似性,必须在训练阶段对样本进行显式学习和排序。
Triplet loss ArcFace loss
Ⅰ、Triplet loss来自谷歌2015年论文 FaceNet。
使用Triplet loss 时作者又加入了如下训练tricks:
硬采样,即triplet (a, p, n) 满足不等式 d(a, n) < d(a, p)
PK采样,保证每一个batch来自P个不同的类,每一类K幅图像 在线生成triplets
了解执行细节可以查看作者代码:
学习更多这些技术推荐阅读论文:
ArcFace loss 相比 triplet loss有更好的特性:
对于类别很多的问题也表现的很好; 消除了训练triplet loss中的难样本挖掘的问题; 提供了漂亮的几何解释; 能够稳定训练; 收敛更快; 更重要的,实验发现仅需要一个ArcFace loss训练的单模型打败了5个triplet loss训练的模型的融合。
去除噪声和已经损坏的图像,比如分辨率很低的,或者鲸鱼的尾巴根本看不见的图像。
去除那些只含有一幅图像的类别,这被证明非常有效。因为度量学习需要类别内部的上下文信息,所以只含有一幅图像的类别是信息不足的。
检测并提取鲸尾页突的图像,以去除大海、水花等的干扰,这一步扮演了注意力机制的角色。作者标注了大约300幅鲸尾页突的图像,训练了一个YOLOv3检测器,使用的标注工具来自:https://www.makesense.ai/ ,YOLOv3的训练代码来自:https://github.com/ultralytics/yolov3
学习要点:我们应该在合适且干净的数据上赢得更多的精度提升,而不是努力做花里胡哨的模型。
学习要点:
迁移学习往往是有效的,且很少会带来伤害,如果可以请把ImageNet预训练模型在与你的问题相似的数据集上进行微调是很有必要的; 迁移学习是增加训练样本的间接方式。
在该问题中因为拍摄的设备很专业,很多图像很大,可以达到3000x1200像素或者更大。
作者首先使用224 x 224分辨率的图像,后来改成大一些分辨率的图像,得到了明显的精度提升,最后发现 480x480是对这个问题最好的输入大小。
学习要点:
如果你在处理高分辨率图像,尝试较大的分辨率是不错的选择,大分辨率能够让模型学到特别小的细节特征,有助于样本个体间的区分;
并不是越大越好,过大会使得训练收敛更慢,且如果原来数据中图像较小,resize到过大分辨率会带来精度下降,因为原有信号被破坏了。
业界有很多流行的深度学习架构如 VGG 或 ResNet,还有很多新出的复杂架构 ResNet-Inception-V4 、 NASNet等。到底如何选择呢?
大而深的SOTA骨干网并不总是最优选择,如果你的数据量不大,这些模型会快速过拟合,而且如果你计算资源有限,你也不能训练它们。 一种比较好的做法是,最开始选择简单的网络,在验证集上监控性能变化,逐步增加模型复杂度。 如果你计划把你的方案部署到网页端,则必须要考虑模型大小、内存消耗、推断时间等。
https://github.com/ahmedbesbes/whales-classification
固定种子保证模型可重复性
在PyTorch中可以使用如下代码:
import random
import numpy as np
import torch
random.seed(seed)
torch.manual_seed(0)
np.random.seed(0)
torch.backends.cudnn.deterministic = True
torch.backends.cudnn.benchmark = False
Adam是安全的优化器,但不要忘记把weight decay 设置为非0值。作者使用了1e-3。
大量的数据增广确实改进了模型精度,强烈推荐使用:albumentations
(https://github.com/albumentations-team/albumentations)选择合适的学习率调度方案,避免模型陷入局部极小值。作者使用了warmup 调度机制后面加cosine退火的方法。 Loss 和其他度量结果的监控,作者使用了 Tensorbaord。 使用伪标签往往可以带来精度提升。这在kaggle竞赛中经常被使用,它使用训练好的模型预测测试数据的类别,将置信度很高(比如大于0.9概率)预测结果的样本加入训练样本,重新训练模型。 最好有强大的硬件支持,训练速度快,可以快速验证改进策略。 保存训练好的模型,跟踪并记录模型的表现。
作者训练了两个模型,如下:
元嵌入特征连接的方式在模型差异比较大的时候能够提供有意义的结果,比如:骨干网不同(resnet34 vs densenet121), 图像输入大小不同 (480 vs 620), 正则化模式不同 (dropout vs no dropout)的模型;
每一个不同的基模型看到不同的事物,把它们联合能够产生新的增强混合模型(这个解释太朴素了——CV君)。
A Hacker’s Guide to Efficiently Train Deep Learning Models
https://towardsdatascience.com/a-hackers-guide-to-efficiently-train-deep-learning-models-b2cccbd1bc0a
https://github.com/ahmedbesbes/whales-classification
更多阅读:
文中作者使用了ArcFace Loss,今年一种新的更好的Loss出现了:
在看,让更多人看到