Pytorch教程

【示例】pytorch模型-顺序模块Sequential

作者 : 老饼 发表日期 : 2024-03-10 05:20:45 更新日期 : 2024-03-24 15:32:24
本站原创文章,转载请说明来自《老饼讲解-深度学习》www.bbbdata.com




顺序模块是深度学习中最常用的模块形式,它按顺序调用每一个模块

而pytorch为顺序模块提供了一种快捷的AIP-Sequential来封装顺序模块

本文讲解pytorch的Sequential顺序模块API的使用以及展示一个日常应用例子




    01. pytorch模型-顺序模块Sequential    




本节讲解pytorch如何使用Sequential函数构建顺序模块




     什么是顺序模块    


顺序模块是指模块的运算就是按顺序连续调用一连串的模块,如下:
class Model(nn.Module):
    def __init__(self):
        super(Model, self).__init__()
        self.L1 = nn.Linear(2,3)             # 定义第一个线性层模块
        self.A1 = nn.ReLU(inplace=True)      # 定义第一个线性层激活函数模块
        self.L2 = nn.Linear(3,2)             # 定义第二个线性层模块
    def forward(self, x):
        # 按顺序连续调用各个模块
        y = self.L1(x)                       # 调用第一个线性层模块
        y = self.A1(y)                       # 调用第一个线性层激活函数模块
        y = self.L2(y)                       # 调用第二个线性层模块
        return y
model = Model()                              # 初始化模型
以上例子就是一个顺序模块,它在forward中只是简单地按顺序调用L1、A1、L2模块
顺序模块是深度学习中最常见的场景,因为深度学习中的模型往往就是层层前馈的结构





      利用Sequential构建顺序模块     


由于顺序模块使用非常频繁,而上述写法比较重复与繁琐,
pytorch提供了Sequential函数,可以把这些连续调用的模块按顺序组装为一个整体的顺序模块,
 具体示例如下
from   torch import nn
from collections import OrderedDict
# 以Sequential的方式定义一个Module并初始化   
model = nn.Sequential(OrderedDict({
    'L1':nn.Linear(2,3),        
    'A1':nn.ReLU(inplace=True),        
    'L2':nn.Linear(3,2)
    }))
# -------打印模型参数-------------------                      
param_dict = model.state_dict()                               # 从模型中提取出模型参数
for key in param_dict:                                        # 历遍所有参数名称
   print(key,':',param_dict[key].data)                        # 打印参数名称和数据
运行结果如下:
  
可以看到,通过Sequential可以快速、简洁地构建一个顺序模块






      利用Sequential构建顺序模块(不带名称)      


在顺序模块的应用中,往往各个子模块的名称并不重要,
因此,Sequential提供了一种更简洁的写法,它默认将以0,1,2.....对子模块进行命名
 具体示例如下:
from   torch import nn
# 以Sequential的方式定义一个Module并初始化   
model = nn.Sequential(
        nn.Linear(2,3),        
        nn.ReLU(inplace=True),        
        nn.Linear(3,2)
    )
# -------打印模型参数-------------------                      
param_dict = model.state_dict()                               # 从模型中提取出模型参数
for key in param_dict:                                        # 历遍所有参数名称
   print(key,':',param_dict[key].data)                        # 打印参数名称和数据
运行结果如下:
 
 
可以看到,在不传入子模块名称时,Sequential以0,1,2.....对子模块进行命名








    02. pytorch模型-Sequential使用实例    




本节展示一个利用Sequential构建一个卷积神经网络的例子,以说明Sequential为模型构建带来的好处




      Sequential使用实例      


下面展示一个pytorch使用Sequential构建模型的实例,它可以使模型的整体结构更加清晰与易理解
具体示例如下:
import torch
from   torch import nn

# 卷积神经网络的结构
class ConvNet(nn.Module):
    def __init__(self,in_channel,num_classes):
        super(ConvNet, self).__init__()
        #------------特征抽取层--------
        self.feature= nn.Sequential(
            # C1层:输出14*14
            nn.Conv2d(in_channel,8, kernel_size=7,stride=1,padding=3),
            nn.ReLU(inplace=True),  
            nn.AvgPool2d(kernel_size=2,stride=2),
            # C2层:输出7*7
            nn.Conv2d(8,16, kernel_size=5,stride=1,padding=2),
            nn.ReLU(inplace=True),
            nn.AvgPool2d(kernel_size=2,stride=2),
            )
        # ----------特征拟合层--------
        self.classifier= nn.Sequential(
            # 第一个全连接层
            nn.Linear(784, 256),  
            nn.ReLU(inplace=True),      
            nn.Dropout(p=0.5),                                      
            # 第二个全连接层                 
            nn.Linear(256, num_classes)                       
            )
    def forward(self, x):
        f = self.feature(x)             # 抽取特征
        f = nn.Flatten()(f)             # 对特征展平
        y = self.classifier(f)          # 拟合特征  
        return y
上述例子构建了一个卷积神经网络,由于卷积神经网络的卷积层的功能是特征抽取,全连接层的功能是特征拟合,
所以代码中利用Sequential把卷积层组装为feature模块,把全连接层组装为classifier模块
这样可以使得模块结构意义更加清晰,在forward里的代码也更简洁,整体代码更加结构化,更具可读性





      老饼语:关于函数与模块    


很多计算pytorch都提供了函数与模块两种Api,
例如ReLu,既有ReLu函数
torch.nn.functional.relu,也有ReLu模块nn.ReLU
 
刚接触pytorch时,老饼非常疑惑,为什么既要有函数又要有模块,
 
直到了解Sequential后才明白,模块主要是提供给Sequential使用的
也就是说,
torch.nn.functional.relu函数一般在forward中使用,
而ReLu模块则在Sequential里使用,因为Sequential是只针对连续模块的











 End 









联系老饼