Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift的思考

文章基于的假设固定输入层输入的分布可以加快训练,防止出现梯度衰减。

收获:

1.如果有疑问可以做简单的实验。

2.BN层只是从一定程度上解决了梯度衰减的问题但是并没有完全解决如果输入值的差距过大会导致模型加BN层后loss依旧无变化。看代码1:

3.BN层在train和eval模型对相同的数据输出值不相同可能对网络的准确率有一定影响。eval情况下BN层的输出像归一化实际上并不是归一化。这是因为参数momentum你设置为0就是论文对应的BN层了。不过对于一些数据来说没啥用。

记录一次轮数network和network1的输出即BN层。

tensor([[39928.2773],
[79855.9531]], grad_fn=)
tensor([[-8.2226],
[ 8.2227]], grad_fn=)
tensor([[39928.2773],
[79855.9531]], grad_fn=)
tensor([[-5.8143],
[ 5.8143]], grad_fn=)看代码2:

4.BN层保持变量的分布,因为前面多层参数变化可能会导致分布变化导致模型出现梯度衰减。

5.BN层进行批归一化的原因:为了固定激活函数的输入分布,防止前边网络层参数改变导致输入分布变化导致模型过拟合。

6.BN层的误区;以为卷积层的b无效,当网络处于验证模式下只能用wx拟合数据而不是wx+b可能不能区分某些数据集。其实BN层第一步是归一化第二步就是wx+b。

7.BN层设置为train和eval。如果参考原文章的话momentum=0。

train和eval都是按文章进行训练归一化验证不归一化。

momentum不是0的话,训练和验证都进行归一化,都是方差和均值算法如下x=(1−momentum)×+momentum×xt,xt是当前的值,x是以往的值。

eval的归一化是通过momentum算的,算出一个全局的均值和方差。train直接在mini-batch上进行批归一化。看代码3。

代码1:

from enum import auto
from scipy.io import loadmat
import numpy as np
import torch
import torch.utils.data as data_utils
from torch import nn
import torch.optim as optim
network=nn.Linear(1,1)
network1=nn.BatchNorm1d(1)
w=nn.Sigmoid()
tr=torch.Tensor([[1],[20000000000000]])
#tr=torch.Tensor([[1],[2]])
test=torch.Tensor([[150000],[300000]])
optimizer = optim.Adam(network.parameters(), lr=0.04)
optimizer1 = optim.Adam(network1.parameters(), lr=0.04)
for i in range(5000):
network.train()
network1.train()
#network1.eval()#
optimizer.zero_grad()
optimizer1.zero_grad()
l=w(network1(network(tr)))
#print(network1(network(tr)))
l=(l[0]-0)**2+(l[1]-1)**2
l.backward()
optimizer.step()
optimizer1.step()
print(l)

代码2:
from enum import auto
from scipy.io import loadmat
import numpy as np
import torch
import torch.utils.data as data_utils
from torch import nn
import torch.optim as optim
network=nn.Linear(1,1)
network1=nn.BatchNorm1d(1)
w=nn.Sigmoid()
tr=torch.Tensor([[100000],[200000]])
#tr=torch.Tensor([[1],[2]])
test=torch.Tensor([[150000],[300000]])
optimizer = optim.Adam(network.parameters(), lr=0.04)
optimizer1 = optim.Adam(network1.parameters(), lr=0.04)
l1=0
while True:
network.train()
network1.train()
#network1.eval()#
optimizer.zero_grad()
optimizer1.zero_grad()
l=w(network1(network(tr)))
#print(network1(network(tr)))
l=(l[0]-0)**2+(l[1]-1)**2
l.backward()
optimizer.step()
optimizer1.step()
print(l)
if l1==0:
l1=l
#network.eval()
if l1/l>100:
print(network(tr))
print(network1(network(tr)))
#print(w(network1(network(tr))))
network.eval()
network1.eval()
print(network(tr))
print(network1(network(tr)))
#print(w(network1(network(tr))))
print(1)
l1=l
代码3:
from enum import auto
from scipy.io import loadmat
import numpy as np
import torch
import torch.utils.data as data_utils
from torch import nn
import torch.optim as optim
network=nn.Linear(1,1,bias=False)
network1=nn.BatchNorm1d(1,affine=True,momentum=0)
w=nn.Sigmoid()
#tr=torch.Tensor([[-200000000000000000],[200000000000000000]])
#tr=torch.Tensor([[1],[2]])
tr=torch.Tensor([[100000],[200000]])
m=nn.BatchNorm1d(1,affine=False,momentum=0.1)
m.eval()
print(m(tr))
print(m.running_mean)
m.train()
print(m(tr))
print((tr-m.running_mean)/np.sqrt(m.running_var))
print(m.running_mean)
print(m.running_var)

print(m(tr))
print((tr-m.running_mean)/np.sqrt(m.running_var))
print(m.running_mean)
print(m.running_var)

m.eval()
print(m.running_mean)
print(m.running_var)
print((tr-m.running_mean)/np.sqrt(m.running_var))
print(m(tr))

你可能感兴趣的:(深度学习论文的复现与思考,batch,深度学习,pytorch)