You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何使用nn.Sequential的PyTorch同结构模型效果远差于手动实现?

问题:PyTorch中nn.Sequential版本模型准确率极低的原因及解决办法

在Fashion MNIST入门实践中,手动实现的模型准确率约90%,但用nn.Sequential改写后准确率仅约10%,核心差异和问题原因如下:

关键差异与问题根源

  • 最后一层Linear的参数注册问题:
    手动实现版本中,self.lin1 = nn.Linear(12544, 10)在__init__方法内定义,会被自动注册为模型的可训练参数,训练时会被优化器更新;
    而nn.Sequential版本中,x = nn.Linear(12544, 10)(x)是在forward方法内临时创建的层,其参数不会被加入模型的参数列表,训练时完全不更新,相当于用随机初始化的固定权重做预测,自然准确率接近随机水平(10%,对应Fashion MNIST的10类)。
  • 手动实现中的self.lin2 = nn.Linear(64, 10)属于冗余代码,未被使用,但不影响模型性能。

修正后的nn.Sequential版本代码

方案1:将全连接层纳入nn.Sequential

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

class Down(nn.Module):
    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.down = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
            nn.BatchNorm2d(out_channels),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
    def forward(self, x):
        return self.down(x)

class MyNet(nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()
        self.net = nn.Sequential(
            Down(1, 128),
            Down(128, 256),
            nn.Flatten(start_dim=1),  # 替代torch.flatten,更符合Sequential风格
            nn.Linear(12544, 10)
        )
        
    def forward(self, x):
        x = self.net(x)
        return F.log_softmax(x, dim=1)

方案2:单独注册全连接层

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

class Down(nn.Module):
    def __init__(self, in_channels, out_channels):
        super().__init__()
        self.down = nn.Sequential(
            nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1),
            nn.BatchNorm2d(out_channels),
            nn.ReLU(),
            nn.MaxPool2d(2)
        )
    def forward(self, x):
        return self.down(x)

class MyNet(nn.Module):
    def __init__(self):
        super(MyNet, self).__init__()
        self.net = nn.Sequential(
            Down(1, 128),
            Down(128,256)
        )
        self.lin1 = nn.Linear(12544, 10)  # 在__init__中注册可训练参数
        
    def forward(self, x):
        x = self.net(x)
        x = torch.flatten(x, start_dim=1)
        x = self.lin1(x)
        return F.log_softmax(x, dim = 1)

验证方法

训练前可以打印模型的参数列表,确认全连接层的参数是否被包含:

model = MyNet()
for name, param in model.named_parameters():
    print(name, param.shape)

修正后的代码应该能看到lin1.weight和lin1.bias(或net.3.weight、net.3.bias,对应方案1的Sequential索引)。

内容的提问来源于stack exchange,提问作者Gruny

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.06 08:55:12