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,:,:])

在這裏插入圖片描述

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