MXNet (6) Parameter and Block Naming (下)
上一篇我們示範了 Name scope 會將 parent 的 prefix 加入 children 的命名之中。
今天來看看 nested block 的命名如何運作。
1. 快速 recall:
建立一個簡單的網路架構,並利用 parent 的 prefix 加入 children 的命名之中。
class SimpleNet(nn.HybridBlock): def __init__(self, **kargs): super(SimpleNet, self).__init__(**kargs) with self.name_scope(): self.body = nn.HybridSequential() self.body.add( nn.Conv2D(20, 3), nn.Conv2D(36, 3), ) def hybrid_forward(self, F, x, *args, **kwargs): return self.body(x)
實例化及初始化:
net = SimpleNet() net.initialize() print(net.collect_params())
children 的 key 包含 parent 類的 simplenet0_。
simplenet0_ ( Parameter simplenet0_conv0_weight (shape=(20, 0, 3, 3), dtype=) Parameter simplenet0_conv0_bias (shape=(20,), dtype= ) Parameter simplenet0_conv1_weight (shape=(36, 0, 3, 3), dtype= ) Parameter simplenet0_conv1_bias (shape=(36,), dtype= ) )
2. Nested block 測試:
我們來測試看看 nested block 的命名規則。
先定義一個 ScopedBlock1,它會把 scopedblock1_ 加入 children 的 key 中:
class ScopedBlock1(nn.HybridBlock): def __init__(self, **kargs): super(ScopedBlock1, self).__init__(**kargs) with self.name_scope(): self.body = nn.HybridSequential() self.body.add( nn.Conv2D(20, 3), nn.Conv2D(36, 3), ) def hybrid_forward(self, F, x, *args, **kwargs): return self.body(x)
再定義一個 ScopedBlock2,它會把 scopedblock2_ 加入 children 的 key 中:
class ScopedBlock2(nn.HybridBlock): def __init__(self, **kargs): super(ScopedBlock2, self).__init__(**kargs) with self.name_scope(): self.body = nn.HybridSequential() for _ in range(4): self.body.add(ScopedBlock1()) def hybrid_forward(self, F, x, *args, **kwargs): return self.body(x)
來看看 ScopedBlock2 的命名:
sb = ScopedBlock2() sb.initialize() print(sb.collect_params())
scopedblock20_ ( Parameter scopedblock20_scopedblock10_conv0_weight (shape=(20, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock10_conv0_bias (shape=(20,), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock10_conv1_weight (shape=(36, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock10_conv1_bias (shape=(36,), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock11_conv0_weight (shape=(20, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock11_conv0_bias (shape=(20,), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock11_conv1_weight (shape=(36, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock11_conv1_bias (shape=(36,), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock12_conv0_weight (shape=(20, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock12_conv0_bias (shape=(20,), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock12_conv1_weight (shape=(36, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock12_conv1_bias (shape=(36,), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock13_conv0_weight (shape=(20, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock13_conv0_bias (shape=(20,), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock13_conv1_weight (shape=(36, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter scopedblock20_scopedblock13_conv1_bias (shape=(36,), dtype=<class 'numpy.float32'>) )
答案其實也滿直觀的,就是命名會依序疊加所以變成類似 scopedblock20_scopedblock10_conv0_weight 這樣的名字。
3. Nested block 但不使用 name_scope:
那 Nested block 但不使用 name_scope 會發變怎樣?
class Block1(nn.HybridBlock): def __init__(self, **kargs): super(Block1, self).__init__(**kargs) self.body = nn.HybridSequential() self.body.add( nn.Conv2D(20, 3), nn.Conv2D(36, 3), ) def hybrid_forward(self, F, x, *args, **kwargs): return self.body(x)
class Block2(nn.HybridBlock): def __init__(self, **kargs): super(Block2, self).__init__(**kargs) self.body = nn.HybridSequential() for _ in range(4): self.body.add(Block1()) def hybrid_forward(self, F, x, *args, **kwargs): return self.body(x)
b = Block2() b.initialize() print(b.collect_params())
block20_ ( Parameter conv0_weight (shape=(20, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter conv0_bias (shape=(20,), dtype=<class 'numpy.float32'>) Parameter conv1_weight (shape=(36, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter conv1_bias (shape=(36,), dtype=<class 'numpy.float32'>) Parameter conv2_weight (shape=(20, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter conv2_bias (shape=(20,), dtype=<class 'numpy.float32'>) Parameter conv3_weight (shape=(36, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter conv3_bias (shape=(36,), dtype=<class 'numpy.float32'>) Parameter conv4_weight (shape=(20, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter conv4_bias (shape=(20,), dtype=<class 'numpy.float32'>) Parameter conv5_weight (shape=(36, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter conv5_bias (shape=(36,), dtype=<class 'numpy.float32'>) Parameter conv6_weight (shape=(20, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter conv6_bias (shape=(20,), dtype=<class 'numpy.float32'>) Parameter conv7_weight (shape=(36, 0, 3, 3), dtype=<class 'numpy.float32'>) Parameter conv7_bias (shape=(36,), dtype=<class 'numpy.float32'>) )
留言
張貼留言