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

如何修复PyTorch二分类CNN触发的UnboundLocalError: o1未定义就引用报错

错误原因
  • 变量赋值顺序颠倒:你初始化nn.Conv2d时用到的o1、o2是在卷积层定义之后才赋值的,Python执行代码是从上到下顺序执行,调用未赋值的变量自然会触发UnboundLocalError。
  • 参数逻辑混淆:nn.Conv2d的第二个入参是卷积层的输出通道数,属于需要手动指定的超参数;而你写的_get_conv1_out方法是用来计算卷积输出特征图展平后的总元素数,完全不能当作卷积输出通道数使用,两者概念完全不同。同时你调用_get_conv1_out时只传入了输入通道数n,该方法需要传入输入张量的完整尺寸(通道数+高+宽)才能正确计算输出尺寸,传参逻辑也存在错误。
修复方案

你可以直接手动指定两个卷积层的输出通道数作为超参数,再通过样例输入自动计算卷积输出的展平维度,不需要手动计算硬传全连接层的输入尺寸,修复后的参考代码如下:

import torch
import torch.nn as nn
import torch.nn.functional as F
import numpy as np

class BinCNN(nn.Module):
    def __init__(self, in_channels, img_h, img_w, 
                 conv1_kernel=(2,2), conv1_out_channels=16,
                 conv2_kernel=(1,1), conv2_out_channels=32,
                 dropout_p=0.3, fc_hidden_dim=150):
        super().__init__()
        # 先定义卷积层
        self.conv1 = nn.Conv2d(in_channels, conv1_out_channels, kernel_size=conv1_kernel)
        self.conv2 = nn.Conv2d(conv1_out_channels, conv2_out_channels, kernel_size=conv2_kernel)
        self.drop = nn.Dropout(dropout_p)
        
        # 自动计算卷积输出展平后的维度
        with torch.no_grad():
            dummy_input = torch.zeros(1, in_channels, img_h, img_w)
            conv_out = self.conv2(self.conv1(dummy_input))
            flatten_dim = int(np.prod(conv_out.size()))
        
        # 初始化全连接层
        self.fcl1 = nn.Linear(flatten_dim, fc_hidden_dim)
        self.fcl2 = nn.Linear(fc_hidden_dim, 2)

    def forward(self, x):
        x = F.relu(self.conv1(x))
        x = F.relu(self.conv2(x))
        x = x.flatten(1)
        x = self.drop(F.relu(self.fcl1(x)))
        return self.fcl2(x)

实例化模型时传入你的输入图像尺寸即可,示例如下(以3通道32*32输入为例):

sd = BinCNN(in_channels=3, img_h=32, img_w=32, dropout_p=0.3, fc_hidden_dim=150)
print(sd)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 03:18:03