创建一个只是标识的 nnModule
Create a nnModule that's just the identity
我正在尝试调试不同 nnModules 之间相当复杂的交互。能够仅用身份网络替换其中一个以进行调试对我来说非常有帮助。例如:
net_a = NetworkA()
net_b = NetworkB()
net_c = NetworkC()
input = Autograd.Variable(torch.rand(10,2))
out = net_a(input)
out = net_b(out)
out = net_c(out)
我希望能够将第二行更改为 net_b = IdentityNet()
,而不必通过并重新连接我所有的 As 到 Cs。但是,当我创建一个完全空的 nnModule 时,优化器会抛出 ValueError: optimizer got an empty parameter list
.
有什么解决方法吗?
一个最小的非工作示例:
import torch.optim as optim
class IdentityModule(nnModule):
def forward(self, inputs):
return inputs
identity = IdentityModule()
opt = optim.Adam(identity, lr=0.001)
out = identity(any_tensor)
error = torch.mean(out)
error.backward()
opt.step()
您在这里遇到的问题是合乎逻辑的。看看你这样做意味着什么:
error.backward()
opt.step()
.backward()
将递归计算从输出到传入网络的任何输入的梯度。就计算图而言,有两种值得注意的输入:您传入的输入,以及模拟网络行为的 nn.Parameter
s。然后当您执行 opt.step()
时,PyTorch 将查找它可以更新以更改网络输出的任何输入,即 nn.Parameters()
.
但是,您的伪代码 没有一个 nn.Parameter
!,因为身份模块不包含一个。所以当你调用这些函数时,opt.step()
没有目标,解释错误信息。
这不会扩展到您之前描述的情况。如果您将一个没有参数的模块链接到一个更大的链中,其中一些模块确实有参数,那么计算图中就会有参数要训练。
不过,您需要确保优化器确实获得了初始化时传递的所有这些参数。一个简单的技巧是打印这些:
net_a = SomeNetwork()
net_b = IdentityNetwork() # has no parameters
net_c = SomeNetwork()
print(list(net_a.parameters())) # will contain whatever parameters in net_a
print(list(net_b.parameters())) # will be []
print(list(net_c.parameters())) # will contain whatever parameters in net_c
# to train all of them, you can do one of two things:
# 1. create new module. This works, since `.parameters()` collects params recursively from all submodules.
class NewNet(nn.Module):
def __init__(self):
nn.Module.__init__(self)
self.net_a = net_a
self.net_b = identity
self.net_c = net_c
def forward(self, input):
return self.net_c(self.net_b(self.net_a(input)))
all_parameters = list(NewNet().parameters())
print(all_parameters) # will contain a list of all parameters of net_a and net_c
# 2. simply merge the lists
all_parameters = list(net_a.parameters()) + list(net_b.parameters()) + list(net_c.parameters())
print(all_parameters) # will contain a list of all parameters of net_a and net_c
opt = optim.SGD(all_parameters)
你也可以just do:
net_b = torch.nn.Sequential()
编辑:在 PyTorch 1.7 中,[nn.Identity](https://pytorch.org/docs/stable/generated/torch.nn.Identity.html#torch.nn.Identity)
出现了。医生在[这里]。
最新版本的 pytorch 有一个身份模块 nn.Identity
。
net_b = nn.Identity()
我正在尝试调试不同 nnModules 之间相当复杂的交互。能够仅用身份网络替换其中一个以进行调试对我来说非常有帮助。例如:
net_a = NetworkA()
net_b = NetworkB()
net_c = NetworkC()
input = Autograd.Variable(torch.rand(10,2))
out = net_a(input)
out = net_b(out)
out = net_c(out)
我希望能够将第二行更改为 net_b = IdentityNet()
,而不必通过并重新连接我所有的 As 到 Cs。但是,当我创建一个完全空的 nnModule 时,优化器会抛出 ValueError: optimizer got an empty parameter list
.
有什么解决方法吗?
一个最小的非工作示例:
import torch.optim as optim
class IdentityModule(nnModule):
def forward(self, inputs):
return inputs
identity = IdentityModule()
opt = optim.Adam(identity, lr=0.001)
out = identity(any_tensor)
error = torch.mean(out)
error.backward()
opt.step()
您在这里遇到的问题是合乎逻辑的。看看你这样做意味着什么:
error.backward()
opt.step()
.backward()
将递归计算从输出到传入网络的任何输入的梯度。就计算图而言,有两种值得注意的输入:您传入的输入,以及模拟网络行为的 nn.Parameter
s。然后当您执行 opt.step()
时,PyTorch 将查找它可以更新以更改网络输出的任何输入,即 nn.Parameters()
.
但是,您的伪代码 没有一个 nn.Parameter
!,因为身份模块不包含一个。所以当你调用这些函数时,opt.step()
没有目标,解释错误信息。
这不会扩展到您之前描述的情况。如果您将一个没有参数的模块链接到一个更大的链中,其中一些模块确实有参数,那么计算图中就会有参数要训练。
不过,您需要确保优化器确实获得了初始化时传递的所有这些参数。一个简单的技巧是打印这些:
net_a = SomeNetwork()
net_b = IdentityNetwork() # has no parameters
net_c = SomeNetwork()
print(list(net_a.parameters())) # will contain whatever parameters in net_a
print(list(net_b.parameters())) # will be []
print(list(net_c.parameters())) # will contain whatever parameters in net_c
# to train all of them, you can do one of two things:
# 1. create new module. This works, since `.parameters()` collects params recursively from all submodules.
class NewNet(nn.Module):
def __init__(self):
nn.Module.__init__(self)
self.net_a = net_a
self.net_b = identity
self.net_c = net_c
def forward(self, input):
return self.net_c(self.net_b(self.net_a(input)))
all_parameters = list(NewNet().parameters())
print(all_parameters) # will contain a list of all parameters of net_a and net_c
# 2. simply merge the lists
all_parameters = list(net_a.parameters()) + list(net_b.parameters()) + list(net_c.parameters())
print(all_parameters) # will contain a list of all parameters of net_a and net_c
opt = optim.SGD(all_parameters)
你也可以just do:
net_b = torch.nn.Sequential()
编辑:在 PyTorch 1.7 中,[nn.Identity](https://pytorch.org/docs/stable/generated/torch.nn.Identity.html#torch.nn.Identity)
出现了。医生在[这里]。
最新版本的 pytorch 有一个身份模块 nn.Identity
。
net_b = nn.Identity()