基于PyTorch的深度学习系列教程(三):使用torch.nn.Module建立模型

1. Module类概述

在PyTorch中,无论是自定义的模块与损失函数,还是完整模型,都是通过继承torch.nn.Module类来构建的。因此,要想建立较复杂的网络,我们必须使用此类。

2. 使用Module类建立模型

在实际使用中,要建立一个模型,我们需要继承torch.nn.Module类,并更新__init__forward这两个方法。其中,forward方法定义了模型前向传播的完整过程。

通常,为了代码的简洁性,我们将需要更新参数的操作(例如卷积层、全连接层等)定义在__init__方法内。对于不需要更新参数的操作(例如池化层、激活函数等),我们直接在foward中定义。

以下为一个简单的例子:

import torch
import torchvision
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms as T

class SimpleNet(nn.Module):
    def __init__(self,in_ch): #in_ch: 输入张量的通道数
        super(SimpleNet, self).__init__() #必须写,调用父类的构建函数
        self.conv1 = nn.Conv2d(in_ch, in_ch, kernel_size=5)  #定义卷积层1
        self.conv2 = nn.Conv2d(in_ch, in_ch, kernel_size=7) #定义卷积层2
        self.linear1 = nn.Linear(13924,2) #定义全连接层1

    def forward(self,x):
        x = self.conv1(x)
        x = self.conv2(x)
        x = x.view(x.size(0), -1) #改变维度
        x = self.linear1(x)
        x = F.sigmoid(x) #进行Sigmoid变换,无参数
        return x
代码分析

在上面的代码中,我们构建了一个名为SimpleNet的类作为模型,并继承了nn.Module类。在类内,我们重构了__init__forward方法。我们在__init__方法内调用了父类的构建函数,并随后定义了模型的两个卷积层和一个全连接层。在forward方法内,我们实现了模型的前向传播,并对结果进行了Sigmoid操作,最后返回了结果。

3. 使用nn.Sequential包装层

在实际应用中,我们常常将多个不同的层打包为一个更大的模块(例如ResNet中的ResBlock),从而方便调用。为了实现这一点,我们可以使用nn.Sequential

nn.Sequential是一个Module的序列容器。我们可以把一个模块的组成部分按顺序传入,也可以传入一个存有组成部分的OrderedDict,从而形成一个新的Module,作为我们想构建的模块。可以看到,在PyTorch中,Module的组合搭配比较灵活自由,既可以作为单个层,也可以作为模块和完整模型使用。

以下为一个使用的小例子:

import torch
import torchvision
import torch.nn as nn
import torch.nn.functional as F
from torchvision import transforms as T
from collections import OrderedDict #导入OrderedDict

class SimpleNet(nn.Module):
    def __init__(self,in_ch): #in_ch: 输入张量的通道数
        super(SimpleNet, self).__init__() #必须写,调用父类的构建函数
		
		#方法一,依次传入组成部分
        self.block1 = nn.Sequential( 
			nn.Conv2d(in_ch, in_ch, kernel_size=5),
			nn.BatchNorm2d(in_ch),
			nn.ReLU()
		)
		#方法二,传入一个OrderedDict
		self.block2 = nn.Sequential(OrderedDict([
				('conv1', nn.Conv2d(in_ch, in_ch, kernel_size=7)),
				('bn1', nn.BatchNorm2d(in_ch)),
				('relu1', nn.ReLU())
		]))
        self.linear1 = nn.Linear(13924,2) #定义全连接层1

    def forward(self,x):
        x = self.block1(x)
        x = self.block2(x)
        x = x.view(x.size(0), -1) #改变维度
        x = self.linear1(x)
        x = F.sigmoid(x) #进行Sigmoid变换,无参数
        return x

上面的代码使用nn.Sequential的两种实现方法,分别封装了两个含有卷积层、正则化层、和ReLU激活函数的模块。相比于直接传入层,使用OrderedDict时可以对层添加解释,但代码更繁琐,可根实际据情况灵活使用。

4. 调用模型

和使用其他类一样,我们先将定义好的模型类实例化,之后将输入矩阵传入即可。我们现在来调用刚刚定义好的SimpleNet模型:

#调用模型
model = SimpleNet(in_ch=1)
input_mat = torch.randn(4,1,128,128)
out = model(input_mat)
print(out.shape)

#输出
torch.Size([4, 2])

可以看到,模型输出是一个尺寸为(4,2)的张量。在之后的博文中,会介绍PyTorch中常用的层。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值