FRN实验记录

在batchsize128的情况下,变化ramp-up,看最佳的ramp-upepoch是多少。

ramp-up 20 50 80
FRN 91.74% 92.30% 92.28%

感觉最优的rampup应在50~80个epoch之间,暂用50.

0:后续实验计划

  • cifar100上FRN效果太差,复现的结果有问题。需要更正。

  • 测试3 的方法究竟有什么好处?更快的收敛究竟意味着什么?
    接下来的实验要从三方面入手:
    1:该方法是否稳定?
    2:该方法究竟有什么好处?
    3:该方法能够进一步优化?
    针对第一点,比较好的方法就是多个数据集检验。鉴于目前算力,只在svhn和cifar100上跑一下就可以,应该足够说明问题。
    针对第二点,因为FRN复现有问题(cifar100上结果不对,同时也找不到更好的调参方式),同时,如果该方法对BN,LN,WN等方式都有好处,将会有更大的意义。所以先不再以FRN为基础,而是转向BN,LN,WN。从BN开始。 目前FRN面临的问题就是训练困难。需要采用warmup和cosine形式的lr下降方式才能work。这种新的训练方式能否降低对这些技巧的依赖,使得该方法更加普适?
    针对第三点,这种训练方式也许说明了方差不那么重要。能否用其他的东西来代替方差?另外,这种方法对BN有没有效果?

1:σ\sigma修正

1.1 Max_Min_FRN

在ramp-up 50的情况下,变化batchsize,看各种算法的accuracy。

Image per GPU 128 32
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
No_sigma_FRN_V1 91.51% 91.50%
No_sigma_FRN_V2 91.71% 91.71%

三种layer的公式如下:

  • BN:x^=γxμbnσbn+β,σbn=(xiμ)2HWBBN: \hat{x}=\gamma\frac{x-\mu_{bn}}{\sigma_{bn}}+\beta,\sigma_{bn}=\sqrt{\frac{\sum (x_i-\mu)^2}{H*W*B}}

  • FRN:x^=max(γxσfrn+β,τ),σfrn=xi2HWFRN:\hat{x}=max(\gamma\frac{x}{\sigma_{frn}}+\beta,\tau),\sigma_{frn}=\sqrt{\frac{\sum x_i^2}{H*W}}

  • Max_Min_FRN:x^=max(γxσrange+β,τ),σrange=xmaxxmin2ln(HW),xmax,xminHWMax\_Min\_FRN:\hat{x}=max(\gamma\frac{x}{\sigma_{range}}+\beta,\tau),\sigma_{range}=\frac{x_{max}-x_{min}}{\sqrt{2*ln(H*W)}},x_{max},x_{min}是在HW两个维度统计的

  • No_σ_FRN_V1:x^=max(γx+β,τ)No\_\sigma\_FRN\_V1:\hat{x}=max(\gamma x +\beta,\tau)

  • No_σ_FRN_V2:x^=max(x,τ)No\_\sigma\_FRN\_V2:\hat{x}=max( x,\tau)
    从上面表格可以看出,

  • FRN在两种batchsize中表现一致。这不仅依赖于FRNlayer的设计(σfrn\sigma_{frn}与batch无关,且无需计算mean),也与FRN的lr设置相关。lr的初始值是0.1batch_size/2560.1*batch\_size/256,是一个与batchsize相关的量,如果没有这个设计,小batchsize也会使得FRN性能变差。

  • FRN在Images per GPU 128的情况下,是差于BN的。但是paper里面最大的Images per GPU是32,而在Images per GPU 32的情况下,FRN性能优于BN。所以这个结果是与paper里面结果一致的。

  • Max_Min_FRN效果较FRN差距比较大。但是在小batchsize下,与BN基本持平。与FRN差距较大的原因,初步分析,是由于σrange=xmaxxmin2ln(HW)σbn=(xiμ)2HWB<<σfrn=xi2HW\sigma_{range}=\frac{x_{max}-x_{min}}{\sqrt{2*ln(H*W)}}\approx\sigma_{bn}=\sqrt{\frac{\sum (x_i-\mu)^2}{H*W*B}}<<\sigma_{frn}=\sqrt{\frac{\sum x_i^2}{H*W}}

  • 非常有意思的点是,当我们把方差σ\sigma置为1时,效果仍然不错。而且与γ,β\gamma,\beta关系不大。同时,我们发现这种训练在前期收敛速度特别快,远远超过正常的FRN。这是一个很好的性质。只是在后期,他的精度无法达到FRN的级别。

1.2:对σfrn\sigma_{frn}的一种估计

有高斯分布性质,大体可以认为,σfrnμ2+σ2\sigma_{frn}\approx\sqrt{\mu^2+\sigma^2},这里的μ,σ\mu,\sigma指在H,W两个维度上算出的均值方差。
若方差用σrange\sigma_{range}代替,均值用(xmax+xmin)/2(x_{max} + x_{min})/2代替,可以降低运算量。

  • Max_Min_FRN_V2:x^=max(γxσrange_v2+β,τ),σrange_v2=(xmaxxmin)22ln(HW)+(xmax+xmin)24Max\_Min\_FRN\_V2:\hat{x}=max(\gamma\frac{x}{\sigma_{range\_v2}}+\beta,\tau),\sigma_{range\_v2}=\sqrt{\frac{(x_{max}-x_{min})^2}{2*ln(H*W)}+\frac{(x_{max}+x_{min})^2}{4}}
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
Max_Min_FRN _V2 91.80% 91.81%

1.3:用可学习变量代替方差

  • Learnable_V1:y=max(γmin(x,α)+β,τ)Learnable\_V1:y=max(\gamma *min(x,\alpha)+\beta,\tau)
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.40%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
Max_Min_FRN _V2 91.80% 91.81%
Learnable_V1 90.55%

  • Learnable_V2:y=max(γmin(x,α)+β,τ)/(αβ)Learnable\_V2:y=max(\gamma *min(x,\alpha)+\beta,\tau)/(\alpha - \beta)
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
Max_Min_FRN _V2 91.80% 91.81%
Learnable_V1 90.55%
Learnable_V2 不收敛,效果很差
  • Learnable_V3:y=2max(γmin(x,α)+β,τ)/(α+β)Learnable\_V3:y=2*max(\gamma *min(x,\alpha)+\beta,\tau)/(\alpha + \beta)
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
Max_Min_FRN _V2 91.80% 91.81%
Learnable_V1 90.55%
Learnable_V2 不收敛,效果很差
Learnable_V3 不收敛,效果很差
  • Learnable_V4:y=max(γmin(x,α)+β,τ)/detach(αβ)Learnable\_V4:y=max(\gamma *min(x,\alpha)+\beta,\tau)/detach(\alpha - \beta)
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
Max_Min_FRN _V2 91.80% 91.81%
Learnable_V1 90.55%
Learnable_V2 不收敛,效果很差
Learnable_V3 不收敛,效果很差
Learnable_V4 不收敛,效果很差
  • Learnable_V5:y=max(γleaky_min(x,uplim,slope)+β,τ)leaky_min(x,lim,s)={x,if x< limsx+(1s)lim,if x > limLearnable\_V5:y=max(\gamma *leaky\_min(x,uplim,slope)+\beta,\tau)\\ leaky\_min(x,lim,s)= \begin{cases}x,&\text {if x< lim} \\ s*x + (1 - s)*lim,&\text{if x > lim}\end{cases}
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
Max_Min_FRN _V2 91.80% 91.81%
Learnable_V1 90.55%
Learnable_V2 不收敛,效果很差
Learnable_V3 不收敛,效果很差
Learnable_V4 不收敛,效果很差
Learnable_V5 90.24%
  • Learnable_V6:y=max(γleaky_min_v2(x,uplim,slope)+β,τ)leaky_min_v2(x,lim,s)={x,if x< limsx+(1s)lim,if x > lims=rsqrt(ln(HW))Learnable\_V6:y=max(\gamma *leaky\_min\_v2(x,uplim,slope)+\beta,\tau)\\ leaky\_min\_v2(x,lim,s)= \begin{cases}x,&\text {if x< lim} \\ s*x + (1 - s)*lim,&\text{if x > lim}\end{cases}\\ s = rsqrt(ln(H*W))
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
Max_Min_FRN _V2 91.80% 91.81%
Learnable_V1 90.55%
Learnable_V2 不收敛,效果很差
Learnable_V3 不收敛,效果很差
Learnable_V4 不收敛,效果很差
Learnable_V5 90.55%
Learnable_V6 90.50%
  • Learnable_V7:y=max(γleaky_min_v4(x,s)+β,τ)leaky_min_v3(x,s)=x/((1+s)sqrt(ln(HW)))Learnable\_V7:y=max(\gamma *leaky\_min\_v4(x,s)+\beta,\tau)\\ leaky\_min\_v3(x,s)=x / ((1 + s)*sqrt(ln(H*W)))
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
Max_Min_FRN _V2 91.80% 91.81%
Learnable_V1 90.55%
Learnable_V2 不收敛,效果很差
Learnable_V3 不收敛,效果很差
Learnable_V4 不收敛,效果很差
Learnable_V5 90.55%
Learnable_V6 90.50%
Learnable_V7 效果很差
  • Learnable_V8:y=max(γleaky_min_v6(x,uplim,slope,s)+β,τ)leaky_min_v8(x,lim,slope,s)={x,if x< lim(1+abs(slope))sx+(1(1+abs(slope))s)lim,if x > lims=rsqrt(ln(HW))Learnable\_V8:y=max(\gamma *leaky\_min\_v6(x,uplim,slope,s)+\beta,\tau)\\ leaky\_min\_v8(x,lim,slope,s)= \begin{cases}x,&\text {if x< lim} \\ (1+abs(slope))s*x + (1 - (1+abs(slope))s)*lim,&\text{if x > lim}\end{cases}\\ s = rsqrt(ln(H*W))
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max_Min_FRN 91.25% 91.25%
Max_Min_FRN _V2 91.80% 91.81%
Learnable_V1 90.55%
Learnable_V2 不收敛,效果很差
Learnable_V3 不收敛,效果很差
Learnable_V4 不收敛,效果很差
Learnable_V5 90.55%
Learnable_V6 90.50%
Learnable_V7 效果很差

1.4:借用二阶矩导数

FRN:y=max(γxσfrn+β,τ),σ=xi2HWFRN:y=max(\gamma\frac{x}{\sigma_{frn}}+\beta,\tau),\sigma=\sqrt{\frac{\sum x_i^2}{H*W}}
其对应的导数如下:
Lx=(σ2+ϵ)0.5[Ly11...Ly1W......LyH1..LyHW]sum(diagnoal([Ly11...Ly1W......LyH1..LyHW][x11...x1W......xH1..xHW]T(σ2+ϵ)1.5(HW)\frac {\partial L}{\partial x}= (\sigma^2+\epsilon)^{-0.5}* \begin{bmatrix} \frac{\partial L}{\partial y_{11}} & ... & \frac{\partial L}{\partial y_{1W}} \\ .. & .. & .. \\ \frac{\partial L}{\partial y_{H1}} & .. & \frac{\partial L}{\partial y_{HW}} \end{bmatrix} - \frac{sum(diagnoal( \begin{bmatrix} \frac{\partial L}{\partial y_{11}} & ... & \frac{\partial L}{\partial y_{1W}} \\ .. & .. & .. \\ \frac{\partial L}{\partial y_{H1}} & .. & \frac{\partial L}{\partial y_{HW}} \end{bmatrix} \bigotimes \begin{bmatrix} x_{11} & ... & x_{1W} \\ .. & .. & .. \\ x_{H1} & .. & x_{HW} \end{bmatrix}^{T}}{(\sigma^2+\epsilon)^{1.5}(H*W)}
[x11...x1W......xH1..xHW] \bigotimes \begin{bmatrix} x_{11} & ... & x_{1W} \\ .. & .. & .. \\ x_{H1} & .. & x_{HW} \end{bmatrix}

我们将σ\sigma替换成比较容易得到的值,但是保留导数的计算方法,看效果

  • σv12=(maxmin)22ln(HW)σv1.12=(maxmin)2,σv1.22=(maxmin)2/2,σv1.32=σrange_v2=(xmaxxmin)22ln(HW)+(xmax+xmin)24\sigma_{v1}^{2}=\frac{(max - min)^2}{2*ln(H*W)},\sigma_{v1.1}^{2}=(max - min)^2,\sigma_{v1.2}^{2}=(max - min)^2/2,\sigma_{v1.3}^{2}=\sigma_{range\_v2}=\sqrt{\frac{(x_{max}-x_{min})^2}{2*ln(H*W)}+\frac{(x_{max}+x_{min})^2}{4}}
σv1.42=σrange_v2=(xmaxxmin)24+(xmax+xmin)24,σv1.52=σrange_v2=(xmaxxmin)22+(xmax+xmin)22σv1.62=abs(x)max2/2\sigma_{v1.4}^{2}=\sigma_{range\_v2}=\sqrt{\frac{(x_{max}-x_{min})^2}{4}+\frac{(x_{max}+x_{min})^2}{4}},\sigma_{v1.5}^{2}=\sigma_{range\_v2}=\sqrt{\frac{(x_{max}-x_{min})^2}{2}+\frac{(x_{max}+x_{min})^2}{2}},\sigma_{v1.6}^{2}=abs(x)_{max}^{2}/2
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
FRN 92.30% 92.31%
σv1\sigma_{v1} 效果很差,收敛慢
σv1.1\sigma_{v1.1} 效果很差,收敛慢,但是比σv1\sigma_{v1}
σv1.2\sigma_{v1.2} σv1.1\sigma_{v1.1}差不多,但是比σv1\sigma_{v1}
σv1.3\sigma_{v1.3} 90.3%
σv1.4\sigma_{v1.4} 90.7%
σv1.5\sigma_{v1.5} 88%

分析σv1.1\sigma_{v1.1}σv1\sigma_{v1}的差别,猜测是因为v1.1距离二阶矩更近。接下来做两种验证。第一种是σv1.2\sigma_{v1.2}<σv1.1\sigma_{v1.1}但是σv1.2\sigma_{v1.2}>σv1.0\sigma_{v1.0}。第二种是σv1.3\sigma_{v1.3}>σv1.2\sigma_{v1.2}
σv1.3\sigma_{v1.3},需要验证该值是偏大还是偏小还是有时偏大有时偏小。假设偏小,σv1.4\sigma_{v1.4}与之比较。如果σv1.4\sigma_{v1.4}性能优于σv1.3\sigma_{v1.3},则应该继续增大该值;
σv1.4\sigma_{v1.4}实验结果,尝试继续增大该值或减小该值。σv1.5\sigma_{v1.5}σv1.4\sigma_{v1.4}大,但是效果比较差。所以尝试一个比σv1.5\sigma_{v1.5}小同时比σv1.4\sigma_{v1.4}大的值

  • σv22=(max)2\sigma_{v2}^{2}=(max )^2

  • σv32=C=2ln(HW)\sigma_{v3}^{2}=C= \sqrt{2ln(H*W)}

并没有发现一个比较好的参数形式,能够达到FRN的精度。

1.5 引入lr参量。

σ^=1+lrmaxlrlrmaxσ\hat{\sigma} = 1 + \frac{lr_{max - lr}}{lr_{max}}*\sigma
这个公式不知怎么回事,会出现NAN。

  • 测试1:
    由于σ=1\sigma=1的时候训练收敛极快,所以epoch < warm_up 时,就用σ=1\sigma=1,epoch>warm_up时,σ=σfrn=xi2HW\sigma=\sigma_{frn}=\sqrt{\frac{\sum x_i^2}{H*W}}
    这个训练结果略差于FRN。
  • 测试2:
    1:epochtotal_epoch<start=0.1\frac{epoch}{total\_epoch}<start = 0.1时,σ^=1\hat{\sigma}=1
    2:epochtotal_epoch<end=0.9\frac{epoch}{total\_epoch}<end= 0.9时,σ^=max(1,(epochtotal_epoch(endstart)startendstart)σ)\hat{\sigma}=max(1,(\frac{epoch}{total\_epoch*(end-start)}-\frac{start}{end-start})*\sigma)
    3:epochtotal_epoch>end\frac{epoch}{total\_epoch}>end时,σ^=max(1,σ)\hat{\sigma}=max(1,\sigma)
    测试结果有好有坏。好处在于当epoch/total_epoch<end时,收敛是非常快的,效果非常好。最优结果达到了92.13%,远超同期的FRN训练效果。但是当进入第三阶段时,性能没有再进一步提升。
    推测是由于max函数中的1导致的。因为训练后期,方差会收缩到1以下,FRN会适当的放大该层的值,从而在后面的训练中能够进一步优化该值。
    在这里插入图片描述
  • 测试3
    1:epochtotal_epoch<start=0.1\frac{epoch}{total\_epoch}<start = 0.1时,σ^=1\hat{\sigma}=1
    2:epochtotal_epoch<end=0.9\frac{epoch}{total\_epoch}<end= 0.9时,σ^=max(1,(epochtotal_epoch(endstart)startendstart)σ)\hat{\sigma}=max(1,(\frac{epoch}{total\_epoch*(end-start)}-\frac{start}{end-start})*\sigma)
    3:epochtotal_epoch>end\frac{epoch}{total\_epoch}>end时,σ^=max(1,(epochtotal_epoch(endstart)startendstart)σ))\hat{\sigma}=max(1,(\frac{epoch}{total\_epoch*(end-start)}-\frac{start}{end-start})*\sigma))
    与测试2相比,进入第三阶段后,会放大σ\sigma
    经过实验测试,本方法会比测试2稳定很多,在第三阶段仍然能够出现一定的上涨,稳定的收敛到92.24%。
  • 测试4
    基于测试2的结果,将max中的1从常数变成逐渐缩小的。
    α=epochtotal_epoch(startend)endstartend\alpha = \frac{epoch}{total\_epoch*(start-end)}-\frac{end}{start-end}
    1:epochtotal_epoch<start=0.1\frac{epoch}{total\_epoch}<start = 0.1时,σ^=1\hat{\sigma}=1
    2:epochtotal_epoch<end=0.9\frac{epoch}{total\_epoch}<end= 0.9时,σ^=max(α,(epochtotal_epoch(endstart)startendstart)σ)\hat{\sigma}=max(\alpha ,(\frac{epoch}{total\_epoch*(end-start)}-\frac{start}{end-start})*\sigma)
    3:epochtotal_epoch>end\frac{epoch}{total\_epoch}>end时,σ^=max(1,σ)\hat{\sigma}=max(1,\sigma)
    这个实验效果很差,无论是收敛速度还是最终效果都比较差,只有91.75%。但是比较有意思的是,当训练的最后阶段,max值停止变动时,训练效果可以稳定提升。推测出现这种情况的原因时,max不能太小,或者是max变动会导致训练不稳定
  • 总结
    测试3 的方法究竟有什么好处?更快的收敛究竟意味着什么?
    接下来的实验要从三方面入手:
    1:该方法是否稳定?
    2:该方法究竟有什么好处?
    3:该方法能够进一步优化?
    针对第一点,比较好的方法就是多个数据集检验。鉴于目前算力,只在svhn和cifar100上跑一下就可以,应该足够说明问题。
    针对第二点,目前FRN面临的问题就是训练困难。需要采用warmup和cosine形式的lr下降方式才能work。这种新的训练方式能否降低对这些技巧的依赖,使得该方法更加普适?
    针对第三点,这种训练方式也许说明了方差不那么重要。能否用其他的东西来代替方差?另外,这种方法对BN有没有效果?

2:max函数导数修正

接下来,基于最初的FRN版本

  • FRN:y=max(γxσfrn+β,τ),σfrn=xi2HWFRN:y=max(\gamma\frac{x}{\sigma_{frn}}+\beta,\tau),\sigma_{frn}=\sqrt{\frac{\sum x_i^2}{H*W}}
    尝试对其导数进行修改。因为上式有一半的时间是对tau不进行梯度更新的。借鉴RCF的技术,将tau的梯度为0时的情况变成梯度不为0.

2.1:Max导数修正V1

yτ>0=τmax(x/detach(τ),1),(τ>0)={τxdetach(τ),if x > τ ,τ>0τ,if x < τ ,τ>0y_{\tau>0}=\tau *max(x/detach(\tau),1),(\tau>0)\\ = \begin{cases}\tau*\frac{x}{detach(\tau)}, & \text {if x > $\tau$ ,$\tau>0$} \\ \tau, & \text{if x < $\tau$ ,$\tau>0$}\end{cases}

yτ<0=τmin(x/detach(τ),1),(τ<0)={τxdetach(τ),if x > τ ,τ<0τ,if x < τ ,τ<0y_{\tau<0}=\tau *min(x/detach(\tau),1),(\tau<0) \\= \begin{cases}\tau*\frac{x}{detach(\tau)}, & \text {if x > $\tau$ ,$\tau<0$} \\ \tau, & \text{if x < $\tau$ ,$\tau<0$}\end{cases}
yτ={xdetach(τ)if x > τ ,τ>01,if x <τ ,τ>0\frac{\partial y}{\partial \tau} = \begin{cases}\frac{x}{detach(\tau)}& \text {if x > $\tau$ ,$\tau>0$}\\1,& \text {if x <$\tau$ ,$\tau>0$}\end{cases}
所以,
Lτ=Lyyτ=Ly{xdetach(τ)if x > τ ,τ>01,if x <τ ,τ>0\frac{\partial L}{\partial \tau}=\frac{\partial L}{\partial y}\frac{\partial y}{\partial \tau}=\frac{\partial L}{\partial y}*\begin{cases}\frac{x}{detach(\tau)}& \text {if x > $\tau$ ,$\tau>0$}\\1,& \text {if x <$\tau$ ,$\tau>0$}\end{cases}
这样做的效果不达预期

Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max导数修正V1 90.49%

2.2:Max导数修正V2

Lτ=Lyyτ=Ly{1if x > τ ,τ>01,if x <τ ,τ>0\frac{\partial L}{\partial \tau}=\frac{\partial L}{\partial y}\frac{\partial y}{\partial \tau}=\frac{\partial L}{\partial y}*\begin{cases}-1& \text {if x > $\tau$ ,$\tau>0$}\\1,& \text {if x <$\tau$ ,$\tau>0$}\end{cases}
这样做并没有取得好的效果

Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max导数修正V1 90.49%
Max导数修正V2 92.02%

2.3:Max导数修正V3

Lτ=Lyyτ=Ly{mean(y)τif x > τ ,τ>01,if x <τ ,τ>0\frac{\partial L}{\partial \tau}=\frac{\partial L}{\partial y}\frac{\partial y}{\partial \tau}=\frac{\partial L}{\partial y}*\begin{cases}mean(y) - \tau& \text {if x > $\tau$ ,$\tau>0$}\\1,& \text {if x <$\tau$ ,$\tau>0$}\end{cases}

Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max导数修正V1 90.49%
Max导数修正V2 92.02%
Max导数修正V3 91.47%

2.4:Max导数修正V4

Lτ=Lyyτ=Ly{1if x > τ ,τ>01,if x <τ ,τ>0\frac{\partial L}{\partial \tau}=\frac{\partial L}{\partial y}\frac{\partial y}{\partial \tau}=\frac{\partial L}{\partial y}*\begin{cases}1& \text {if x > $\tau$ ,$\tau>0$}\\1,& \text {if x <$\tau$ ,$\tau>0$}\end{cases}

Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max导数修正V1 90.49%
Max导数修正V2 92.02%
Max导数修正V3 91.47%
Max导数修正V4 92.13%

2.5:Max导数修正V5

首先修改正向传播值

  • y=max(γxσfrn+β,τ)τ,σfrn=xi2HWy=max(\gamma\frac{x}{\sigma_{frn}}+\beta,\tau) - \tau,\sigma_{frn}=\sqrt{\frac{\sum x_i^2}{H*W}}
    这样做,τ\tau的作用会非常类似于mean。以各个channel的mean为基准修正τ\tau,以期获得更快的收敛速度
    导数的计算方式与V3一样。
    Lτ=Lyyτ=Ly{mean(y)τif x > τ ,τ>01,if x <τ ,τ>0\frac{\partial L}{\partial \tau}=\frac{\partial L}{\partial y}\frac{\partial y}{\partial \tau}=\frac{\partial L}{\partial y}*\begin{cases}mean(y) - \tau& \text {if x > $\tau$ ,$\tau>0$}\\1,& \text {if x <$\tau$ ,$\tau>0$}\end{cases}
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max导数修正V1 90.49%
Max导数修正V2 92.02%
Max导数修正V3 91.47%
Max导数修正V4 92.13%
Max导数修正V5 89.35%

2.6:Max导数修正V6

首先修改正向传播值

  • y=max(γxσfrn+β,τ)τ,σfrn=xi2HWy=max(\gamma\frac{x}{\sigma_{frn}}+\beta,\tau) - \tau,\sigma_{frn}=\sqrt{\frac{\sum x_i^2}{H*W}}
    这样做,τ\tau的作用会非常类似于mean。以各个channel的mean为基准修正τ\tau,以期获得更快的收敛速度
    导数与V5的区别是,
    Lτ=Lyyτ=Ly{mean(y)τ1if x > τ ,τ>00,if x <τ ,τ>0\frac{\partial L}{\partial \tau}=\frac{\partial L}{\partial y}\frac{\partial y}{\partial \tau}=\frac{\partial L}{\partial y}*\begin{cases}mean(y) - \tau - 1& \text {if x > $\tau$ ,$\tau>0$}\\0,& \text {if x <$\tau$ ,$\tau>0$}\end{cases}
Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
Max导数修正V1 90.49%
Max导数修正V2 92.02%
Max导数修正V3 91.47%
Max导数修正V4 92.13%
Max导数修正V5 89.35%
Max导数修正V6 91.00%

3:BN,LN,GN上对lr方法的测试

经过实验发现,在BN,LN上应用lr测试3的方法,并不work。BN会大大降低训练速度,LN的数值会急剧增大,出现nan值。GN上没有测试,估计也不行。

4:warm up 和cosine decay是必须的

经过实验测试,在没有warm up的时候,FRN是不收敛的,lr测试3的方法也是,所以warm up对新方法来说,仍然是必须的
同时,cosine decay也是必须的

一些尝试

FRN中除以σfrn\sigma_{frn}后,对x导数有很大影响。
在这里插入图片描述
那么,如果认为σfrn\sigma_{frn}只是一个常数,与x无关,那么上式可以写成
fx=1σfrn2+ϵfx^\frac{\partial f}{\partial x}=\frac{1}{\sqrt{\sigma_{frn}^{2}+\epsilon}}*\frac{\partial f}{\partial \hat{x}}
经过实验发现,准确率出现很大的降低。

Image per GPU 128 32(batchsize:64,GPU:2)
BN 93.01% 92.01%
FRN 92.30% 92.31%
No_sigma_FRN_V1 91.51% 91.50%
No_sigma_FRN_V2 91.71% 91.71%
No_grad_FRN 91.0%

如果没有导数,甚至还不如直接不除σfrn\sigma_{frn}


4:代码单元测试部分

先检查模块的正确性,再做实验

FRN单元测试

比较了paper中tensorflow版本的输出和自己实现的pytorch版本的输出。

import tensorflow as tf
tf.__version__

def FRNLayer(x, tau, beta, gamma, eps=1e-6):
    nu2 = tf.reduce_mean(tf.square(x), axis=[1,2], keepdims=True)
    x = x / tf.sqrt(nu2 + tf.abs(eps))
    # return tf.maximum(gamma * x + beta, tau)
    return tf.maximum(gamma * x + beta,tau)

x = tf.reshape(tf.range(2,34.),[1,4,4,2])
print(x[0,:,:,0])
gamma = tf.Variable(tf.ones([1,1,1,2]))
beta = tf.Variable(tf.zeros([1,1,1,2]))
tau = tf.Variable(tf.zeros([1,1,1,2]))
with tf.GradientTape() as g:
    g.watch(x)
    y = FRNLayer(x,tau,beta,gamma)
    loss = tf.reduce_sum(y)
print('output:',y[0,:,:,0])
print('loss:',loss)
# dl_dgamma = g.gradient(loss,gamma)
# print(dl_dgamma)

# dl_dbeta = g.gradient(loss,beta)
# print(dl_dbeta)

dl_dtau = g.gradient(loss,tau)
print(dl_dtau)

在这里插入图片描述

class FilterResponseNormalization(nn.Module):
    def __init__(self, num_features, eps=1e-6):
        """
        Input Variables:
        ----------------
            beta, gamma, tau: Variables of shape [1, C, 1, 1].
            eps: A scalar constant or learnable variable.
        """

        super(FilterResponseNormalization, self).__init__()
        self.beta = nn.parameter.Parameter(
             torch.Tensor(1, num_features, 1, 1), requires_grad=True)
        self.gamma = nn.parameter.Parameter(
             torch.Tensor(1, num_features, 1, 1), requires_grad=True)
        self.tau = nn.parameter.Parameter(
             torch.Tensor(1, num_features, 1, 1), requires_grad=True)
        self.eps = nn.parameter.Parameter(torch.Tensor([eps]))
        self.reset_parameters()
    def reset_parameters(self):
        nn.init.ones_(self.gamma)
        nn.init.zeros_(self.beta)
        nn.init.zeros_(self.tau)
    def forward(self, x):
        """
        Input Variables:
        ----------------
            x: Input tensor of shape [NxCxHxW]
        """

        n, c, h, w = x.shape
        assert (self.gamma.shape[1], self.beta.shape[1], self.tau.shape[1]) == (c, c, c)

        # Compute the mean norm of activations per channel
        nu2 = x.pow(2).mean(dim=(2,3), keepdim=True)
        # Perform FRN
        x = x * torch.rsqrt(nu2 + torch.abs(self.eps))
        # Return after applying the Offset-ReLU non-linearity
        # return torch.max(self.gamma*x + self.beta, self.tau)
        return torch.max(self.gamma * x + self.beta,self.tau)
x = torch.transpose(torch.transpose(torch.arange(2,34.).reshape([1,4,4,2]),1,3),2,3)

print(x[0,0,:,:])
frn = FilterResponseNormalization(2)

y = frn(x)
print('output:',y[0,0,:,:])
print("loss:",loss)
loss = torch.sum(y)
loss.backward()
print(frn.tau.grad)

在这里插入图片描述
从导数和输出值来看,pytorch版本的结果是没有问题的。

max_min_FRN单元测试

在这里插入图片描述

import torch 

x = torch.arange(0,16,dtype=torch.float32).reshape(1,1,4,4)
n, c, h, w = x.shape
print(x.shape)
channel_max = torch.max(torch.max(x,dim=2,keepdim=True)[0],dim=3,keepdim=True)[0]
channel_min = torch.min(torch.min(x,dim=2,keepdim=True)[0],dim=3,keepdim=True)[0]

print(channel_max)
print(channel_min)

Cn = torch.log(torch.tensor(h * w + 0.000001)) * 2
print(Cn)

在这里插入图片描述

MyMax模块单元测试

import torch 

class MyMax(torch.autograd.Function):
    @staticmethod
    def forward(self, x, tau):

        self.save_for_backward(x, tau)
        output = torch.max(x, tau)
        return output

    @staticmethod
    def backward(self, grad_output):

        x, tau = self.saved_tensors
        dl_dx = grad_output.clone()
        dl_dx[x < tau] = 0

        dl_dtau = grad_output.clone()
        # x_max = torch.max(torch.max(torch.max(x,dim=0,keepdim=True)[0],
        #                             dim=2,keepdim=True)[0],dim=3,keepdim=True)[0]
        # x_min = torch.min(torch.min(torch.min(x,dim=0,keepdim=True)[0],
        #                             dim=2,keepdim=True)[0],dim=3,keepdim=True)[0]
        # mu = (x_max + x_min)/2
        # mu = x.mean([0,2,3],keepdim=True)
        A = (x > tau).float() * (x / (tau + 1e-6)) * dl_dtau
        print("A")
        print(A)
        # print("A",A.device)
        # num = torch.sum(x > tau, dim=(0, 2, 3), keepdim=True).to(A.device)
        # print("num:",num.device)
        dl_dtau = dl_dtau*(x < tau).float() + A
        # print(dl_dtau.shape)
        # dl_dtau[x > tau] = x / (tau + 1e-6)
        # dl_dtau = dl_dtau.mean([0, 2, 3], keepdim=True)
        return dl_dx, dl_dtau

x = torch.nn.parameter.Parameter(torch.reshape(torch.range(1,8.),[2,2,2,1]))
print(x[0,0,:,:])
tau = torch.nn.parameter.Parameter(4 * torch.ones([1,2,1,1]))
max_ = MyMax.apply
y = max_(x, tau)
print("y",y.shape)
loss = torch.sum(y)
loss.backward()
print("tau:")
print(tau.grad)
print("x:")
print(x.grad[1,1,:,:])

在这里插入图片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章