为什么用深度学习
深度学习可以自己学会如何提取有用的特征,相反,机器学习则十分依赖特征工程。
上手门槛低。
常见术语
-
ResNet层数
resnet18 = 16 + 2
resnet34 = 16 * 2 + 2
resnet50 = 改为bottleneck,总共增加了16层
resnet101 = 增加第4区的块数
resnet152 = 增加第3、4区的块数
-
Backbone
CV领域中,一般要先提取图像的特征,再利用这些特征去干一些事情(分类,识别,分割等)。因此,提取特征的部分被称作网络的主干(骨干,backbone)。常见的backbone有ResNet、VGG等。
-
head
利用之前的特征,得到网络最后的输出(做出预测),一般位于网络的最后。
-
neck
一般位于Backbone和head之间,为了更好地利用Backbone提取的特征。
-
Embedding
嵌入:将原始数据转变为向量/特征的过程(提取特征的过程)。reference
解决过拟合
- 权值衰减(weight decay): Adam优化器自带的参数
- 学习率衰减:自己手动设置规则,或pytorch提供现成的方法
- Dropout
- Batch Normalization: 与Relu一起使用, 防止Dead Relu, 也能加速训练?
- 增加训练集的样本数
实验结果
之前实验发生过拟合的原因是:定义模型结构的时候,复用了编码和解码路径上的(等通道)卷积模块,导致这些模块变成了权值共享(或者说是强行使编码和解码路径上部分模块的权值相同)。修改模型代码后过拟合问题消失。
修改前模型参数量:6238532,修改后:8563652,证实了前面的分析
调整学习率
-
自己手动设置规则:最后几轮进行衰减
设定一个衰减轮数n,最后n轮每轮使lr减掉初始lr的n分之1,持续n轮,最后减为0
$$ lr=lr-\frac{lr_{begin}}{n} $$
实验结果:在lr开始衰减时,可以看到训练集有明显提升(mean Dice提升2%左右),但验证集几乎没有影响
-
Pytorch提供的现成的方法:随着迭代次数增加,学习率自动衰减
-
指数衰减 ExponentialLR $$ lr = lr_{base} * \gamma ^ {epoch} \tag {1} $$
-
等步长衰减 StepLR
每隔一定epoch,就衰减为原来的γ(gamma)倍(0<γ<1)
比如step_size=30,则在epoch为30、60、90时进行调整
$$ lr = lr_{base} * \gamma ^ {\lfloor \frac{epoch}{stepsize} \rfloor} $$
-
多步长衰减 MultiStepLR
达到milestones=[200, 300, 320, 340, 400]指定的步数时,学习率衰减为γ倍
小结:其实前面三种方法本质上都是按epoch进行衰减,只是发生衰减的步数不同
- 指数衰减就是每个epoch都衰减一次
- 等步长就是间隔固定的步长后衰减一次
- 多步长就是自定义在第几个epoch进行衰减
-
余弦退火衰减 CosineAnnealingLR
学习率周期变化,而不是衰减
-
自适应调整学习率 ReduceLROnPlateau
当某指标不再变化(下降或升高),调整学习率,这是非常实用的学习率调整策略
-
自定义调整学习率 LambdaLR
为不同参数组设定不同学习率调整策略,fine-tune 中十分有用,我们不仅可为不同的层设定不同的学习率,还可以为其设定不同的学习率调整策略
-
-
在每个epoch结束时调用返回的scheduler对象的step()方法
scheduler.step()
-
查看当前学习率
scheduler.get_lr()
可以通过查看每个类对get_lr()的实现方法,来找到每个类的学习率调整公式
-
示例
import torch.optim as optim optimizer = optim.Adam(model.parameters(), lr=0.0002, weight_decay=0.0005) scheduler = optim.lr_scheduler.ExponentialLR(optimizer, gamma=0.01) for epoch in range(100): scheduler.step() # train(...) # validate(...)
Dropout
一般适合于全连接层,卷积层由于参数不多,所以不是很需要Dropout,加上也对模型泛化能力没有太大影响。
干的事情:
- Pytorch的Dropout设置的p是失活率(drop rate)
- 不是按失活比例进行失活,而是对每个神经元按失活率进行失活(对每个输出点按失活率进行失活)。因此,实际失活的数量不一定等于失活率的比例
实验:
- Pytorch的Dropout分为:
- Dropout
- Dropout2d
- Dropout3d
- 不加dropout时,训练集效果最好,p越高,训练集效果越差
- 在p(失活率)为0.1~0.8的实验中,p=0.1的训练、验证结果最好
- p为0.6时,训练集性能下降明显(验证集也一样),p为0.7和0.8时,就几乎学不动了,训练和验证的Dice很早就收敛到0.5左右
总结:
- drop rate越高训练集上的效果越差,感觉像是强行降低在训练集上的拟合能力来提高泛化能力。。。
- 确实能够抑制一点过拟合,但是dice依然抖动严重,可能还需要加上学习率衰减。
权值初始化
- kaiming初始化
数据归一化/标准化
- 数据点(x, y)的归一化:为了降低数据(x和y)之间的相关性,去除冗余信息,如:正相关变为不相关
- 图像像素值归一化:为了将像素值约束到一个合理范围内,便于后续神经网络的学习
- BN:将数据归一化到均值0,方差1。通常卷积后数据的方差较小,即数据的分布比较集中,差异较小,不便于后序网络的学习
下采样
仅用卷积来下采样的话(不做BN归一化),深层特征图上的值的绝对值会快速趋于0。
解决方法:卷积后进行归一化BN
性能
- 深层参数量大,但显存消耗较小
- 浅层参数量小,但显存消耗较大