Pytorchでのnn.ModuleListとnn.Sequentialの使用法と違い



Usage Difference Nn



https://zhuanlan.zhihu.com/p/64990232

最近、マルチタスクネットワークを定義するときに、nn.ModuleListとnn.Sequentialの使用法を疑っていました。 2つの使用法と違いを調べてみましょう。



1.nn.ModuleListの役割
まず、nn.ModuleListの役割を調べて、完全な接続のみを含む単純なネットワークを定義しましょう。 ModuleListを使用せず、リストのみを使用してネットワーク内のレイヤーを定義する場合:

import torch import torch.nn as nn class testNet(nn.Module): def __init__(self): super(testNet, self).__init__() self.combine = [] self.combine.append(nn.Linear(100,50)) self.combine.append(nn.Linear(50,25)) net = testNet() print(net)

結果には、追加された完全に接続されたレイヤーの情報が表示されていないことがわかります。 ModuleListを使用するように変更した場合:



import torch import torch.nn as nn class testNet(nn.Module): def __init__(self): super(testNet, self).__init__() self.combine = nn.ModuleList() self.combine.append(nn.Linear(100,50)) self.combine.append(nn.Linear(50,25)) net = testNet() print(net)

pytorchは、定義時にnn.ModuleListのパラメーターを自動的に認識できますが、通常のリストでは認識できないことがわかります。 Sequentialを使用すると、ModuleListと同じ効果を得ることができます。

nn.ModuleListとnn.Sequentialの違い
上で定義したネットワークに入力を与える場合は、出力を確認してください。

import torch import torch.nn as nn class testNet(nn.Module): def __init__(self): super(testNet, self).__init__() self.combine = nn.ModuleList() self.combine.append(nn.Linear(100,50)) self.combine.append(nn.Linear(50,25)) testnet = testNet() input_x = torch.ones(100) output_x = testnet(input_x) print(output_x)

エラーNotImplementedErrorを報告します:



これは、forward()メソッドが実装されていないためです。 forward()メソッドが次のように完了した場合:

import torch import torch.nn as nn class testNet(nn.Module): def __init__(self): super(testNet, self).__init__() self.combine = nn.ModuleList() self.combine.append(nn.Linear(100,50)) self.combine.append(nn.Linear(50,25)) #Complete forward() def forward(self, x): x = self.combine(x) return x testnet = testNet() input_x = torch.ones(100) output_x = testnet(input_x) print(output_x)

NotImplementedErrorが引き続き報告されることがわかりました。これは、nn.ModuleListが順序付けられていないシーケンスであるためです。彼はforward()メソッドを実装していません。 x = self.combine(x)を直接呼び出してforward()を実装することはできません。 ModuleListメソッドを実装する場合は、forward()を次のように定義する必要があります。

import torch import torch.nn as nn class testNet(nn.Module): def __init__(self): super(testNet, self).__init__() self.combine = nn.ModuleList() self.combine.append(nn.Linear(100,50)) self.combine.append(nn.Linear(50,25)) #Redefine forward() method def forward(self, x): x = self.combine[0](x) x = self.combine[1](x) return x testnet = testNet() input_x = torch.ones(100) output_x = testnet(input_x) print(output_x)

正しい結果が得られました。 nn.Sequential定義に置き換えられた場合:

import torch import torch.nn as nn class testNet(nn.Module): def __init__(self): super(testNet, self).__init__() self.combine = nn.Sequential( nn.Linear(100,50), nn.Linear(50,25), ) def forward(self, x): x = self.combine(x) return x testnet = testNet() input_x = torch.ones(100) output_x = testnet(input_x) print(output_x)

nn.Sequentialで定義されたネットワーク内の各レイヤーは、定義された順序に従ってカスケードされるため、各レイヤーの入力と出力が接続されていることを確認する必要があります。また、nn.Sequentialはfarward()メソッドを実装しているため、x = self.combine(x)と同様の方法でforwardを直接実装できます。

nn.ModuleListには順序要件がなく、forward()メソッドを実装していません。

これが2つの違いです。

元のリンク:https://blog.csdn.net/watermelon1123/article/details/89954224