0%

为什么回归任务不能用Dropout

最近在做一个nlp的回归任务,所以直接套用之前做分类问题的的代码,仅仅修改了下损失函数而已,结果发现验证损失一直在震荡,不收敛,但是别人的代码loss却能够稳定下降,最终下降到0.1左右,而我的只能却一直飘,最终只下降到0.14,如下图:


image.png
最后通过对比别人的代码,我发现其实就两行代码的差异:
image.png
这边把bert内部的dropout全部关掉了,于是我也尝试了这种做法,最终得到这样的一个loss,对比一下,这个loss下降就很平稳了,而且最小值明显低很多
image.png

很神奇是不是,按照之前学的,dropout相当于ensemble,按理应该是能够防止过拟合,增加模型稳健性的,怎么到了我这里,用了dropout反而性能损失这么大?
于是我在讨论区发了个帖子问了一下,有个大佬给了我回复:
image.png
通过阅读他给出的两个链接(见文末链接),我终于明白了问题的根源,总结一下,我做的这个是回归任务,回归任务是不能用dropout的,接下来结合我自己的理解阐述一下为什么。
首先回顾一下dropout的用法:
dropout在训练时会把以\(p\)的概率将隐藏层的神经元置为零,同时会将其他神经元乘以\(\frac{1}{1-p}\),保证输出值期望的一致性,即
\(h^{\prime}= \begin{cases}0 & \text { 概率为 } p \\ \frac{h}{1-p} & \text { 其他情况 }\end{cases}\)
接下来我们来推导一下dropout输出值的均值和方差(这里是为了推出经过dropout层后方差发生了变化)
这里为了方便计算,我们把dropout代表的随机变量单独拿出来,假设\(d\)为一个服从二项分布的随机变量(\(p\)的概率取0,\(1-p\)的概率取1),则根据二项分布的公式,\(d\)的均值为\(1-p\), 方差为\(p(1-p)\), 假设原来的隐藏层为随机变量\(h\),则经过dropout后可以用如下公式表示:
\(h' = \frac{1}{1-p} dh\)
接下来来计算下这个东西的均值和方差:
首先是均值:
\(E(h') = \frac{1}{1-p}\times (1-p)\times \mu_h = \mu_h\)
可以发现均值是没有发生变化的
然后是方差,这里直接套用计算两个随机变量相乘后方差的公式:
\(D(h') =\frac{1}{(1-p)^2}\times E(d^2)E(h^2) - \frac{1}{(1-p)^2} (E(d)E(h))^2 = \frac{1}{1-p}(\mu_h^2+\sigma_h^2)-\mu_h^2\)
可以发现,经过dropout之后,输出的均值没有发生变化,但是方差发生了变化。
由于经过dropout的输出还要经过非线性层(比如Linear层+ReLU),非线性层可以理解为把它输入的一个分布转换成另外一个分布(ReLU就是把小于0部分全砍掉了),那它输出的均值就可以表示为一个关于dropout层输出均值和方差的一个函数,虽然在测试时,dropout层输出的均值没有发生改变,但是方差发生了变化,这个变化就会导致非线性层输出的均值发生偏移,最终导致整个网络的输出值发生偏移。
也就是说,如果使用了dropout,在训练时隐藏层神经元的输出的方差会与验证时输出的方差不一致,这个方差的变化在经过非线性层的映射之后会导致输出值发生偏移,最终导致了在验证集上的效果很差。
由于回归问题输出是一个绝对值,对这种变化就很敏感,但是分类问题输出只是一个相对的logit,对这种变化就没那么敏感,因此,在回归问题上最好不要用dropout,而在分类问题上才用dropout,后面查了下发现也有一篇论文的实验佐证了这一观点:(PDF) Effect of Dropout Layer on Classical Regression Problems
不过,根据上面的分析,其实dropout最好是不要加在网络的中间,在最后输出层前面加应该还是没问题的,根据我自己的实验来看,dropout加在最后一层是没有观察到明显的性能损失的,但是也没有提高就是了,因此,回归任务干脆就别用dropout了。

参考

  1. Pitfalls with Dropout and BatchNorm in regression problems | by Søren Rasmussen | Towards Data Science
  2. The Magic of No Dropout | Kaggle

欢迎关注我的其它发布渠道