模型训练相关

【EMA : Exponential Moving Average】

cnblogs:https://www.cnblogs.com/wuliytTaotao/p/9479958.html
代码:https://www.shangmayuan.com/a/92d49ecf09aa4a079817bc4c.html

1. 用滑动平均估计局部均值
滑动平均(exponential moving average),或者叫做指数加权平均(exponentially weighted moving average),可以用来估计变量的局部均值,使得变量的更新与一段时间内的历史取值有关。
变量v在t时刻记为 vt,θt 为变量 v在 t 时刻的取值,即在不使用滑动平均模型时 vt=θt,在使用滑动平均模型后,vt的更新公式如下:
在这里插入图片描述
上式中,β∈[0,1)。β=0 相当于没有使用滑动平均。
假设起始 v0=0,β=0.9,之后每个时刻,依次对变量 v 进行赋值,不使用滑动平均和使用滑动平均结果如下:在这里插入图片描述

Andrew Ng在Course 2 Improving Deep Neural Networks中讲到,t 时刻变量 v 的滑动平均值大致等于过去 1/(1−β)个时刻 θ 值的平均。
这个结论在滑动平均起始时相差比较大,所以有了Bias correction,将 vt除以 (1−βt)修正对均值的估计。
加入了Bias correction后,vt 和 v_biasedt的更新公式如下:在这里插入图片描述
t 越大,1−βt越接近 1,则公式(1)和(2)得到的结果 (vt 和 v_biasedt)将越来越近,如图 1 所示。
当 β越大时,滑动平均得到的值越和 θ 的历史值相关。如果 β=0.9,则大致等于过去 10 个 θ 值的平均;如果 β=0.99,则大致等于过去 100 个 θ 值的平均。

滑动平均的好处:
占内存少,不需要保存过去10个或者100个历史 θ 值,就能够估计其均值。(当然,滑动平均不如将历史值全保存下来计算均值准确,但后者占用更多内存和计算成本更高)

2. TensorFlow中使用滑动平均来更新变量(参数)
滑动平均可以看作是变量的过去一段时间取值的均值,相比对变量直接赋值而言,滑动平均得到的值在图像上更加平缓光滑,抖动性更小,不会因为某次的异常取值而使得滑动平均值波动很大,如图 1所示。
TensorFlow 提供了 tf.train.ExponentialMovingAverage 来实现滑动平均。在初始化 ExponentialMovingAverage 时,需要提供一个衰减率(decay),即公式(1)(2)中的 ββ。这个衰减率将用于控制模型的更新速度。
ExponentialMovingAverage 对每一个变量(variable)会维护一个影子变量(shadow_variable),这个影子变量的初始值就是相应变量的初始值,而每次运行变量更新时,影子变量的值会更新为:
在这里插入图片描述
公式(3)中的 shadow_variable 就是公式(1)中的 vt,公式(3)中的 variable 就是公式(1)中的 θt,公式(3)中的 decay 就是公式(1)中的 β。
公式(3)中,decay 决定了影子变量的更新速度,decay 越大影子变量越趋于稳定。在实际运用中,decay一般会设成非常接近 1 的数(比如0.999或0.9999)。
为了使得影子变量在训练前期可以更新更快,ExponentialMovingAverage 还提供了 num_updates 参数动态设置 decay 的大小。
如果在初始化 ExponentialMovingAverage 时提供了 num_updates 参数,那么每次使用的衰减率将是:
在这里插入图片描述
这一点其实和 Bias correction 很像。TensorFlow 中使用 ExponentialMovingAverage 的例子:code (如果 GitHub 无法加载 .ipynb 文件,则将 .ipynb 文件的 URL 复制到网站 https://nbviewer.jupyter.org/)

3. 滑动平均为什么在测试过程中被使用?
滑动平均可以使模型在测试数据上更健壮(robust)。“采用随机梯度下降算法训练神经网络时,使用滑动平均在很多应用中都可以在一定程度上提高最终模型在测试数据上的表现。”
对神经网络边的权重 weights 使用滑动平均,得到对应的影子变量 shadow_weights。在训练过程仍然使用原来不带滑动平均的权重 weights,不然无法得到 weights 下一步更新的值,又怎么求下一步 weights 的影子变量 shadow_weights。
之后在测试过程中使用 shadow_weights 来代替 weights 作为神经网络边的权重,这样在测试数据上效果更好。
因为 shadow_weights 的更新更加平滑,对于随机梯度下降而言,更平滑的更新说明不会偏离最优点很远;
对于梯度下降 batch gradient decent,我感觉影子变量作用不大,因为梯度下降的方向已经是最优的了,loss 一定减小;对于 mini-batch gradient decent,可以尝试滑动平均,毕竟 mini-batch gradient decent 对参数的更新也存在抖动。
设 decay=0.999decay=0.999,一个更直观的理解,在最后的 1000 次训练过程中,模型早已经训练完成,正处于抖动阶段,而滑动平均相当于将最后的 1000 次抖动进行了平均,这样得到的权重会更加 robust。

【Cross entropy】

知乎:https://zhuanlan.zhihu.com/p/149186719

【二分类CE】
对某个样本:
在这里插入图片描述
考虑batchsize:
在这里插入图片描述
B1是一个batch的正样本数(y=1),B2是一个batch的负样本数(y=0)

【多分类CE】
假设一个动物照片的数据集中有5种动物,且每张照片中只有一只动物,每张照片的标签都是one-hot编码。
在这里插入图片描述
第一张照片是狗的概率为100%,是其他的动物的概率是0;第二张照片是狐狸的概率是100%,是其他动物的概率是0,其余照片同理;
因此可以计算下,每张照片的熵都为0。换句话说,以one-hot编码作为标签的每张照片都有100%的确定度,不像别的描述概率的方式:狗的概率为90%,猫的概率为10%。
假设有两个机器学习模型对第一张照片分别作出了预测:Q1和Q2,而第一张照片的真实标签为[1,0,0,0,0]。
在这里插入图片描述
两个模型预测效果如何呢,可以分别计算下交叉熵:
在这里插入图片描述

交叉熵对比了模型的预测结果和数据的真实标签,随着预测越来越准确,交叉熵的值越来越小,如果预测完全正确,交叉熵的值就为0。因此,训练分类模型时,可以使用交叉熵作为损失函数。

考虑batchsize:
在这里插入图片描述
c是类别数,Bj是一个batch中类别j的样本数,Pji是类别j的第i个样本的输出概率

【Focal loss】

知乎:https://zhuanlan.zhihu.com/p/49981234
代码(torch):https://zhuanlan.zhihu.com/p/28527749

【目标】
我们知道object detection的算法主要可以分为两大类:two-stage detector和one-stage detector。
前者是指类似Faster RCNN,RFCN这样需要region proposal的检测算法,这类算法可以达到很高的准确率,但是速度较慢。虽然可以通过减少proposal的数量或降低输入图像的分辨率等方式达到提速,但是速度并没有质的提升。
后者是指类似YOLO,SSD这样不需要region proposal,直接回归的检测算法,这类算法速度很快,但是准确率不如前者。
作者提出focal loss的出发点也是希望one-stage detector可以达到two-stage detector的准确率,同时不影响原有的速度。

【现在的问题】
既然有了出发点,那么就要找one-stage detector的准确率不如two-stage detector的原因,作者认为原因是:样本的类别不均衡导致的。
我们知道在object detection领域,一张图像可能生成成千上万的candidate locations,但是其中只有很少一部分是包含object的,这就带来了类别不均衡。
那么类别不均衡会带来什么后果呢?引用原文讲的两个后果:
(1) training is inefficient as most locations are easy negatives that contribute no useful learning signal;
(2) en masse, the easy negatives can overwhelm training and lead to degenerate models.
什么意思呢?负样本数量太大,占总的loss的大部分,而且多是容易分类的,因此使得模型的优化方向并不是我们所希望的那样。
因此针对类别不均衡问题,作者提出一种新的损失函数:focal loss,这个损失函数是在标准交叉熵损失基础上修改得到的。
这个函数可以通过减少易分类样本的权重,使得模型在训练时更专注于难分类的样本。
为了证明focal loss的有效性,作者设计了一个dense detector:RetinaNet,并且在训练时采用focal loss训练。
实验证明RetinaNet不仅可以达到one-stage detector的速度,也能有two-stage detector的准确率。

【Corss entropy】
介绍focal loss,在介绍focal loss之前,先来看看交叉熵损失,这里以二分类为例,原来的分类loss是各个训练样本交叉熵的直接求和,也就是各个样本的权重是一样的。公式如下:
在这里插入图片描述

因为是二分类,p表示预测样本属于1的概率(范围为0-1),y表示label,y的取值为{+1,-1}。
当真实label是1,也就是y=1时,假如某个样本x预测为1这个类的概率p=0.6,那么损失就是-log(0.6),注意这个损失是大于等于0的。
如果p=0.9,那么损失就是-log(0.9),所以p=0.6的损失要大于p=0.9的损失,这很容易理解。这里仅仅以二分类为例,多分类分类以此类推
为了方便,用pt代替p,如下公式2:
在这里插入图片描述
为了表示简便,我们用p_t表示样本属于true class的概率。所以(1)式可以写成:
在这里插入图片描述

【Focal loss】
接下来介绍一个最基本的对交叉熵的改进,也将作为本文实验的baseline。
既然one-stage detector在训练的时候正负样本的数量差距很大,那么一种常见的做法就是给正负样本加上权重,负样本出现的频次多,那么就降低负样本的权重,正样本数量少,就相对提高正样本的权重。
在这里插入图片描述
因此可以通过设定a的值来控制正负样本对总的loss的共享权重。a取比较小的值来降低负样本(多的那类样本)的权重。
显然前面的公式3虽然可以控制正负样本的权重,但是没法控制容易分类和难分类样本的权重,于是就有了focal loss:
在这里插入图片描述
称为调制系数(modulating factor):
在这里插入图片描述
为什么要加上这个调制系数呢?目的是通过减少易分类样本的权重,从而使得模型在训练时更专注于难分类的样本。

【性质】
这里介绍下focal loss的两个重要性质:
1、当一个样本被分错的时候,pt是很小的,那么调制因子(1-Pt)接近1,损失不被影响;
当Pt→1,因子(1-Pt)接近0,那么分的比较好的(well-classified)样本的权值就被调低了。
因此调制系数就趋于1,也就是说相比原来的loss是没有什么大的改变的。
当pt趋于1的时候(此时分类正确而且是易分类样本),调制系数趋于0,也就是对于总的loss的贡献很小。

2、当γ=0的时候,focal loss就是传统的交叉熵损失,当γ增加的时候,调制系数也会增加。
专注参数γ平滑地调节了易分样本调低权值的比例。γ增大能增强调制因子的影响,实验发现γ取2最好。
直觉上来说,调制因子减少了易分样本的损失贡献,拓宽了样例接收到低损失的范围。
当γ一定的时候,比如等于2,一样easy example(pt=0.9)的loss要比标准的交叉熵loss小100+倍,当pt=0.968时,要小1000+倍,但是对于hard example(pt < 0.5),loss最多小了4倍。
这样的话hard example的权重相对就提升了很多。这样就增加了那些误分类的重要性

【Focal loss最终形式】
focal loss的两个性质算是核心,其实就是用一个合适的函数去度量难分类和易分类样本对总的损失的贡献。
作者在实验中采用的是公式5的focal loss(结合了公式3和公式4,这样既能调整正负样本的权重,又能控制难易分类样本的权重):
在实验中a的选择范围也很广,一般而言当γ增加的时候,a需要减小一点(实验中γ=2,a=0.25的效果最好)
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值