1 权重衰减
为了防止过拟合,要减少模型复杂度。将线性函数权重向量的某个范数度量复杂度,因此将范数作为惩罚项加到最小化损失中。使用L2范数,对权重向量中大分量进行惩罚,使得筛选权重分布均匀的模型,L1范数将模型权重集中一小部分特征。
L2范数惩罚为:torch.sum(w.pow(2))/2
权重衰减被集成到优化算法中,用weight_decay控制
net=nn.Sequential(nn.Linear(num_inputs,1))
for param in net.parameters():
param.data.normal_()
loss=nn.MSELoss(reduction='none')
num_epochs,lr=100,0.003
trainer=torch.optim.SGD([
{"param":net[0].weight,"weight_decay":wd},
{"param":net[0].bias}],lr=lr)
对比没有进行权重衰减的算法:
trainer=torch.optim.SGD(net.parameters(),lr=lr)
对于pytorch中优化器函数感到困惑可以参考这一篇PyTorch: torch.optim 的6种优化器及优化算法介绍_torch.optim.sgd-CSDN博客
torch.optim.SGD(params, lr=<required parameter>, momentum=0, dampening=0, weight_decay=0, nesterov=False)
之后常规操作:
for epoch in range(num_epochs):
for X,y in train_iter:
trainer.zero_grad()
l=loss(net(X),y)
l.mean().backward()
trainer.step()
2 暂退法
为了让神经网络对噪声稳健,采取对每一层无偏注入噪声。相当于一定概率drop out一些神经元,使得得到的模型不过度依赖任何神经元。暂退法在训练中间使用。
暂退法的从零实现
def dropout_layer(X,dropout):#dropout是概率
assert 0<=dropout<=1
if dropout==1:
return torch.zeros_like(X)
if dropout==0:
return X
mask=(torch.randn(X.shape)>dropout).float()
return mask*X/(1-dropout)#除以是为了保证均值不变
两种实现方法:
1:
class Net(nn.Module):
def __init__(self,num_inputs,num_outputs,num_hiddens1,num_hiddens2,
is_training=True)
super(Net,self).__init__()
self.num_inputs=num_inputs
self.training=is_training
self.lin1=nn.Linear(num_inputs,num_hiddens1)
self.lin2=nn.Linear(num_hiddens1,num_hiddens2)
self.lin3=nn.Linear(num_hiddens2,num_outputs)
self.relu=nn.Relu
def forward(self,X):
H1=self.relu(self.lin1(X.reshape((-1,num_inputs))))
if self.training==True:#训练时才使用暂退法
H1=dropout_layer(H1,dropout1)
H2=self.relu(self.lin2(H2))
if self.training==True:#训练时才使用暂退法
H2=dropout_layer(H2,dropout2)
out=self.lin3(H2)
return out
2:
net=nn.Sequential(nn.Flatten(),
nn.Linear(784,256),
nn.Relu(),
nn.Dropout(dropout1),#训练时起作用,测试时不起作用
nn.Linear(256,256),
nn.Relu(),
nn.Dropout(dropout2),
nn.Linear(256,10))
def init_weight(m):
if type(m)==nn.Linear:
nn.init.normal_(m.weight,std=0.01)
net.apply(init_weights);
net.apply(init_weights)
的作用是将初始化权重函数init_weights
应用于神经网络net
中的每个线性层(nn.Linear
)。具体来说,net.apply(init_weights)
会迭代遍历神经网络中的每个模块,并判断其是否为线性层。对于线性层,它会调用init_weights
函数来初始化权重。在给定的代码中,init_weights
函数会判断输入的模块类型是否为线性层。如果是线性层(nn.Linear
),则使用nn.init.normal_
来按照指定的均值和标准差进行正态分布的初始化。这里的指定标准差为0.01。通过调用net.apply(init_weights)
,可以方便地为神经网络中的线性层进行统一的权重初始化操作。这有助于模型在训练过程中更好地收敛,并提高模型的性能。