我在学习PyTorch教程,刚了解到optimizer.step
是如何更新网络参数的(这里)。
有没有一种方法可以创建一个函数,每当有梯度更新到每个可学习的参数(例如权重)时,该函数会获取权重值和损失,并将该值乘以某个百分比,比如90%
?
所以如果更新应该是:w1 -= lr * loss_value = 1e-5 * 50
,我希望它在更新之前通过该函数,并使其变为1e-5 * 50 * 90%
def func(loss_value, percentage): return loss_value * percentage #新的更新应该是 w1 -= loss_value * percentage
示例模型:
import torchimport torch.nn as nnimport torch.optim as optimclass Model(nn.Module): def __init__(self): super(Model, self).__init__() self.fc1 = nn.Linear(1, 5) self.fc2 = nn.Linear(5, 10) self.fc3 = nn.Linear(10, 1) def forward(self, x): x = self.fc1(x) x = torch.relu(x) x = torch.relu(self.fc2(x)) x = self.fc3(x) return xnet = Model()opt = optim.Adam(net.parameters())features = torch.rand((3,1)) opt.zero_grad()out = net(features)loss = torch.tensor(5) - torch.sum(out)loss.backward()# 需要在优化器更新之前使用函数改变损失更新的值?opt.step()
回答:
我从https://discuss.pytorch.org/t/how-to-modify-the-gradient-manually/7483/2获取了这段代码,并稍作编辑:
loss.backward()for p in model.parameters(): weights = p.data scales = def_scales(weights) p.grad *= scales # 或其他任何操作optimizer.step()
这段代码会在模型中的每个参数(在loss.backward()
和优化器步伐之前)之间运行,并在反向传播应用之前调整其存储的梯度。
一个示例def_scales
看起来会像这样(非常丑陋),其中vals
是比较的参数值,scales
是所需的损失缩放值:
def def_scales(weights,scales=[0.1,0.5,1,1],vals=[0,5,10,float('inf')]): out = torch.zeros_like(weights) for V,v in enumerate(vals[::-1]): #向后遍历,因为我们是在做小于比较 out[weights<=v] = scales[len(scales)-V-1] #可能需要与绝对值比较 return out