Incubator-mxnet: Some questions about gluon

Created on 30 Dec 2017  路  2Comments  路  Source: apache/incubator-mxnet

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

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:

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")

All 2 comments

@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.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

luoruisichuan picture luoruisichuan  路  3Comments

Ajoo picture Ajoo  路  3Comments

dushoufu picture dushoufu  路  3Comments

Zhaoyang-XU picture Zhaoyang-XU  路  3Comments

phunterlau picture phunterlau  路  3Comments