torch.nn.Module()類有一些重要屬性,我們可用其下面幾個屬性來實現對神經網絡層結構的提取:
torch.nn.Module.children()
torch.nn.Module.modules()
torch.nn.Module.named_children()
torch.nn.Module.named_moduless()
為方面說明,我們首先搭建一個簡單的神經網絡模型,后面所有的內容都是基於這個模型展開的。
1 import torch.nn as nn 2 3 class Net(nn.Module): 4 def __init__(self): 5 super(Net, self).__init__() # input shape (1, 28, 28) 6 self.conv1 = nn.Sequential() 7 self.conv1.add_module('conv1', nn.Conv2d(1, 16, 5, 1, 2)) # output shape (16, 28, 28) 8 self.conv1.add_module('ReLU1', nn.ReLU()) 9 self.conv1.add_module('pool1', nn.MaxPool2d(2)) # output shape (16, 14, 14) 10 11 self.conv2 = nn.Sequential() 12 self.conv2.add_module('conv2', nn.Conv2d(16, 32, 5, 1, 2)) # output shape (32, 14, 14) 13 self.conv2.add_module('ReLU2', nn.ReLU()) 14 self.conv2.add_module('pool2', nn.MaxPool2d(2)) # output shape (32, 7, 7) 15 16 self.linear = nn.Linear(32 * 7 * 7, 10) 17 18 def forward(self, x): 19 x = self.conv1(x) 20 x = self.conv2(x) 21 x = x.view(x.size(0), -1) 22 output = self.linear(x) 23 return output 24 25 net = Net() 26 print(net)
運行結果:
1 Net( 2 (conv1): Sequential( 3 (conv1): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 4 (ReLU1): ReLU() 5 (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 6 ) 7 (conv2): Sequential( 8 (conv2): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 9 (ReLU2): ReLU() 10 (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 11 ) 12 (linear): Linear(in_features=1568, out_features=10, bias=True) 13 )
torch.nn.Modules.children()
children()這個屬性返回下一級模塊的迭代器(可與下一小節中的modules()模塊對照,更容易理解)。
1 i = 1 2 for layer in net.children(): 3 print('{}th layer:'.format(i)) 4 print(layer) 5 i += 1
運行結果:
1 1th layer: 2 Sequential( 3 (conv1): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 4 (ReLU1): ReLU() 5 (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 6 ) 7 2th layer: 8 Sequential( 9 (conv2): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 10 (ReLU2): ReLU() 11 (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 12 ) 13 3th layer: 14 Linear(in_features=1568, out_features=10, bias=True)
torch.nn.Modules.modules()
modules()屬性返回神經網絡每一級的內容。
1 for layer in net.modules(): 2 print(layer) 3 print()
運行結果:
1 Net( 2 (conv1): Sequential( 3 (conv1): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 4 (ReLU1): ReLU() 5 (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 6 ) 7 (conv2): Sequential( 8 (conv2): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 9 (ReLU2): ReLU() 10 (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 11 ) 12 (linear): Linear(in_features=1568, out_features=10, bias=True) 13 ) 14 15 Sequential( 16 (conv1): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 17 (ReLU1): ReLU() 18 (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 19 ) 20 21 Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 22 23 ReLU() 24 25 MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 26 27 Sequential( 28 (conv2): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 29 (ReLU2): ReLU() 30 (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 31 ) 32 33 Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 34 35 ReLU() 36 37 MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 38 39 Linear(in_features=1568, out_features=10, bias=True)
從上面的運行結果可以看出來,modules()模塊以迭代器的形式返回神經網絡逐級的內容。
torch.nn.Modules.named_children()和torch.nn.Modules.named_modules()
named_children()和named_modules()這兩個模塊不僅返回模塊的迭代器,而且還會返回網絡層的名字。
1 for layer in net.named_modules(): 2 print(layer)
運行結果:
1 ('', Net( 2 (conv1): Sequential( 3 (conv1): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 4 (ReLU1): ReLU() 5 (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 6 ) 7 (conv2): Sequential( 8 (conv2): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 9 (ReLU2): ReLU() 10 (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 11 ) 12 (linear): Linear(in_features=1568, out_features=10, bias=True) 13 )) 14 ('conv1', Sequential( 15 (conv1): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 16 (ReLU1): ReLU() 17 (pool1): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 18 )) 19 ('conv1.conv1', Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))) 20 ('conv1.ReLU1', ReLU()) 21 ('conv1.pool1', MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)) 22 ('conv2', Sequential( 23 (conv2): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) 24 (ReLU2): ReLU() 25 (pool2): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) 26 )) 27 ('conv2.conv2', Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))) 28 ('conv2.ReLU2', ReLU()) 29 ('conv2.pool2', MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)) 30 ('linear', Linear(in_features=1568, out_features=10, bias=True))
只提取模型中的卷積層
如果希望只提取卷積層,可以這樣操作:
1 conv_net = nn.Sequential() 2 for layer in net.named_modules(): 3 if isinstance(layer[1], nn.Conv2d): 4 conv_net.add_module(layer[0][:5], layer[1]) # layer[1] is the net layer, layer[0] is its name. 5 print(conv_net)
運行結果:
Sequential( (conv1): Conv2d(1, 16, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) (conv2): Conv2d(16, 32, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2)) )
參數初始化
參數初始化需用到torch.nn.init,下面幾個函數比較常用,截圖摘自PyTorch中文文檔。
在神經網絡中,模型參數就是weights和bias,weights和bias在PyTorch中是Variable,所以我們只需取出weights的data屬性,並填充數值就可以了。比如對卷積層進行參數初始化:
1 for m in net.modules(): 2 if isinstance(m, nn.Conv2d): 3 nn.init.normal(m.weight.data) 4 # nn.init.xavier_normal(m.weight.data) 5 # nn.init.kaiming_normal(m.weight.data) 6 elif isinstance(m, nn.Linear): 7 m.weight.data.normal_() 8 m.bias.data.fill_(0)
參考文獻:
深度學習之PyTorch第四章,廖星宇.