Pytorch的优化器都自带正则化,比如
optimizer = optim.Adam(model.parameters(),lr=learning_rate,weight_decay=0.01)
optimizer = optim.SGD(model.parameters(), lr=learing_rate, momentum=0.9,weight_decay=0.01)
其中的weight_decay就是正则化系数,设定为0或者不设定就是无正则化。但这个优化器自带正则化有两个特点,一是只能是L2正则,二是它将所有的参数都进行了正则化,包括权重、偏执及其他的一些。
可以模仿tensorflow自己加正则化,这包括几个步骤:获得需要加正则的参数,将这些参数的正则化和表示出来,将这个和加入损失函数。下面采用一个类来具体介绍,先给出代码。
class Regularization(nn.Module):
def __init__(self,model,weight_decay,p=2):
super(Regularization, self).__init__()
self.model = model
self.weight_decay = weight_decay
self.p = p
self.weight_list = self.get_weight(model)
self.weight_info(self.weight_list)
#在训练过程中每次调用需要
def forward(self,model):
self.weight_list = self.get_weight(model)
reg_loss = self.regularization_loss(self.weight_list,self.weight_decay,p=self.p)
return reg_loss
#确定设备
def to(self, device):
self.device = device
super().to(device)
return self
#得到正则化参数
def get_weight(self, model):
weight_list = []
for name, param in model.named_parameters():
if 'weight' in name:
weight = (name, param)
weight_list.append(weight)
return weight_list
#求取正则化的和
def regularization_loss(self, weight_list, weight_decay, p=2):
reg_loss = 0
for name, w in weight_list:
l2_reg = torch.norm(w, p=p)
reg_loss = reg_loss + l2_reg
reg_loss = weight_decay * reg_loss
return reg_loss
#打印有哪些参数
def weight_info(self, weight_list):
print("---------------regularization weight---------------")
for name, w in weight_list:
print(name)
print("---------------------------------------------------")
这个类需要传入模型model,正则化系数weight_decay。p是决定L1正则还是L2正则的一个系数,p=1代表L1,p=2代表L2.
其中get_weight(self, model)函数用于获取参数列表,里面只获取权重列表,如果要获取其他可以自行修改,但一般来说,都是获取权重。weight_info(self, weight_list)函数用于打印获取的权重,可以知晓都获得了哪些层的权重,得到的结果如下面的例子所示:
regularization_loss(self, weight_list, weight_decay, p=2)函数用于具体的计算正则化。它的原理很简单,就是取出每个参数值,然后求一范数或者二范数,再求和。to(self, device)函数和forward(self,model)函数是继承nn.Module()所常用的两个函数。
首先,把这个函数完整的放入代码中
然后,在你的模型建立的时候也调用一下这个,像这样
reg_loss = Regularization(model, weight_decay, p=2).to(device)
将这一行放在迭代训练开始前就可以,和优化器什么的放一起
最后,在你的损失里面加入正则损失,像下面这样,其中第一行是真实损失,第二行是加入正则后的损失
loss = criterion(y_pred, labels.long())
loss = loss + reg_loss(model)
在训练过程中将loss.item()输出一下,可以看到具体损失值是多少,大倍数的改变正则化系数weight_decay,如果loss.item的输出变化很大,那么就是加入了
以上内容都是在看了一个github后总结的,原代码地址如下
https://github.com/PanJinquan/pytorch-learning-tutorials/blob/master/image_classification/train_resNet.py