Pytorch 模型梯度没有使用一些自定义代码进行更新
Pytorch model gradients no updating with some custom code
我整理了一些计算,试图计算结果的损失,并计算模型所有参数的梯度 w.r.t。那个损失。问题是计算中包含一个我希望能够(最终)调整的可调模型。现在我只是想确认当模型参数用 backward()
更新时我可以看到它们的梯度,但我不能,这就是问题所在。下面我 post 代码、输出和所需的输出。
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
's parameters' 梯度没有得到更新。我试图回顾所有的计算,所有的代码都在这里,并确保任何东西都有 requires_grad=True
但我仍然无法让它工作。这应该行得通吗?有人有任何提示吗?谢谢。
您的代码存在一些问题。您可以直接通过查看输出张量判断模型是否至少可以启动反向传播:
>>> result
tensor([...], requires_grad=True)
它没有 grad_fn
,所以您已经知道它没有连接到图表。
现在调试问题,这里有一些提示:
首先,如果您打算进行反向传播,则永远不要改变 .data
或使用 .item
。这基本上会杀死图表!因为之后执行的任何操作都不会附加到图表。
其实大多数时候你不需要使用requires_grad
。请注意 nn.Parameter
默认情况下会将 requires_grad=True
分配给张量。
在 PyTorch 管道中使用列表理解时,您可以将 list 包装成 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)
现在注意 result
附加的 grad_fn
:
>>> result
tensor([...], grad_fn=<SubBackward0>)
我整理了一些计算,试图计算结果的损失,并计算模型所有参数的梯度 w.r.t。那个损失。问题是计算中包含一个我希望能够(最终)调整的可调模型。现在我只是想确认当模型参数用 backward()
更新时我可以看到它们的梯度,但我不能,这就是问题所在。下面我 post 代码、输出和所需的输出。
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
's parameters' 梯度没有得到更新。我试图回顾所有的计算,所有的代码都在这里,并确保任何东西都有 requires_grad=True
但我仍然无法让它工作。这应该行得通吗?有人有任何提示吗?谢谢。
您的代码存在一些问题。您可以直接通过查看输出张量判断模型是否至少可以启动反向传播:
>>> result
tensor([...], requires_grad=True)
它没有 grad_fn
,所以您已经知道它没有连接到图表。
现在调试问题,这里有一些提示:
首先,如果您打算进行反向传播,则永远不要改变
.data
或使用.item
。这基本上会杀死图表!因为之后执行的任何操作都不会附加到图表。其实大多数时候你不需要使用
requires_grad
。请注意nn.Parameter
默认情况下会将requires_grad=True
分配给张量。在 PyTorch 管道中使用列表理解时,您可以将 list 包装成
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)
现在注意 result
附加的 grad_fn
:
>>> result
tensor([...], grad_fn=<SubBackward0>)