Python 如何在nn.顺序模型中使用自定义torch.autograd.Function
是否有任何方法可以在Python 如何在nn.顺序模型中使用自定义torch.autograd.Function,python,pytorch,torch,Python,Pytorch,Torch,是否有任何方法可以在nn.Sequential对象中使用自定义torch.autograd.Function,或者我应该显式使用带有向前函数的nn.Module对象。具体来说,我正在尝试实现一个稀疏自动编码器,我需要将代码的L1距离(隐藏表示)添加到丢失中。 我在下面定义了自定义torch.autograd.Functionl1,然后尝试在nn.Sequential对象中使用它,如下所示。但是,当我运行时,我得到了错误TypeError:\uuuuu main\uuul1。惩罚不是模块子类如何解
nn.Sequential
对象中使用自定义torch.autograd.Function
,或者我应该显式使用带有向前函数的nn.Module
对象。具体来说,我正在尝试实现一个稀疏自动编码器,我需要将代码的L1距离(隐藏表示)添加到丢失中。
我在下面定义了自定义torch.autograd.Function
l1,然后尝试在nn.Sequential
对象中使用它,如下所示。但是,当我运行时,我得到了错误TypeError:\uuuuu main\uuul1。惩罚不是模块子类
如何解决此问题
class L1Penalty(torch.autograd.Function):
@staticmethod
def forward(ctx, input, l1weight = 0.1):
ctx.save_for_backward(input)
ctx.l1weight = l1weight
return input, None
@staticmethod
def backward(ctx, grad_output):
input, = ctx.saved_variables
grad_input = input.clone().sign().mul(ctx.l1weight)
grad_input+=grad_output
return grad_input
nn.Module
API似乎工作正常,但在l1
forward
方法中不应返回None
import torch, torch.nn as nn
class L1Penalty(torch.autograd.Function):
@staticmethod
def forward(ctx, input, l1weight = 0.1):
ctx.save_for_backward(input)
ctx.l1weight = l1weight
return input
@staticmethod
def backward(ctx, grad_output):
input, = ctx.saved_variables
grad_input = input.clone().sign().mul(ctx.l1weight)
grad_input+=grad_output
return grad_input
class Model(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(10,10)
self.fc2 = nn.Linear(10,6)
self.fc3 = nn.Linear(6,10)
self.fc4 = nn.Linear(10,10)
self.relu = nn.ReLU(inplace=True)
self.penalty = L1Penalty()
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.penalty.apply(x)
x = self.fc3(x)
x = self.relu(x)
x = self.fc4(x)
x = self.relu(x)
return x
model = Model()
a = torch.rand(50,10)
b = model(a)
print(b.shape)
正确的方法是这样做
导入火炬,火炬.nn作为nn
L1类惩罚(火炬自动悬挂功能):
@静力学方法
def前进(ctx,输入,L1重量=0.1):
ctx.save_for_backward(输入)
ctx.L1重量=L1重量
返回输入
@静力学方法
def向后(ctx、梯度输出):
输入,=ctx.saved\u变量
grad_input=input.clone().sign().mul(ctx.l1weight)
梯度输入+=梯度输出
返回梯度输入
创建充当包装器的Lambda类
类Lambda(nn.模块):
"""
输入:一个函数
返回:可以使用的模块
内部nn.顺序
"""
定义初始化(self,func):
super()。\uuuu init\uuuuu()
self.func=func
def forward(self,x):返回self.func(x)
塔达
model=nn.Sequential(
nn.线性(10,10),
nn.ReLU(),
nn.线性(10,6),
nn.ReLU(),
#稀疏
Lambda(L1处罚。适用),
nn.线性(6,10),
nn.ReLU(),
nn.线性(10,10),
nn.ReLU())
a=火炬兰特(50,10)
b=型号(a)
印刷品(b.shape)
有要共享的代码吗?当然,我已经编辑了这个问题。因此,在我看来,您希望在前进模式中像使用身份函数一样使用它,并希望在后退模式中用系数(0.1)乘以梯度。这是正确的吗?您的autograd函数似乎也不正确:a=torch.rand(50,10);f=l1惩罚();b=f(a)
这给出了TypeError:forward()缺少1个必需的位置参数:“input”
。这可能是您的问题的真正原因error@PiyushSingh在前进模式中,我想要你提到的身份,但在后退模式中,我想要在渐变中添加0.1*(该层的激活)。另外,当您将函数调用为f.apply(a)时,它也可以工作。然而,也许当我以这种方式实例化函数时;默认情况下,pytorch按您所做的方式调用它。但是我们的错误消息是不同的,我认为在后退模式下需要第二次返回L1。我尝试使用nn.Sequential编写,但您的版本现在可以工作了。谢谢
import torch, torch.nn as nn
class L1Penalty(torch.autograd.Function):
@staticmethod
def forward(ctx, input, l1weight = 0.1):
ctx.save_for_backward(input)
ctx.l1weight = l1weight
return input
@staticmethod
def backward(ctx, grad_output):
input, = ctx.saved_variables
grad_input = input.clone().sign().mul(ctx.l1weight)
grad_input+=grad_output
return grad_input
class Model(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(10,10)
self.fc2 = nn.Linear(10,6)
self.fc3 = nn.Linear(6,10)
self.fc4 = nn.Linear(10,10)
self.relu = nn.ReLU(inplace=True)
self.penalty = L1Penalty()
def forward(self, x):
x = self.fc1(x)
x = self.relu(x)
x = self.fc2(x)
x = self.relu(x)
x = self.penalty.apply(x)
x = self.fc3(x)
x = self.relu(x)
x = self.fc4(x)
x = self.relu(x)
return x
model = Model()
a = torch.rand(50,10)
b = model(a)
print(b.shape)