【动手学深度学习】层和块

层和块

简单介绍

  • 块:描述单个层,由多个层组成的组件或整个模型本身。使用块进行抽象的一个好处是可以将一些块组合成更大的组件,这一过程通常是递归的

在这里插入图片描述

简单入门


import torch
from torch import nn
from torch.nn import functional as F

# 直接定义两层  两个线性层
net = nn.Sequential(nn.Linear(20,256),nn.ReLU(),nn.Linear(256,10))

X = torch.rand(2,20)
net(X)
  • 实例化nn.Sequential来构建我们的模型,层的执行顺序是作为参数进行传递的
  • nn.Sequential定义一种特殊的Module,维护了一个Module组成的有序列表,两个全连接层都是Linear类的实例。
  • 前向传播函数很简单:将列表中的每一个块连接在一起,将每一个块的输出作为下一个快的输入

自定义块

  • 将输入数据作为其前向传播函数的参数。

  • 通过前向传播函数来生成输出。请注意,输出的形状可能与输入的形状不同。例如,我们上面模型中的第一个全连接的层接收一个20维的输入,但是返回一个维度为256的输出。

  • 计算其输出关于输入的梯度,可通过其反向传播函数进行访问。通常这是自动发生的。
    存储和访问前向传播计算所需的参数。

  • 根据需要初始化模型参数。

class MLP(nn.Module):
    # 用模型参数声明层。这里,我们声明两个全连接的层
    def __init__(self):
        # 调用MLP的父类Module的构造函数来执行必要的初始化。
        # 这样,在类实例化时也可以指定其他函数参数,例如模型参数params(稍后将介绍)
        super().__init__()
        self.hidden = nn.Linear(20, 256)  # 隐藏层
        self.out = nn.Linear(256, 10)  # 输出层

    # 定义模型的前向传播,即如何根据输入X返回所需的模型输出
    def forward(self, X):
        # 注意,这里我们使用ReLU的函数版本,其在nn.functional模块中定义。
        return self.out(F.relu(self.hidden(X)))

  • init函数通过super操作调用父类初始化,然后实例化两个全连接层

  • 块的一个主要优点是它的多功能性。 我们可以子类化块以创建层(如全连接层的类)、 整个模型(如上面的MLP类)或具有中等复杂度的各种组件。 我们在接下来的章节中充分利用了这种多功能性, 比如在处理卷积神经网络时。

顺序块

  • Sequential的设计是将其他模块串接起来
  • 自定义MySequential:一种将块逐个追加到列表的函数,一种前向传播函数,用于将输入按追加块的顺序传递给块组成的链条
class MySequential(nn.Module):
    def __init__(self,*args):
        super().__init__()
        for idx,module in enumerate(args):
            self._modules[str(idx)] = module

    def forward(self,X):
        for block in self._modules.values():
            X = block(X)
        return X
    
  • init函数将每一个模块逐个添加到有序字典_modules中,使用_modules的好处是:在模块的参数初始化过程中,系统知道在_modules字典中查找需要初始化参数的子块

  • 当MySequential的前向传播函数被调用的时候,每一个添加的块都按照它们被添加的顺序执行

net = MySequential(nn.Linear(20,256),nn.ReLU(),nn.Linear(256,10))
net(X)

猜你喜欢

转载自blog.csdn.net/qq_44653420/article/details/131705495
今日推荐