1、nn.Sequential类-使用Sequential类来自定义顺序连接模型
前言:torch.nn.Sequential是一个Sequential容器,模块将按照构造函数中传递的顺序添加到模块中。通俗的话说,就是根据自己的需求,把不同的函数组合成一个(小的)模块使用或者把组合的模块添加到自己的网络中。主要有三种使用方法(见二)。也就是说我们可以使用torch.nn.Sequential类来实现简单的顺序连接模型。这个模式也是继承自Module类的。
作用:Sequential除了本身可以用来定义模型之外,它还可以包装层,把几个层包装起来像一个块一样。
一、关于Sequential类的简介
注意:torch的核心是Module类,Module类在下面这个模块中:E:\Anaconda3\envs\EncDec\Lib\site-packages\torch\nn\modules\module.py
Sequential继承自Module,在下面这个模块中:E:\Anaconda3\envs\EncDec\Lib\site-packages\torch\nn\modules\container.py
这样看来,Sequential似乎是一个容器,的确,它是可以作为一个容器包装各层。这里先简单的看一下它的定义:
1 class Sequential(Module): # 继承Module 2 def __init__(self, *args): # 重写了构造函数 3 def _get_item_by_idx(self, iterator, idx): 4 def __getitem__(self, idx): 5 def __setitem__(self, idx, module): 6 def __delitem__(self, idx): 7 def __len__(self): 8 def __dir__(self): 9 def forward(self, input): # 重写关键方法forward
再看一下container.py里面还有那些“容器”存在:
1 class Container(Module): 2 class Sequential(Module): 3 class ModuleList(Module): 4 class ModuleDict(Module): 5 class ParameterList(Module): 6 class ParameterDict(Module):
二、Sequential类的三种实现
2.1、最简单的序贯模型
1 import torch.nn as nn 2 model = nn.Sequential( 3 nn.Conv2d(1,20,5), 4 nn.ReLU(), 5 nn.Conv2d(20,64,5), 6 nn.ReLU() 7 ) 8 9 print(model) 10 print(model[2]) # 通过索引获取第几个层 11 '''运行结果为: 12 Sequential( 13 (0): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1)) 14 (1): ReLU() 15 (2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) 16 (3): ReLU() 17 ) 18 Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) 19 '''
注意:这种实现方法有一个问题,那就是每一层是没有名称的,默认的是以0、1、2、3来命名。
2.2、给每一层添加名称
1 import torch.nn as nn 2 from collections import OrderedDict 3 4 model = nn.Sequential(OrderedDict([ 5 ('conv1', nn.Conv2d(1, 20, 5)), 6 ('relu1', nn.ReLU()), 7 ('conv2', nn.Conv2d(20, 64, 5)), 8 ('relu2', nn.ReLU()) 9 ])) 10 11 print(model) 12 print(model[2]) # 通过索引获取第几个层 13 print(model.conv1) 14 '''运行结果为: 15 Sequential( 16 (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1)) 17 (relu1): ReLU() 18 (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) 19 (relu2): ReLU() 20 ) 21 Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) 22 Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1)) 23 '''
注意:从上面的结果中可以看出,这个时候每一个层都有了自己的名称,但是此时需要注意,并不能通过名称直接获取层,
依然只能通过索引index,即model[2],不能通过model["conv2"]来获取。这其实是由它的定义实现的,看上面的Sequential
定义可知,支持inddex访问。但可以通过model.covn2获取。
2.3、Sequential的第三种实现
1 import torch.nn as nn 2 from collections import OrderedDict 3 4 model = nn.Sequential() 5 model.add_module("conv1", nn.Conv2d(1, 20, 5)) 6 model.add_module('relu1', nn.ReLU()) 7 model.add_module('conv2', nn.Conv2d(20, 64, 5)) 8 model.add_module('relu2', nn.ReLU()) 9 10 print(model) 11 print(model[2]) # 通过索引获取第几个层 12 print(model.conv1) 13 """运行结果为: 14 Sequential( 15 (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1)) 16 (relu1): ReLU() 17 (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) 18 (relu2): ReLU() 19 ) 20 Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1)) 21 Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1)) 22 """
注意:Sequential里面并没有定义add_module()方法,实际上,这个方法是定义在它的父类Module里面的,Sequential继承了而已,它的定义如下:
def add_module(self, name, module):
参考:
1、pytorch教程之nn.Sequential类详解——使用Sequential类来自定义顺序连接模型
原文:https://blog.csdn.net/qq_27825451/article/details/90551513

浙公网安备 33010602011771号