PyTorch模型定义及MNIST演示

Datawhale202210——《深入浅出PyTorch》(5)

Sequential+ModuleList+ModuleDict 代码演示


前言

深度学习模型构建和搭积木一样有趣,要想实现最终的结果,首先需要明白如何定义单个模型,本节将通过MNIST数据集为例演示PyTorch是如何进行模型定义的。


一、PyTorch模型定义

1.知识回顾

1)Module类是torch.nn里提供的应该模型构造类,是用于构造所有神经网网络模块的积累,其他模型的搭建可以通过继承它。
2)它提供三种定义方式,分别是Sequential、ModuleList、ModuleDict。

2.三种定义方式+代码示例

(在进行代码演示前,需要引入需要的库)

import os
import numpy as np
import collections
import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision

1)Sequential(nn.Sequential())
模型在进行前向计算时通过简单串联各个层,Sequential通过更为简单的方式定义模型。接收一个模块的OrderedDict或一系列模块作为参数来注意添加Module的示例,模型的前向计算就是在按序计算这些示例,代码演示如下:

直接排列

import torch.nn as nn
net1=nn.Sequential(
   nn.Linear(784,256),
   nn.ReLU(),    
   nn.Linear(256,10),
      )
   print(net1)
 #结果
 Sequential(
  (0): Linear(in_features=784, out_features=256, bias=True)
  (1): ReLU()
  (2): Linear(in_features=256, out_features=10, bias=True))
  #利用OrderedDict
  import collections
  import torch.nn as nn
  net2=nn.Sequential(collections.OrderedDict([
   ('fcl',nn.Linear(784,256)),('relu1',nn.ReLU()),       ('fc2',nn.Linear(256,10))
   ]))
   print(net2)
  #结果
  Sequential(
  (fcl): Linear(in_features=784, out_features=256, bias=True)
  (relu1): ReLU()
  (fc2): Linear(in_features=256, out_features=10, bias=True)
  )

2)ModuleList(nn.ModuleList())

ModuleList接受一个子模块的列表作为输入,因此可以进行append和extend的操作,同时,子模块或层的权重也会自动添加到网络中。

net3=nn.ModuleList([nn.Linear(784,256),nn.ReLU()])
net3.append(nn.Linear(256,10))
print(net3[-1])
print(net3)
Linear(in_features=256, out_features=10, bias=True)
ModuleList(
 (0): Linear(in_features=784, out_features=256, bias=True)
 (1): ReLU()
 (2): Linear(in_features=256, out_features=10, bias=True)
 )

需要注意的时,ModuleList并不能提供示例,只是简单地把各模块组合在一起,使用它来进行模型实例化需要进行以下操作,否则会报错

(NotImplementedError)
class Net3(nn.Module):
   def __init__(self):
          super().__init__()
                 self.modulelist=nn.ModuleList([nn.Linear(784,256),nn.ReLU()])      self.modulelist.append(nn.Linear(256,10))    
   def forward(self,x):   
           for layer in self.modulelist:    
             x=layer(x)     
            return xnet3_=Net3()
            out3_=net3_(a)
            print(out3_.shape)

3)ModuleDict(nn.ModuleDict())

ModuleDict和ModuleList类似,前者可以更好地为各层添加名称有助于大模型的实现。

net4=nn.ModuleDict({
    
    
'linear':nn.Linear(784,256), 'act':nn.ReLU(),
})
net4['output']=nn.Linear(256,10)print(net4['linear'])
print(net4.output)

二、三种方式比较及使用情况

名称 优势 适用情况
Sequential 简单,且已经明确有哪些层 快速验证
ModuleList、ModuleDict 某层需要重复多次或作为后面层的输入 ResNet等

三、获取参数的方法(补充)

我们发现,在训练的过程中,往往需要了解过程中参数的变化,以便更好地完成训练达成目标。这里介绍三个获取参数的方法:
model.parameters、model.named_parameters、model.submodule.weight

1.model.parameters
model.parameters是一个generator,需要循环打印,其中依次包含了从前至后的计算中涉及的参数,如下分别是hidden_linear中的w,b和output_linear中的w,b的shape

[param.shape for param in seq_model.parameters()]
[torch.Size([13, 1]), torch.Size([13]), torch.Size([1, 13]), torch.Size([1])]

2.model.named_parameters
用1中的函数对于模块较多的情况就很不便利,如果各参数和模块名对应会更加清晰

for name, param in seq_model.named_parameters():
 print(name, param.shape)
 hidden_linear.weight torch.Size([13, 1])
 hidden_linear.bias torch.Size([13])
 output_linear.weight torch.Size([1, 13])
 output_linear.bias torch.Size([1])

3.model.submodule.weight
该函数可直接调用某子模块的参数seq_model.output_linear.bias

Parameter containing:
tensor([0.0821], requires_grad=True)

四、参考文档

1.来自Datawhale的投喂

在线教程链接:https://datawhalechina.github.io/thorough-pytorch/
Github在线教程:https://github.com/datawhalechina/thorough-pytorch
Gitee在线教程:https://gitee.com/datawhalechina/thorough-pytorch
b站视频:https://www.bilibili.com/video/BV1L44y1472Z
(欢迎大家一键三连+关注!)

2.来自广大网友的投喂

Module类源码分析
传送门
MNIST数据集
传送门
获取定义某块的参数https://blog.csdn.net/sinat_33761963/article/details/104332723


总结

1.对于理论的理解要伴随代码演示。
2.最好的效果是理解每个细节,所以有机会就多查多问。
3.向Datawhale的小伙伴特别是组内的Dennis博士和奇奇同学致谢。

猜你喜欢

转载自blog.csdn.net/weixin_50967907/article/details/127447963
今日推荐