I want to do this by using list self.conv.append(nn.Conv2D()), but it does work.
Can someone give me a suggestion for this case? I have on idea for it.
The network is created with skip connections.
class Layer(nn.HybridBlock):
def __init__(self, depth=15, channels=3, **kwargs):
super(Layer, self).__init__(**kwargs)
self.depth = depth
self.conv01 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv02 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv03 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv04 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv05 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv06 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv07 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv08 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv09 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv10 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv11 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv12 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv13 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv14 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.conv15 = nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv01 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv02 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv03 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv04 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv05 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv06 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv07 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv08 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv09 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv10 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv11 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv12 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv13 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv14 = nn.Conv2DTranspose(128, kernel_size=3, strides=1, padding=1, use_bias=True)
self.deconv15 = nn.Conv2DTranspose(channels, kernel_size=3, strides=1, padding=1, use_bias=True)
def hybrid_forward(self, F, x):
encode01 = F.relu(self.conv01(x))
encode02 = F.relu(self.conv02(encode01))
encode03 = F.relu(self.conv03(encode02))
encode04 = F.relu(self.conv04(encode03))
encode05 = F.relu(self.conv05(encode04))
encode06 = F.relu(self.conv06(encode05))
encode07 = F.relu(self.conv07(encode06))
encode08 = F.relu(self.conv08(encode07))
encode09 = F.relu(self.conv09(encode08))
encode10 = F.relu(self.conv10(encode09))
encode11 = F.relu(self.conv11(encode10))
encode12 = F.relu(self.conv12(encode11))
encode13 = F.relu(self.conv13(encode12))
encode14 = F.relu(self.conv14(encode13))
encode15 = F.relu(self.conv15(encode14))
decode00 = encode15
decode01 = F.relu(self.deconv01(decode00))
decode01 = F.relu(encode14+decode01)
decode02 = F.relu(self.deconv02(decode01))
decode03 = F.relu(self.deconv03(decode02))
decode03 = F.relu(encode12+decode03)
decode04 = F.relu(self.deconv04(decode03))
decode05 = F.relu(self.deconv05(decode04))
decode05 = F.relu(encode10+decode05)
decode06 = F.relu(self.deconv06(decode05))
decode07 = F.relu(self.deconv07(decode06))
decode07 = F.relu(encode08+decode07)
decode08 = F.relu(self.deconv08(decode07))
decode09 = F.relu(self.deconv09(decode08))
decode09 = F.relu(encode06+decode09)
decode10 = F.relu(self.deconv10(decode09))
decode11 = F.relu(self.deconv11(decode10))
decode11 = F.relu(encode04+decode11)
decode12 = F.relu(self.deconv12(decode11))
decode13 = F.relu(self.deconv13(decode12))
decode13 = F.relu(encode02+decode13)
decode14 = F.relu(self.deconv14(decode13))
decode15 = self.deconv15(decode14)
return decode15
@kice We cannot use list to store Blocks because they will not be registered correctly. You may refer to this PR for more information https://github.com/apache/incubator-mxnet/pull/9148.
One solution to this problem is to use Sequential or HybridSequential as a container of the Conv Layers. For example:
class Layer(nn.HybridBlock):
def __init__(self, depth=15, channels=3, **kwargs):
super(Layer, self).__init__(**kwargs)
self.conv_layers = nn.HybridSequential()
with self.conv_layers.name_scope():
for i in range(depth):
self.conv_layers.add(nn.Conv2D(128, kernel_size=3, strides=1, padding=1, use_bias=True))
def hybrid_forward(self, F, x):
# You can use the layers as self.conv_layers[i]
@szha @piiswrong In PyTorch, there is an additional ModuleList object (http://pytorch.org/docs/master/nn.html#torch.nn.ModuleList) for this behavoir. Do you think we need to add this? (Sequential and HybridSequential already have the functionality of "BlockList")
It might have been nice if we adopted the list interface with append and extend. Given that the only missing functionality is the equivalent of list.extend, I think the added value of adding BlockList is only marginal.
Most helpful comment
@kice We cannot use list to store Blocks because they will not be registered correctly. You may refer to this PR for more information https://github.com/apache/incubator-mxnet/pull/9148.
One solution to this problem is to use Sequential or HybridSequential as a container of the Conv Layers. For example:
@szha @piiswrong In PyTorch, there is an additional ModuleList object (http://pytorch.org/docs/master/nn.html#torch.nn.ModuleList) for this behavoir. Do you think we need to add this? (Sequential and HybridSequential already have the functionality of "BlockList")