2017-12-05 3 views
0

異なるnnModule間のかなり複雑な相互作用をデバッグしようとしています。デバッグの目的で、そのうちの1つをアイデンティティネットワークに置き換えることができれば非常に役に立ちます。たとえば:IDだけのnnModuleを作成する

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) 

私の代わりにすべての私としてCsに通過し、再接続するので、ちょうどnet_b = IdentityNet()に2つ目の行を変更できるようにしたいと思います。しかし、完全に空の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() 
+0

空のnnModuleとはどういう意味ですか?あなたの 'IdentifyNet()'はどのように見えますか?それは単に入力を返しますか?投稿をより明確にする必要があります。 – jdhao

+0

はい、私はIdentityNetに入力を返すだけです。私は、 'forward'メソッドが入力を返すようにすることができると考えましたが、オプティマイザは、最適化するパラメータがないというエラーを送出します。私はIdentityNetクラスの作成に関するアドバイスを探しています。 –

+0

あなたはエラーを再現するための人々のための最小の実例を与えるべきです。 – jdhao

答えて

1

問題は論理1です。あなたが行うとき、それが何を意味するのかを見てください:

error.backward() 
opt.step() 

.backward()は再帰的に使用すると、ネットワークに渡す任意の入力にあなたの出力から勾配を計算します。計算グラフの点では、入力の2つの注目すべき種類があります:あなたが渡す入力と、ネットワークの動作をモデル化するnn.Parameteropt.step()を実行すると、PyTorchはネットワークの出力を変更するために更新できる入力を探します。つまり、nn.Parameters()です。

ただし、擬似コードにはnn.Parameterが1つありません。 IDモジュールにはID番号が含まれていないため、です。したがって、これらの関数を呼び出すと、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) 
+0

よろしくお願いいたします。私はすべてのパラメータが毎回更新されることを望まないGANのようなことをしていますが、それを回避するためにはrequires_grad = Falseで何かできます。 1つのネットワークにそれらを組み合わせることをお勧めします。 –

+0

@SamBobel、中間変数に 'detach()'を使わないのはなぜですか? – jdhao

+0

私はそれを見て、その提案に感謝します。私は前に 'デタッチ 'を見ていなかった –

関連する問題