nn.Module模块概述


nn.Module类的基本定义

在定义自已的网络的时候,需要继承nn.Module类,并重新实现构造函数__init__()和forward这两个方法。在构造函数__init__()中使用super(Model, self).init()来调用父类的构造函数,forward方法是必须要重写的,它是实现模型的功能,实现各个层之间的连接关系的核心。
1.一般把网络中具有可学习参数的层(如全连接层、卷积层)放在构造函数__init__()中。
2.一般把不具有可学习参数的层(如ReLU、dropout)可放在构造函数中,也可不放在构造函数中(在forward中使用nn.functional来调用)。
示例1:将具有可学习参数层和不具有可学习参数层均放在构造函数中

import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()   # 调用父类的构造函数
        self.con2v = nn.Conv2d(1, 3, 3, 1)
        self.relu = nn.ReLU()
        self.max_pooling = nn.MaxPool2d(2, 1)
    def forward(self, x):
        x = self.con2v(x)
        x = self.relu(x)
        x = self.max_pooling(x)
        return x
model = Model()
print(model)
'''  可看到输出的模型结构
Model(
  (con2v): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
  (relu): ReLU()
  (max_pooling): MaxPool2d(kernel_size=2, stride=1, padding=0, dilation=1, ceil_mode=False)
)
'''

示例2:把不具有可学习参数的层不放在构造函数中(在forward中使用nn.functional调用)

import torch.nn as nn
import torch.nn.functional as F
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()   # 调用父类的构造函数
        self.con2v = nn.Conv2d(1, 3, 3, 1)
        self.max_pooling = nn.MaxPool2d(2, 1)
    def forward(self, x):
        x = self.con2v(x)
        x = F.relu(x)
        x = self.max_pooling(x)
        return x
model = Model()
print(model)
''' 可看到输出的模型结构
Model(
  (con2v): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
  (max_pooling): MaxPool2d(kernel_size=2, stride=1, padding=0, dilation=1, ceil_mode=False)
)
'''

由此可看出不具有可学习参数层没有放在构造函数里面,那么这些层就不会出现在model中。
也就是在构造函数__init__()中只是定义了模型的结构,而在forward方法中实现了模型中的所有层的连接。
3.只要在nn.Module中定义了forward函数,backward函数就会被自动实现(利用Autograd)。而且一般不是显式的调用forward(layer.forward), 而是layer(input), 会自执行forward()。

Sequential类的概述

nn.Sequential的定义:一个有顺序容器,神经网络模块将按照构造函数中传递的顺序添加到该容器中。此外,也可以传入一个有序的模块字典。

Sequenrial类实现了整数索引,每一个层是没有名称的,默认是以0、1、2…这样的index来命名,可以使用model[index]这样的方式获取一个层,并不能够通过名称(如model[“Conv2d”])来获取层。
示例如下:

import torch.nn as nn
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()   # 调用父类的构造函数
        self.model1= nn.Sequential(
            nn.Conv2d(1, 3, 3, 1),
            nn.ReLU(),
            nn.Conv2d(3, 9, 3, 1),
            nn.MaxPool2d(2, 1)
        )
    def forward(self, x):
        x = self.struct(x)
        return x
model = Model()
print(model)
print(model.model1[2])  # 通过索引获取第几个层

'''  输出结果
Model(
  (model1): Sequential(
    (0): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
    (1): ReLU()
    (2): Conv2d(3, 9, kernel_size=(3, 3), stride=(1, 1))
    (3): MaxPool2d(kernel_size=2, stride=1, padding=0, dilation=1, ceil_mode=False)
  )
)
Conv2d(3, 9, kernel_size=(3, 3), stride=(1, 1))
'''

Sequential的三种包装方式

示例如下:

import torch.nn as nn
from collections import OrderedDict
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()   # 调用父类的构造函数
        self.model1 = nn.Sequential(    # 方式一
            nn.Conv2d(1, 3, 3, 1),
            nn.ReLU()
        )
        self.model2 = nn.Sequential(   # 方式二
            OrderedDict([
                ('conv1', nn.Conv2d(1, 3, 3, 1)),
                ('relu1', nn.ReLU())
            ])
        )
        self.model3 = nn.Sequential()  # 方式三
        self.model3.add_module('conv1', nn.Conv2d(1, 3, 3, 1)),
        self.model3.add_module('relu1', nn.ReLU())
    def forward(self, x):
        x = self.model1(x)
        x = self.model2(x)
        x = self.model3(x)
        return x
model = Model()
print(model)

'''  输出结果
Model(
  (model1): Sequential(
    (0): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
    (1): ReLU()
  )
  (model2): Sequential(
    (conv1): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
    (relu1): ReLU()
  )
  (model3): Sequential(
    (conv1): Conv2d(1, 3, kernel_size=(3, 3), stride=(1, 1))
    (relu1): ReLU()
  )
)
'''

reference:

https://blog.csdn.net/qq_27825451/article/details/90550890

  • 1
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值