【问题标题】:Pytorch model gradients no updating with some custom codePytorch 模型渐变没有使用一些自定义代码进行更新
【发布时间】:2021-07-29 18:48:26
【问题描述】:

我已经进行了一些计算,试图计算结果的损失,并计算模型 w.r.t 的所有参数的梯度。那个损失。问题在于,计算中包含一个可调模型,我希望能够(最终)调整它。现在我只是想确认当模型参数用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,但我仍然无法让它工作。这应该有效吗?有人有任何提示吗?谢谢。

【问题讨论】:

    标签: python pytorch gradient


    【解决方案1】:

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

    >>> 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>)
    

    【讨论】:

      猜你喜欢
      • 2020-06-07
      • 2021-12-23
      • 2021-12-09
      • 2019-09-20
      • 1970-01-01
      • 2020-01-22
      • 1970-01-01
      • 2013-01-25
      • 1970-01-01
      相关资源
      最近更新 更多