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

PyTorch自定义CNN模块出现额外1792个参数的问题咨询

问题描述

单独统计第一个卷积块的参数量时,得到结果为36928,与预期值完全一致。但在另一个继承自nn.Module的类中调用该块搭建模型时,模型多出了1792个额外参数,无法定位参数来源。

复现代码

卷积块定义

class Conv2dBlock(torch.nn.Module):
    def __init__(self, in_filters, out_filters, kernel_size=3):
        super(Conv2dBlock, self).__init__()
        self.conv2d_seq = torch.nn.Sequential()
        for k in range(2):
            self.conv2d_seq.append(torch.nn.Conv2d(in_channels=in_filters, out_channels=out_filters, kernel_size=kernel_size, padding='same'))
            self.conv2d_seq.append(torch.nn.ReLU())
            in_filters = out_filters
        
    def forward(self, input):
        out = self.conv2d_seq(input)
        return out

编码器块定义

class EncoderBlock(torch.nn.Module):
    def __init__(self):
        super(EncoderBlock, self).__init__()
        self.conv2d = Conv2dBlock(3, 64)
        self.maxpool = torch.nn.MaxPool2d(kernel_size=2)

    def forward(self, input):
        x = self.conv2d(input)
        p = self.maxpool(x)
        out = torch.nn.functional.dropout(p, 0.3)
        return x, out

模型定义与参数量统计

class UNet_model(torch.nn.Module): 
    def __init__(self):
        super(UNet_model, self).__init__()
        self.encoder_block1 = EncoderBlock()


    def forward(self, input):
        p1 = self.encoder_block1(input)
        # 已省略无关代码
        
        return p1


model = UNet_model()
summary(model, (3,128,128))

问题现象

summary工具统计得到UNet_model总参数量为38720,比预期的36928多1792,差值刚好对应一个输入通道3、输出通道64、3×3卷积核的卷积层参数量(3*64*3*3 + 64 = 1792),相当于对输入多应用了一次卷积,找不到问题成因。

问题原因与排查方案

你的代码里不存在“额外新增的卷积层”,嵌套模型统计得到的38720是当前定义下的正确参数量,之前单独统计得到36928是统计失误导致的:

  1. 按你当前给出的Conv2dBlock定义,传入in_filters=3, out_filters=64时,块内包含两个卷积层:
    • 第一层为3输入通道、64输出通道的3×3卷积(带偏置),参数量为64*(3*3*3 + 1) = 1792
    • 第二层为64输入通道、64输出通道的3×3卷积(带偏置),参数量为64*(3*3*64 +1) = 36928
      两个卷积层总参数量为1792+36928=38720,和你嵌套模型的统计结果完全一致。
  2. 代码中MaxPool2d是无参数层,torch.nn.functional.dropout是函数式操作、无注册参数,二者都不会增加可学习参数量。
  3. 之前单独统计卷积块得到36928,通常是以下原因导致:
    • 单独测试时实例化的是旧版本类:比如之前Conv2dBlock的循环只执行1次、输入通道设为64,刚好得到单个64->64卷积的参数量36928,修改类代码为循环2次、输入通道3后,没有重新运行类定义代码块,导致单独测试用的是内存中缓存的旧类,搭建嵌套模型时才加载了新的类定义
    • 单独统计参数量的方法有误,只统计到了第二个卷积层的参数,漏统计了第一个卷积层
    • 单独测试时实例化参数写错,传入的输入通道不是3,导致第一个卷积层参数量和预期不符

你可以执行以下代码直接打印所有参数的名称和归属,验证参数来源:

for name, param in model.named_parameters():
    print(f"参数名:{name},参数量:{param.numel()}")

执行后你会看到所有参数都归属Conv2dBlock内的两个卷积层,不存在任何不明来源的参数。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 15:48:35