• 【深度学习】torch.nn.Sequential方法介绍


    torch.nn.Sequential是一个Sequential容器,模块将按照构造函数中传递的顺序添加到模块中。

    另外,也可以传入一个有序模块。

    作用:Sequential除了本身可以用来定义模型之外,它还可以包装层,把几个层包装起来像一个块一样。

    具体理解如下:

    一、普通构建网络

    import torch
    import torch.nn as nn
    
    class Net(nn.Module):
        def __init__(self, n_feature, n_hidden, n_output):
            super(Net, self).__init__()
            self.hidden = nn.Linear(n_feature, n_hidden)
            self.predict = nn.Linear(n_hidden, n_output)
    
        def forward(self, x):
            x = F.relu(self.hidden(x))      # 隐藏层后接relu层
            x = self.predict(x)
            return x
    
    model_1 = Net(1, 10, 1)
    print(model_1)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    输出为:

    Net (
    (hidden): Linear(in features=l, out features=10, bias=True)predict): Linear(in features=10, out features=l, bias=True)
    )
    
    • 1
    • 2
    • 3

    二、使用Sequential快速搭建网络

    import torch
    import torch.nn as nn
    
    class Net(nn.Module):
        def __init__(self, n_feature, n_hidden, n_output):
            super(Net,self).__init__()
            self.net_1 = nn.Sequential(
                nn.Linear(n_feature, n_hidden),
                nn.ReLU(),
                nn.Linear(n_hidden, n_output)
            )
        
        def forward(self,x):
            x = self.net_1(x)
            return x
    
    model_2 = Net(1,10,1)
    print(model_2)
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    输出为:

    Net (
    (net 1): Sequential((0): Linear(in features=l, out features=10, bias=True)(1): ReLU0(2): Linear(in features=10, out features=1, bias=True)
    )
    )
    
    • 1
    • 2
    • 3
    • 4

    三、关于Sequential类的简介

    Sequential似乎是一个容器,的确,它是可以作为一个容器包装各层。这里先简单的看一下它的定义:

    class Sequential(Module): # 继承Module
        def __init__(self, *args):  # 重写了构造函数
        def _get_item_by_idx(self, iterator, idx):
        def __getitem__(self, idx):
        def __setitem__(self, idx, module):
        def __delitem__(self, idx):
        def __len__(self):
        def __dir__(self):
        def forward(self, input):  # 重写关键方法forward
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    再看一下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):
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    四、Sequential类的三种实现

    4.1 最简单的序贯模型

    import torch.nn as nn
    model = nn.Sequential(
                      nn.Conv2d(1,20,5),
                      nn.ReLU(),
                      nn.Conv2d(20,64,5),
                      nn.ReLU()
                    )
    
    print(model)
    print(model[2]) # 通过索引获取第几个层
    '''运行结果为:
    Sequential(
      (0): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
      (1): ReLU()
      (2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
      (3): ReLU()
    )
    Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    注意:这种实现方法有一个问题,那就是每一层是没有名称的,默认的是以0、1、2、3来命名。

    4.2 给每一层添加名称

    import torch.nn as nn
    from collections import OrderedDict
    
    model = nn.Sequential(OrderedDict([
        ('conv1', nn.Conv2d(1, 20, 5)),
        ('relu1', nn.ReLU()),
        ('conv2', nn.Conv2d(20, 64, 5)),
        ('relu2', nn.ReLU())
    ]))
    
    print(model)
    print(model[2])  # 通过索引获取第几个层
    print(model.conv1)
    '''运行结果为:
    Sequential(
      (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
      (relu1): ReLU()
      (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
      (relu2): ReLU()
    )
    Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
    Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
    '''
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    注意:从上面的结果中可以看出,这个时候每一个层都有了自己的名称,但是此时需要注意,并不能通过名称直接获取层,依然只能通过索引index,即model[2],不能通过model[“conv2”]来获取。这其实是由它的定义实现的,看上面的Sequential定义可知,支持inddex访问。但可以通过model.covn2获取。

    4.3 Sequential的第三种实现

    import torch.nn as nn
    from collections import OrderedDict
    
    model = nn.Sequential()
    model.add_module("conv1", nn.Conv2d(1, 20, 5))
    model.add_module('relu1', nn.ReLU())
    model.add_module('conv2', nn.Conv2d(20, 64, 5))
    model.add_module('relu2', nn.ReLU())
    
    print(model)
    print(model[2])  # 通过索引获取第几个层
    print(model.conv1)
    """运行结果为:
    Sequential(
      (conv1): Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
      (relu1): ReLU()
      (conv2): Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
      (relu2): ReLU()
    )
    Conv2d(20, 64, kernel_size=(5, 5), stride=(1, 1))
    Conv2d(1, 20, kernel_size=(5, 5), stride=(1, 1))
    """
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    注意:Sequential里面并没有定义add_module()方法,实际上,这个方法是定义在它的父类Module里面的,Sequential继承了而已,它的定义如下:

    def add_module(self, name, module):
    
    • 1
  • 相关阅读:
    直播课堂系统03-model类及实体
    软考高级系统架构设计师系列论文二十八:论需求分析方法及应用
    Java入门有多快,看这篇
    [Prob] (Coupon collector)
    CMS getshell
    【JavaScript】制作一个抽奖转盘页面
    数据类型
    从月薪10k到30k的必走之路:自动化测试
    HazelEngine 学习记录 - 2D Renderer Transforms and 2D Renderer Textures
    elementUI可拖拉宽度抽屉
  • 原文地址:https://blog.csdn.net/wzk4869/article/details/127972860