『PyTorch』第九彈_前饋網絡簡化寫法


『PyTorch』第四彈_通過LeNet初識pytorch神經網絡_上

『PyTorch』第四彈_通過LeNet初識pytorch神經網絡_下

在前面的例子中,基本上都是將每一層的輸出直接作為下一層的輸入,這種網絡稱為前饋傳播網絡(feedforward neural network)。對於此類網絡如果每次都寫復雜的forward函數會有些麻煩,在此就有兩種簡化方式,ModuleList和Sequential。其中Sequential是一個特殊的module,它包含幾個子Module,前向傳播時會將輸入一層接一層的傳遞下去。ModuleList也是一個特殊的module,可以包含幾個子module,可以像用list一樣使用它,但不能直接把輸入傳給ModuleList。下面舉例說明。

 

一、nn.Sequential()對象

nn.Sequential()對象是類似keras的前饋模型的對象,可以為之添加層實現前饋神經網絡。

1、模型建立方式

第一種寫法:

nn.Sequential()對象.add_module(層名,層class的實例)

net1 = nn.Sequential()
net1.add_module('conv', nn.Conv2d(3, 3, 3))
net1.add_module('batchnorm', nn.BatchNorm2d(3))
net1.add_module('activation_layer', nn.ReLU())

 第二種寫法:

nn.Sequential(*多個層class的實例)

net2 = nn.Sequential(
        nn.Conv2d(3, 3, 3),
        nn.BatchNorm2d(3),
        nn.ReLU()
        )

第三種寫法:

nn.Sequential(OrderedDict([*多個(層名,層class的實例)]))

from collections import OrderedDict
net3= nn.Sequential(OrderedDict([
          ('conv', nn.Conv2d(3, 3, 3)),
          ('batchnorm', nn.BatchNorm2d(3)),
          ('activation_layer', nn.ReLU())
        ]))

 

2、檢查以及調用模型

查看模型

print對象即可

print('net1:', net1)
print('net2:', net2)
print('net3:', net3)
net1: Sequential(
  (conv): Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1))
  (batchnorm): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True)
  (activation_layer): ReLU()
)
net2: Sequential(
  (0): Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1))
  (1): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True)
  (2): ReLU()
)
net3: Sequential(
  (conv): Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1))
  (batchnorm): BatchNorm2d(3, eps=1e-05, momentum=0.1, affine=True)
  (activation_layer): ReLU()
)

提取子Module對象

# 可根據名字或序號取出子module
net1.conv, net2[0], net3.conv
(Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1)),
 Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1)),
 Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1)))

調用模型

可以直接網絡對象(輸入數據),也可以使用上面的Module子對象分別傳入(input)。

input = V(t.rand(1, 3, 4, 4))
output = net1(input)
output = net2(input)
output = net3(input)
output = net3.activation_layer(net1.batchnorm(net1.conv(input)))

 

二、nn.ModuleList()對象

ModuleListModule的子類,當在Module中使用它的時候,就能自動識別為子module。

建立以及使用方法如下,

modellist = nn.ModuleList([nn.Linear(3,4), nn.ReLU(), nn.Linear(4,2)])
input = V(t.randn(1, 3))
for model in modellist:
    input = model(input)
# 下面會報錯,因為modellist沒有實現forward方法
# output = modelist(input)

 

和普通list不一樣,它和torch的其他機制結合緊密,繼承了nn.Module的網絡模型class可以使用nn.ModuleList並識別其中的parameters,當然這只是個list,不會自動實現forward方法,

class MyModule(nn.Module):
    def __init__(self):
        super(MyModule, self).__init__()
        self.list = [nn.Linear(3, 4), nn.ReLU()]
        self.module_list = nn.ModuleList([nn.Conv2d(3, 3, 3), nn.ReLU()])
    def forward(self):
        pass
model = MyModule()
print(model)
MyModule(
  (module_list): ModuleList(
    (0): Conv2d (3, 3, kernel_size=(3, 3), stride=(1, 1))
    (1): ReLU()
  )
)
for name, param in model.named_parameters():
    print(name, param.size())
('module_list.0.weight', torch.Size([3, 3, 3, 3]))
('module_list.0.bias', torch.Size([3]))

可見,list中的子module並不能被主module所識別,而ModuleList中的子module能夠被主module所識別。這意味着如果用list保存子module,將無法調整其參數,因其未加入到主module的參數中。

除ModuleList之外還有ParameterList,其是一個可以包含多個parameter的類list對象。在實際應用中,使用方式與ModuleList類似。如果在構造函數__init__中用到list、tuple、dict等對象時,一定要思考是否應該用ModuleList或ParameterList代替。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM