Pytorch模型渐变不更新一些自定义代码



我已经把一些计算放在一起,我试图计算结果的损失,并计算模型的所有参数的梯度。问题是,在计算中隐藏着一个可调模型,我希望能够(最终)对其进行调优。现在我只是想确认一下,当我用backward()更新模型参数时,我能看到它们的梯度,这是问题所在。下面是邮政编码、输出和期望的输出。

class ExpModelTunable(torch.nn.Module):
def __init__(self):
super(ExpModelTunable, self).__init__()
self.alpha = torch.nn.Parameter( torch.tensor(1.0, requires_grad=True) )
self.beta = torch.nn.Parameter( torch.tensor(1.0, requires_grad=True) )

def forward(self, t):
return self.alpha * torch.exp(  - self.beta * t ) 
def func_f(t, t_list):
mu = torch.tensor(0.13191110355, requires_grad=True)
running_sum = torch.sum( torch.tensor( [ f(t-ti) for ti in t_list ], requires_grad=True ) )
return mu + running_sum
def pytorch_objective_tunable(u, t_list):
global U
steps = torch.linspace(t_list[-1].item(),u.item(),100, requires_grad=True)
func_values = torch.tensor( [ func_f(steps[i], t_list) for i in range(len(steps)) ], requires_grad=True )
return torch.log(U) + torch.trapz(func_values, steps)
def newton_method(function, func, initial, t_list, iteration=200, convergence=0.0001):
for i in range(iteration): 
previous_data = initial.clone()
value = function(initial, t_list)
initial.data -= (value / func(initial.item(), t_list)).data
if torch.abs(initial - previous_data) < torch.tensor(convergence):
return initial
return initial # return our final after iteration
# call starts
f = ExpModelTunable()
U = torch.rand(1, requires_grad=True)
initial_x = torch.tensor([.1], requires_grad=True) 
t_list = torch.tensor([0.0], requires_grad=True)
result = newton_method(pytorch_objective_tunable, func_f, initial_x, t_list)
print("Next Arrival at ", result.item())

打印出来,输出是正确的,这里一切正常:Next Arrival at 4.500311374664307。我的问题出现在这里:

loss = result - torch.tensor(1)
loss.backward()
print( result.grad )
for param in f.parameters():
print(param.grad)

输出:

tensor([1.])
None #this should not be None
None #this should not be None

所以我们可以看到结果变量的梯度在更新,但是模型f的参数的梯度没有更新。我试着回到所有的计算,所有的代码都在这里,并确保任何东西都有requires_grad=True,但我仍然不能让它工作。这应该行得通吧?有人有什么建议吗?谢谢。

您的代码有几个问题。通过查看输出张量,你可以直接判断模型是否至少可以启动反向传播:

>>> result
tensor([...], requires_grad=True)

它没有grad_fn,所以你已经知道它没有连接到一个图。

现在要调试这些问题,这里有一些提示:

  • 首先,如果您计划反向传播,您不应该改变.data或使用.item。这基本上会毁掉这个图!因为之后执行的任何操作都不会附加到图形上。

  • 大多数时候你实际上不需要使用requires_grad。请注意,默认情况下nn.Parameter会将requires_grad=True赋值给张量。

  • 当在PyTorch管道中使用列表推导式时,您可以用torch.stack包装列表,这非常有效地保持它的整洁。

  • 如果我是你,我不会使用全局变量…


更正后的版本:

class ExpModelTunable(nn.Module):
def __init__(self):
super(ExpModelTunable, self).__init__()
self.alpha = nn.Parameter(torch.ones(1))
self.beta = nn.Parameter(torch.ones(1))

def forward(self, t):
return self.alpha * torch.exp(-self.beta*t) 
f = ExpModelTunable()
def func_f(t, t_list):
mu = torch.tensor(0.13191110355)
running_sum = torch.stack([f(t-ti) for ti in t_list]).sum()
return mu + running_sum
def pytorch_objective_tunable(u, t_list):
global U
steps = torch.linspace(t_list[-1].item(), u.item(), 100)
func_values = torch.stack([func_f(steps[i], t_list) for i in range(len(steps))])
return torch.log(U) + torch.trapz(func_values, steps)
# return torch.trapz(func_values, steps)
def newton_method(function, func, initial, t_list, iteration=1, convergence=0.0001):
for i in range(iteration): 
previous_data = initial.clone()
value = function(initial, t_list)
initial -= (value / func(initial, t_list))
if torch.abs(initial - previous_data) < torch.tensor(convergence):
return initial
return initial # return our final after iteration
U = torch.rand(1, requires_grad=True)
initial_x = torch.tensor([.1]) 
t_list = torch.tensor([0.0], requires_grad=True)
result = newton_method(pytorch_objective_tunable, func_f, initial_x, t_list)

现在注意grad_fn附加到result:

>>> result
tensor([...], grad_fn=<SubBackward0>)

相关内容

最新更新