如何修复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
相关产品推荐
相关产品推荐

