在 pytorch 中反向传播时自动更新自定义层参数
Auto updating custom layer parameters while backpropagating in pytorch
我有一个 pytorch 自定义层定义为:
class MyCustomLayer(nn.Module):
def __init__(self):
super(MyCustomLayer, self).__init__()
self.my_parameter = torch.rand(1, requires_grad = True)
# the following allows the previously defined parameter to be recognized as a network parameter when instantiating the model
self.my_registered_parameter = nn.ParameterList([nn.Parameter(self.my_parameter)])
def forward(self, x):
return x*self.my_parameter
然后我在使用自定义层的地方定义我的网络:
class MyNet(nn.Module):
def __init__(self):
super(MyNet, self).__init__()
self.layer1 = MyCustomLayer()
def forward(self, x):
x = self.layer1(x)
return x
现在让我们实例化 MyNet 并观察问题:
# instantiate MyNet and run it over one input value
model = MyNet()
x = torch.tensor(torch.rand(1))
output = model(x)
criterion = nn.MSELoss()
loss = criterion(1, output)
loss.backward()
迭代模型参数显示 None
自定义层参数:
for p in model.parameters():
print (p.grad)
None
直接访问该参数显示正确的 grad
值:
print(model.layer1.my_parameter.grad)
tensor([-1.4370])
反过来,这会阻止优化步骤自动更新内部参数,让我不得不手动更新这些参数。有人知道我该如何解决这个问题吗?
好的!
我不得不将自定义层中的参数变量调用切换到 nn.ParameterList
对象(即 return x*self.my_registered_parameter[0]
而不是 x*self.my_parameter )。在此示例中,这意味着将转发方法中自定义图层的参数调用更改为:
def forward(self, x):
return x*self.my_registered_parameter[0]
如果按引用传递!
现在 optim 按预期更新了所有参数!
你所做的,即 return x*self.my_registered_parameter[0]
之所以有效,是因为你使用注册的参数来计算梯度。
当您调用 nn.Parameter
时,它 returns 一个新对象,因此您用于操作的 self.my_parameter
与注册的对象不同。
您可以通过将 my_parameter
声明为 nn.Parameter
来解决此问题
self.my_parameter = nn.Parameter(torch.rand(1, requires_grad = True))
self.my_registered_parameter= nn.ParameterList([self.some_parameter])
或者您根本不需要创建 my_registered_parameter
变量。当您将 self.my_parameter
声明为 nn.Parameter
时,它会注册为参数。
我有一个 pytorch 自定义层定义为:
class MyCustomLayer(nn.Module):
def __init__(self):
super(MyCustomLayer, self).__init__()
self.my_parameter = torch.rand(1, requires_grad = True)
# the following allows the previously defined parameter to be recognized as a network parameter when instantiating the model
self.my_registered_parameter = nn.ParameterList([nn.Parameter(self.my_parameter)])
def forward(self, x):
return x*self.my_parameter
然后我在使用自定义层的地方定义我的网络:
class MyNet(nn.Module):
def __init__(self):
super(MyNet, self).__init__()
self.layer1 = MyCustomLayer()
def forward(self, x):
x = self.layer1(x)
return x
现在让我们实例化 MyNet 并观察问题:
# instantiate MyNet and run it over one input value
model = MyNet()
x = torch.tensor(torch.rand(1))
output = model(x)
criterion = nn.MSELoss()
loss = criterion(1, output)
loss.backward()
迭代模型参数显示 None
自定义层参数:
for p in model.parameters():
print (p.grad)
None
直接访问该参数显示正确的 grad
值:
print(model.layer1.my_parameter.grad)
tensor([-1.4370])
反过来,这会阻止优化步骤自动更新内部参数,让我不得不手动更新这些参数。有人知道我该如何解决这个问题吗?
好的!
我不得不将自定义层中的参数变量调用切换到 nn.ParameterList
对象(即 return x*self.my_registered_parameter[0]
而不是 x*self.my_parameter )。在此示例中,这意味着将转发方法中自定义图层的参数调用更改为:
def forward(self, x):
return x*self.my_registered_parameter[0]
如果按引用传递!
现在 optim 按预期更新了所有参数!
你所做的,即 return x*self.my_registered_parameter[0]
之所以有效,是因为你使用注册的参数来计算梯度。
当您调用 nn.Parameter
时,它 returns 一个新对象,因此您用于操作的 self.my_parameter
与注册的对象不同。
您可以通过将 my_parameter
声明为 nn.Parameter
self.my_parameter = nn.Parameter(torch.rand(1, requires_grad = True))
self.my_registered_parameter= nn.ParameterList([self.some_parameter])
或者您根本不需要创建 my_registered_parameter
变量。当您将 self.my_parameter
声明为 nn.Parameter
时,它会注册为参数。