未验证 提交 4acbb1b8 编写于 作者: C cuicheng01 提交者: GitHub

Add 10 train model tricks in faq. (#498)

* Update faq_2020_s1.md

* Update faq_2020_s1.md

* Update faq_series.md
上级 6ddd8049
......@@ -7,4 +7,4 @@
## 目录
* [【精选】图像分类30个问题及PaddleClas常见使用问题](./faq.md)
* [2020 FAQ第一季](./faq_series/faq_2020_s1.md)(最近更新2020.12.09)
* [2020 FAQ第一季](./faq_series/faq_2020_s1.md)(最近更新2020.12.17)
......@@ -6,6 +6,7 @@
* [第2期](#第2期)(2020.11.11)
* [第3期](#第3期)(2020.11.18)
* [第4期](#第4期)(2020.12.07)
* [第5期](#第5期)(2020.12.17)
<a name="第1期"></a>
## 第1期
......@@ -192,3 +193,142 @@ use_dynamic_loss_scaling: True
* *Fex*操作表示两次全连接,作者将该操作称为*Excitation*。其中第一次全连接将向量的维度从*1 × 1 × C*压缩到*1 × 1 × C/r*,然后使用*RELU*,再通过第二次全连接将向量的维度恢复到*C*,这样操作的目的是为了减小计算量,*SENet*作者通过实验得出结论:在*r=16*时可以获得增益与计算量之间的平衡。
* 对于*Fsq*部分,关键是求得*C*维的向量,因此不局限于使用*Global Average Pooling*操作,*SENet*作者认为,最终求得的*scale*是按通道分别作用于*U*的,因此需要基于对应通道的信息计算对应的*scale*,故使用了最简单的*Global Average Pooling*操作,最终求得的*scale*向量表示了不同通道之间的分布关系,而忽略了同一个通道中的分布关系。
* 对于*Fex*部分,其作用是为了在每一个*mini batch*上的训练来求得基于所有训练数据的分布。因为我们的训练是在*mini batch*上进行的,而基于全部训练数据求得的*scale*才是最佳的,使用*Fex*部分,可以通过在每个*mini batch*上的训练来求得更为逼近全部训练数据的*scale*
<a name="第5期"></a>
## 第5期
### Q5.1 如何选择优化器?
**A**:自深度学习发展以来,就有很多关于优化器的研究者工作,优化器的目的是为了让损失函数尽可能的小,从而找到合适的权重来完成某项任务。目前业界主要用到的优化器有SGD、RMSProp、Adam、AdaDelt等,其中由于带momentum的SGD优化器广泛应用于学术界和工业界(此处仅限于分类任务),所以我们发布的模型也大都使用该优化器来实现损失函数的梯度下降。带momentum的SGD优化器有两个劣势,其一是收敛速度慢,其二是初始学习率的设置需要依靠大量的经验,然而如果初始学习率设置得当并且迭代轮数充足,该优化器也会在众多的优化器中脱颖而出,使得其在验证集上获得更高的准确率。一些自适应学习率的优化器如Adam、RMSProp等,收敛速度往往比较快,但是最终的收敛精度会稍差一些。如果追求更快的收敛速度,我们推荐使用这些自适应学习率的优化器,如果追求更高的收敛精度,我们推荐使用带momentum的SGD优化器。具体到数据集来说:
- ImageNet-1k: 建议只使用带momentum的SGD优化器。
- 其他数据集(默认加载ImageNet-1k预训练): 加载预训练模型的时候可以考虑使用Adam等优化器(效果可能会更好),但使用带momentum的SGD优化器是绝对是比较不错的方案。
另外,为了进一步加速训练,Lookahead优化器也是一个不错的选择,在ImageNet-1k上,其可以保证在更快的收敛速度下拥有相同的收敛精度,但在部分数据集上表现不太稳定,需要进一步调参。
### Q5.2 如何设置初始学习率以及学习率下降策略?
**A**:学习率的选择往往和优化器以及数据和任务有关系。学习率决定了网络种权重更新的速度。学习率越低,损失函数的变化速度就越慢。虽然使用低学习率可以确保不会错过任何局部极小值,但也意味着将花费更长的时间来进行收敛,特别是在被困在高原区域的情况下。
在整个训练过程中,我们不能使用同样的学习率来更新权重,否则无法到达最优点,所以需要在训练过程中调整学习率的大小。在训练初始阶段,由于权重处于随机初始化的状态,损失函数下降较快,所以可以设置一个较大的学习率。在训练后期,由于权重已经接近最优值,较大的学习率无法进一步寻找最优值,所以需要设置一个较小的学习率。至于学习率下降策略,很多研究者或者从业人员使用的学习率下降方式是piecewise_decay(step_decay),即阶梯式下降学习率,此外,很多研究者也提出了学习率的其他下降方式,如polynomial_decay(多项式下降)、exponential_decay(指数下降),cosine_decay(余弦下降)等,其中cosine_decay无需调整超参数,鲁棒性也比较高,所以成为现在提高模型精度首选的学习率下降方式。
Cosine_decay和piecewise_decay的学习率变化曲线如下图所示,容易观察到,在整个训练过程中,cosine_decay都保持着较大的学习率,所以其收敛较为缓慢,但是最终的收敛效果较peicewise_decay更好一些。
![](../../images/models/lr_decay.jpeg)
另外,从图中我们也可以看到,cosine_decay中只有少数轮数使用了较小的学习率,这样会影响到最终的精度,所以为了使得cosine_decay发挥更好的效果,建议迭代更多的轮数。
最后,如果使用较大的batch_size训练神经网络时,建议您使用warmup策略。Warmup策略顾名思义就是让学习率先预热一下,在训练初期不直接使用最大的学习率,而是用一个逐渐增大的学习率去训练网络,当学习率增大到最高点时,再去衰减学习率的值。实验表明,在batch_size较大时,warmup可以稳定提升模型的精度。具体到数据集来说:
- ImageNet-1k:建议batch-size大小为256、初始学习率为0.1,cosine-decay下降学习率。
- 其他数据集(默认加载ImageNet-1k预训练): 数据集规模越大,初始学习率也越大,但最好不要超过0.1(batch-size为256时候),数据集规模越小,初始学习率也越小,当数据集较小时,使用warmup也会带来一定的精度提升,学习率下降策略仍旧推荐cosine-decay。
### Q5.3 如何设置batch-size的大小?
**A**:Batch_size是训练神经网络中的一个重要的超参数,该值决定了一次将多少数据送入神经网络中训练。之前有研究者通过实验发现,当batch_size的值与学习率的值呈线性关系时,收敛精度几乎不受影响。在训练ImageNet-1k数据时,大部分的神经网络选择的初始学习率为0.1,batch_size是256。具体到数据集来说:
- ImageNet-1k: 学习率设置为0.1\*k,batch_size设置为256\*k。
- 其他数据集(默认加载ImageNet-1k预训练): 可以根据实际情况设置(如更小的学习率),但在调整学习率或者batch-size时,要同时调整另外一个值。
### Q5.4 weight_decay是什么?怎么设置?
**A**:过拟合是机器学习中常见的一个名词,简单理解即为模型在训练数据上表现很好,但在测试数据上表现较差,在图像分类问题中,同样存在过拟合的问题,为了避免过拟合,很多正则方式被提出,其中,weight_decay是其中一个广泛使用的避免过拟合的方式。当使用SGD优化器时, weight_decay等价于在最终的损失函数后添加L2正则化,L2正则化使得网络的权重倾向于选择更小的值,最终整个网络中的参数值更趋向于0,模型的泛化性能相应提高。在各大深度学习框架的实现中,该值表达的含义是L2正则前的系数,在飞桨框架中,该值的名称是L2Decay,所以以下都称其为L2Decay。该系数越大,表示加入的正则越强,模型越趋于欠拟合状态。具体到数据集来说:
- ImageNet-1k:大多数的网络将该参数值设置为1e-4,在一些小的网络如MobileNet系列网络中,为了避免网络欠拟合,该值设置为1e-5~4e-5之间。下表展示了MobileNetV1_x0_25在ImageNet-1k上使用不同L2Decay的精度情况。由于MobileNetV1_x0_25是一个比较小的网络,所以L2Decay过大会使网络趋向于欠拟合状态,所以在该网络中,相对1e-4,3e-5是更好的选择。
| 模型 | L2Decay | Train acc1/acc5 | Test acc1/acc5 |
|:--:|:--:|:--:|:--:|
| MobileNetV1_x0_25 | 1e-4 | 43.79%/67.61% | 50.41%/74.70% |
| MobileNetV1_x0_25 | 3e-5 | 47.38%/70.83% | 51.45%/75.45% |
另外,该值的设置也和训练过程中是否使用其他正则化有关系。如果训练过程中的数据预处理比较复杂,相当于训练任务变的更难,可以将该值适当减小,下表展示了在ImageNet-1k上,ResNet50在使用RandAugment预处理方式后使用不同L2Decay的精度。容易观察到,在任务变难后,使用更小的l2_decay有助于模型精度的提升。
| 模型 | L2Decay | Train acc1/acc5 | Test acc1/acc5 |
|:--:|:--:|:--:|:--:|
| ResNet50 | 1e-4 | 75.13%/90.42% | 77.65%/93.79% |
| ResNet50 | 7e-5 | 75.56%/90.55% | 78.04%/93.74% |
- 其他数据集(默认加载ImageNet-1k预训练):在做迁移任务的时候,最好不要改变训练ImageNet-1k时的L2Decay的值(即训练得到预训练时的L2Decay值,每个backbone对应的L2Decay值都在相应的训练yaml配置文件中),一般的数据集只改变学习率足够。
### Q5.5 是否使用label_smoothing,如何设置其中的参数值?
**A**:Label_smoothing是深度学习中的一种正则化方法,其全称是 Label Smoothing Regularization(LSR),即标签平滑正则化。在传统的分类任务计算损失函数时,是将真实的one hot标签与神经网络的输出做相应的交叉熵计算,而label_smoothing是将真实的one hot标签做一个标签平滑的处理,使得网络学习的标签不再是一个hard label,而是一个有概率值的soft label,其中在类别对应的位置的概率最大,其他位置概率是一个非常小的数。在label_smoothing中,epsilon参数描述了将标签软化的程度,该值越大,经过label smoothing后的标签向量的标签概率值越小,标签越平滑,反之,标签越趋向于hard label。具体到数据集来说:
- ImageNet-1k:在训练ImageNet-1k的实验里通常将该值设置为0.1,ResNet50大小级别及其以上的模型在使用label_smooting后,精度有稳定的提升。下表展示了ResNet50_vd在使用label_smoothing前后的精度指标。
| 模型 | Use_label_smoothing(0.1) | Test acc1 |
|:--:|:--:|:--:|
| ResNet50_vd | 0 | 77.9% |
| ResNet50_vd | 1 | 78.4% |
同时,由于label_smoohing相当于一种正则方式,在相对较小的模型上,精度提升不明显甚至会有所下降,下表展示了ResNet18在ImageNet-1k上使用label_smoothing前后的精度指标。可以明显看到,在使用label_smoothing后,精度有所下降。
| 模型 | Use_label_smoohing(0.1) | Train acc1/acc5 | Test acc1/acc5 |
|:--:|:--:|:--:|:--:|
| ResNet18 | 0 | 69.81%/87.70% | 70.98%/89.92% |
| ResNet18 | 1 | 68.00%/86.56% | 70.81%/89.89% |
如何在较小的模型中也可以让label-smoothing有效,这里有一个技巧,即在Global-Average-Pool后接一个1000-2000大小的全连接层,该技巧可以与label-smoothing同时作用,发挥更好的效果。
- 其他数据集(默认加载ImageNet-1k预训练):使用label-smooth之后往往都会提升精度,规模越小的数据集epsilon值可以越大,在一些规模较小的细粒度图像中,最佳模型通常是在该值设置到0.4-0.5时获得的。
### Q5.6 默认的图像预处理中random-crop还可以调整吗?怎么调整?
**A**:在ImageNet-1k数据的标准预处理中,random_crop函数中定义了scale和ratio两个值,两个值分别确定了图片crop的大小和图片的拉伸程度,其中scale的默认取值范围是0.08-1(lower_scale-upper_scale),ratio的默认取值范围是3/4-4/3(lower_ratio-upper_ratio)。在非常小的网络训练中,此类数据增强会使得网络欠拟合,导致精度有所下降。为了提升网络的精度,可以使其数据增强变的更弱,即增大图片的crop区域或者减弱图片的拉伸变换程度。可以分别通过增大lower_scale的值或缩小lower_ratio与upper_scale的差距来实现更弱的图片变换。具体到数据集来说:
- ImageNet-1k:不是特别小的网络建议只用默认值,特别小的网络可以调大lower_scale的值(增大crop区域面积)或者缩小ratio值的范围(减弱图像伸缩变换),特别大的网络可以调小lower_scale的值(减小crop面积)或者增大ratio值的范围(增强图像伸缩变换)。下表列出了使用不同lower_scale训练MobileNetV2_x0_25的精度,可以看到,增大图片的crop区域面积后训练精度和验证精度均有提升。
| 模型 | Scale取值范围 | Train_acc1/acc5 | Test_acc1/acc5 |
|:--:|:--:|:--:|:--:|
| MobileNetV2_x0_25 | [0.08,1] | 50.36%/72.98% | 52.35%/75.65% |
| MobileNetV2_x0_25 | [0.2,1] | 54.39%/77.08% | 53.18%/76.14% |
- 其他数据集(默认加载ImageNet-1k预训练):建议使用默认值,如果过拟合较严重,可以考虑调小lower_scale的值(减小crop面积)或者增大ratio值的范围(增强图像伸缩变换)。
### Q5.7 目前常用数据增广有哪些?如何选择?
**A**:一般来说,数据集的规模对性能影响至关重要,但是图片的标注往往比较昂贵,所以有标注的图片数量往往比较稀少,在这种情况下,数据的增广尤为重要。在训练ImageNet-1k的标准数据增广中,主要使用了Random_Crop与Random_Flip两种数据增广方式,然而,近些年,越来越多的数据增广方式被提出,如cutout、mixup、cutmix、AutoAugment等。实验表明,这些数据的增广方式可以有效提升模型的精度。具体到数据集来说:
- ImageNet-1k:下表列出了ResNet50在8种不同的数据增广方式的表现,可以看出,相比baseline,所有的数据增广方式均有收益,其中cutmix是目前最有效的数据增广。更多数据增广的介绍请参考[**数据增广章节**](https://paddleclas.readthedocs.io/zh_CN/latest/advanced_tutorials/image_augmentation/ImageAugment.html)
| 模型 | 数据增广方式 | Test top-1 |
|:--:|:--:|:--:|
| ResNet50 | 标准变换 | 77.31% |
| ResNet50 | Auto-Augment | 77.95% |
| ResNet50 | Mixup | 78.28% |
| ResNet50 | Cutmix | 78.39% |
| ResNet50 | Cutout | 78.01% |
| ResNet50 | Gridmask | 77.85% |
| ResNet50 | Random-Augment | 77.70% |
| ResNet50 | Random-Erasing | 77.91% |
| ResNet50 | Hide-and-Seek | 77.43% |
- 其他数据集(默认加载ImageNet-1k预训练):在其他数据集中除了使用Auto-Augment,一般都会有精度的提升,Auto-Augment会针对每一个数据集搜索的独立超参数,该超参数决定了数据如何处理,所以默认的ImageNet-1k的超参数并不适合所有的数据集,当然您可以使用Random-Augment来替代Auto-Augment。其他策略可以正常使用,对于比较难的任务或者比较小的网络,建议不要使用较强的数据增广。
此外,多种数据增广也可以叠加使用,当数据集较为简单或数据规模较小时,叠加数据增广可以进一步提升精度。
### Q5.8 如何通过train_acc和test_acc确定调优策略?
**A**:在训练网络的过程中,通常会打印每一个epoch的训练集准确率和验证集准确率,二者刻画了该模型在两个数据集上的表现。通常来说,训练集的准确率反映了经过Random-Crop后的数据的精度,由于数据经过Random-Crop后,数据往往较难,所以训练集的准确率和验证集的准确率往往不是一个概念。
- ImageNet-1k:通常来说,训练集准确率比验证集准确率微高或者二者相当是比较不错的状态。如果发现训练集的准确率比验证集高很多,说明在这个任务上已经过拟合,需要在训练过程中加入更多的正则,如增大L2Decay的值,加入更多的数据增广策略,加入label_smoothing策略等;如果发现训练集的准确率比验证集低一些,说明在这个任务上可能欠拟合,需要在训练过程中减弱正则效果,如减小L2Decay的值,减少数据增广方式,增大图片crop区域面积,减弱图片拉伸变换,去除label_smoothing等。
- 其他数据集(默认加载ImageNet-1k预训练):基本和训练ImageNet-1k的调整策略相当,此外,在其他数据集上如果模型趋向于过拟合(train acc远大于test acc)状态,也可以使用更优的预训练权重,PaddleClas为常用的网络提供了SSLD的蒸馏预训练权重,其比ImageNet-1k的权重更优,您可以优先选择。
- **【备注】** 不太建议根据loss来重新调整训练策略,在使用不同的数据增广后,train loss的大小差异较大,如使用Cutmix或者RandAugment后,train loss会大于test loss,当数据增广策略减弱后,train loss会小于test loss,所以较难调整。
### Q5.9 如何通过预训练模型提升自己的数据集的精度?
**A**:在现阶段图像识别领域中,加载预训练模型来训练自己的任务已成为普遍的做法,相比从随机初始化开始训练,加载预训练模型往往可以提升特定任务的精度。一般来说,业界广泛使用的预训练模型是通过训练128万张图片1000类的ImageNet-1k数据集得到的,该预训练模型的fc层权重是是一个k\*1000的矩阵,其中k是fc层以前的神经元数,在加载预训练权重时,无需加载fc层的权重。在学习率方面,如果您的任务训练的数据集特别小(如小于1千张),我们建议你使用较小的初始学习率,如0.001(batch_size:256,下同),以免较大的学习率破坏预训练权重。如果您的训练数据集规模相对较大(大于10万),我们建议你尝试更大的初始学习率,如0.01或者更大。如果目标数据集较小,也可以冻结一些浅层的权重。此外,如果训练一个特定垂类的小数据集,也可以先在相关的大的数据集上训练一个预训练权重,再在该权重上用较小的学习率微调模型。
### Q5.10 现有的策略已经让模型的精度趋于饱和,如何进一步提升特定模型的精度?
**A**:如果现有的策略不能进一步提升模型的精度,说明在现有数据集和现有的策略下,模型几乎到达饱和状态,这里提供两种进一步提升模型精度的方法。
- 挖掘相关数据:用在现有数据集上训练饱和的模型去对相关的数据做预测,将置信度较高的数据打label后加入训练集进一步训练,如此循环操作,可进一步提升模型的精度。
- 知识蒸馏:可以先使用一个较大的模型在该数据集上训练一个精度较高的teacher model,然后使用该teacher model去教导一个Student model,其中,Student model即为目标模型。PaddleClas提供了百度自研的SSLD知识蒸馏方案,即使在ImageNet-1k这么有挑战的分类任务上,其也能稳定提升3%以上。SSLD知识蒸馏的的章节请参考[**SSLD知识蒸馏**](https://paddleclas.readthedocs.io/zh_CN/latest/advanced_tutorials/distillation/distillation.html)
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册