pytorch框架的模型定义以及推理数据流向

在这里插入图片描述

一、前言

这篇博文旨在基于pytorch深度学习框,讲解模型定义以及推理数据流向,围绕下面这个问题:

用过pytorch的朋友肯定知道,在模型所谓model初始化之后,再去看这个变量的内容,可以看到每一层结构,那么可能会有一个疑问,我还没forward(推理),怎么就知道我的数据流向呢?这个模型定义的顺序和初始化的顺序有没有关系呢?

二、模型初始化

在 PyTorch 的 nn.Module 中,参数层(如 Conv2d、Linear 等)确实有前后顺序,这与它们在模型中定义的顺序一致。这种顺序在以下几个方面体现:

2.1 定义顺序

在定义模型的过程中,层的顺序是重要的,因为它决定了数据在前向传播(forward pass)中的流动顺序。例如:

import torch.nn as nn
class SimpleModel(nn.Module):
    def __init__(self):
        super(SimpleModel, self).__init__()
        self.fc1 = nn.Linear(10, 20)  # 第一层
        self.relu = nn.ReLU()         # 第二层
        self.fc2 = nn.Linear(20, 5)   # 第三层

    def forward(self, x):
        x = self.fc1(x)  # 数据先经过 fc1
        x = self.relu(x) # 然后经过 ReLU 激活
        x = self.fc2(x)  # 最后经过 fc2
        return x

在这个例子中:

  • self.fc1 是第一个线性层。
  • self.relu 是中间的激活层。
  • self.fc2 是最后一个线性层。
    数据流动顺序决定了各层的作用顺序。

2.2 参数顺序

  • 在调用 self.parameters() 或 self.named_parameters() 时,返回的参数的顺序与层定义的顺序一致:
    model = SimpleModel()
    for name, param in model.named_parameters():
        print(name)
    
  • 输出顺序:
    fc1.weight
    fc1.bias
    fc2.weight
    fc2.bias
    
  • 这里的顺序反映了层的定义顺序(fc1 在 fc2 之前)。

2.3 在优化器中的顺序

当你将模型的参数传递给优化器时,它们会保留这个顺序:

import torch.optim as optim
optimizer = optim.SGD(model.parameters(), lr=0.01)

优化器会按照 self.parameters() 返回的顺序更新参数。但这并不影响梯度更新的正确性,因为每个参数的梯度是独立计算和更新的。

2.4 在计算图中的顺序

前后顺序在计算图中也很重要,尤其是在前向传播和反向传播过程中。数据按层的顺序流动,梯度也按相反的顺序传播(从最后一层向前传递)。

2.5 总结

  • 定义顺序决定了前向传播顺序。
  • self.parameters() 返回的参数顺序与定义顺序一致。
  • 优化器会按顺序更新参数,但不会影响训练的正确性。
    这种顺序有助于确保模型前向和反向传播流程的逻辑性和可读性。

三、推理数据流

层的顺序记录:定义 vs. Forward 过程
这里有个核心问题是:PyTorch 中参数顺序是基于 init 定义,还是 forward 方法中的执行顺序?

3.1 init 定义顺序

  • 在 nn.Module 的 init 方法中,你定义了模型的各个层(如 nn.Conv2d、nn.Linear 等)。

  • PyTorch 会在初始化时注册这些层,并按照它们在 init 中定义的顺序存储。这个顺序决定了调用 self.parameters() 或 self.named_parameters() 时参数的顺序。

  • 示例:

    class SimpleModel(nn.Module):
        def __init__(self):
            super(SimpleModel, self).__init__()
            self.fc1 = nn.Linear(10, 20)  # 第一层
            self.fc2 = nn.Linear(20, 5)   # 第二层
    
    • 在这里,self.fc1 会先被注册,self.fc2 后注册。
    • 使用 model.parameters() 会按 fc1 → fc2 的顺序返回。

3.2 forward 中的执行顺序

  • forward 决定数据的流动顺序。
    你可以在 forward 中改变数据流经各层的顺序,但这不会影响参数的存储顺序。
  • 示例:
def forward(self, x):
   x = self.fc2(x)  # 先经过 fc2
   x = self.fc1(x)  # 再经过 fc1
   return x
  • 在这个例子中:
    • 数据流顺序是 fc2 → fc1。
    • 参数顺序依然是 fc1 → fc2,因为它们是在 init 中按这个顺序定义的。
  • 注意:
    这种灵活性允许你在 forward 中实现复杂的前向传播逻辑,比如跳跃连接、并行处理等。

3.3 训练与优化器中的顺序

  • 优化器更新顺序:
    优化器更新参数的顺序与 init 定义的顺序一致,而不是 forward 中的顺序。
    原因: 参数和梯度是分层存储和更新的,优化器不会关心数据流顺序。

3.4 总结:

  1. 参数的顺序是在 init 中定义时决定的。
  2. 数据的流动顺序是在 forward 方法中决定的。
  3. 训练过程中,参数更新顺序遵循 init 的定义,而非 forward 的执行顺序。
    这种设计允许你在 forward 中灵活构建前向传播逻辑,而 init 确保所有层的参数能被正确注册和管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Thomas_Cai

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值