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

PyTorch修改ResNet50的layer4.conv3输出通道数报错求解

问题

想要修改PyTorch中ResNet50的输出通道数,尝试了以下代码却出现“weight should contain 2048 elements not 300”错误,使用ChatGPT给出的方案也出现其他错误,请问问题出在哪里?

代码如下:

# Model training routine
print("\nTraining:-\n")

new_num_channels = 300

#----#
resnet_v2 = models.resnet50(pretrained=True)

#print(resnet_v2)
#print("fc_layer.in_features")
#print(fc_layer.in_features)

resnet_v2.layer4[-1].conv3.out_channels = new_num_channels
num_classes = 3


weight = torch.nn.Parameter(torch.Tensor(new_num_channels))
torch.nn.init.uniform_(weight)  # Initialize the weight tensor

resnet_v2.layer4[-1].bn3.weight = weight
resnet_v2.layer4[-1].bn3.num_features = new_num_channels



fc_layer = resnet_v2.fc
fc_layer.in_features = new_num_channels
fc_layer.weight = torch.nn.Parameter(torch.Tensor(new_num_channels, fc_layer.out_features))

gap_layer = resnet_v2.avgpool
gap_layer.num_features = fc_layer.in_features


resnet_v2.fc = nn.Sequential(
              nn.Linear(new_num_channels, 128), # Change the number of channels in Fully connected layer 
              nn.ReLU(inplace=True),
              nn.Linear(128, num_classes))

fc_layer.reset_parameters()

resnet_v2 = resnet_v2.to(device)

print(resnet_v2)
changed_model = train_model(resnet_v2, loss_fn, opt, scheduler, num_epochs=train_epoch)

问题分析与解决方案

错误根源

  • 直接修改层属性无效:你仅修改conv3.out_channels、bn3.num_features这类数值属性,并没有改变卷积层和BN层的权重张量形状。比如原conv3权重是(2048, in_channels, k, k),修改out_channels为300后,实际权重还是2048通道的形状,后续绑定新参数时维度不匹配,直接触发报错。
  • BN层参数替换逻辑错误:BN层的weight和bias需与特征通道数对应,但前面卷积层未正确修改,导致即使替换BN参数也无法匹配卷积输出。
  • AvgPool层修改多余:ResNet的avgpool是AdaptiveAvgPool2d((1,1)),不存在num_features属性,此修改会引发属性不存在的错误。
  • FC层操作逻辑混乱:先修改原fc_layer属性,随后又直接替换resnet_v2.fc为新的Sequential,之前的操作完全无效,还会因原fc_layer权重形状不匹配报错。

正确修改方式

要修改ResNet50最后一个卷积块的输出通道数,需重新实例化卷积层和BN层,而非直接修改属性:

import torch
import torch.nn as nn
from torchvision import models

new_num_channels = 300
num_classes = 3
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# 加载预训练模型
resnet_v2 = models.resnet50(pretrained=True)

# 获取最后一个残差块
last_residual_block = resnet_v2.layer4[-1]
# 保留原卷积层的输入通道、核尺寸、步长等参数
in_channels = last_residual_block.conv3.in_channels
kernel_size = last_residual_block.conv3.kernel_size
stride = last_residual_block.conv3.stride
padding = last_residual_block.conv3.padding
bias = last_residual_block.conv3.bias is not None

# 重新定义conv3:输出通道改为目标值
last_residual_block.conv3 = nn.Conv2d(
    in_channels=in_channels,
    out_channels=new_num_channels,
    kernel_size=kernel_size,
    stride=stride,
    padding=padding,
    bias=bias
)

# 重新定义bn3:匹配新的通道数
last_residual_block.bn3 = nn.BatchNorm2d(num_features=new_num_channels)

# 替换全连接层,输入特征数对应新的通道数
resnet_v2.fc = nn.Sequential(
    nn.Linear(new_num_channels, 128),
    nn.ReLU(inplace=True),
    nn.Linear(128, num_classes)
)

# 移动到计算设备
resnet_v2 = resnet_v2.to(device)

# 后续训练逻辑
# changed_model = train_model(resnet_v2, loss_fn, opt, scheduler, num_epochs=train_epoch)

关键说明

  • 卷积层必须重新实例化,确保权重张量形状为(new_num_channels, in_channels, k, k),才能与前一层输出维度匹配。
  • BN层需同步重新定义,保证参数数量与新的卷积输出通道一致。
  • 全连接层直接替换即可,自适应池化层会自动适配输入通道数,输出展平后刚好匹配新全连接层的输入维度。
  • 无需修改AvgPool层,它会根据输入自动调整输出形状。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 02:40:22