关于pyorch中的autograd,添加新的用户定义层,如何更新其参数?

时间:2018-12-28 12:51:55

标签: computer-vision pytorch autograd

所有人!

我的需求是产生光流的问题。我有两个原始图像和一个光流数据作为地面实况,现在我的算法是使用原始图像生成光流,并且可以将生成光流与地面实况之间的欧氏距离定义为损耗值,因此可以实现反向传播以更新参数。

我将其视为回归问题,现在我必须提出想法:

我可以将每个参数设置为(required_grad = true),然后计算损失,然后可以loss.backward()来获取梯度,但是我不知道如何在优化器中添加这些参数来更新它们。

我将算法写为模型。如果设计“自定义”模型,则可以初始化def init()中的几层,例如nn.Con2d(),nn.Linear(),并且可以使用(torch.optim.Adam(model.parameters ())),但是如果我自己定义新层,那么在更新参数集合时应如何添加该层的参数呢?

这个问题使我困惑了好几天。有什么好的方法可以更新用户定义的参数?如果您能给我一些建议,我将不胜感激!

1 个答案:

答案 0 :(得分:1)

如果张量值的梯度被计算出来

  1. 拥有requires_grad == True
  2. 习惯于计算您称之为.backward()的某些价值(通常是损失)。

然后,梯度将累积在其.grad参数中。您可以手动使用它们以执行任意计算(包括优化)。预定义的optimizers接受iterable of parameters,而model.parameters()就是这样做的-它返回一个可迭代的参数。如果您有一些自定义的“自由浮动”参数,则可以将其传递为

my_params = [my_param_1, my_param_2]
optim = torch.optim.Adam(my_params)

,您还可以将它们与其他可迭代参数合并,如下所示:

model_params = list(model.parameters())
my_params = [my_param_1, my_param_2]
optim = torch.optim.Adam(model_params + my_params)

但是,在实践中,通常可以构造代码来避免这种情况。有nn.Parameter类包装张量。 nn.Module的所有子类都将覆盖其__setattr__,因此,每当您将nn.Parameter的实例分配为其属性时,它都将成为Module的{​​{1}的一部分}。换句话说

.parameters()

将允许您写

class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.my_param_1 = nn.Parameter(torch.tensor(...))
        self.my_param_2 = nn.Parameter(torch.tensor(...))

,并进行module = MyModule() optim = torch.optim.Adam(module.parameters()) 更新optimmodule.my_param_1。这是首选的方式,因为它有助于使代码保持结构化

  1. 创建优化程序时,您不必手动包含所有参数
  2. 您可以调用module.zero_grad()并将其所有子module.my_param_2上的渐变归零。
  3. 您可以调用module.cuda()module.double()之类的方法,这些方法同样适用于所有子nn.Parameter,而无需手动遍历它们。