PyTorch构建逻辑回归模型时遇"optimizer got an empty parameter list"错误求助
PyTorch构建逻辑回归模型时遇"optimizer got an empty parameter list"错误求助
嗨,我来帮你排查这个问题~ 这个报错的核心原因和你模型的初始化逻辑、代码缩进都有关系,咱们一步步来解决:
1. 报错的根本原因
当你创建LogisticRegressionModel实例时如果没传input_dim,__init__里会把self.linear设为None。这时候你去创建SGD优化器,调用model.parameters()会返回空列表——因为PyTorch此时还没识别到任何可训练的层(self.linear要等到第一次调用forward才会被实例化),优化器自然就报错了。
另外我注意到你代码里的缩进有严重问题:forward方法被错误地嵌套在__init__的else代码块里了!这会导致forward不是类的方法,模型实例根本无法正常执行前向传播,这也是必须先修正的问题。
2. 完整的修正方案
第一步:先修正模型的代码缩进
把forward方法的缩进调整到和__init__同一级别,确保它是类的成员方法:
import torch import torch.nn as nn import torch.optim as optim from torch import Tensor class LogisticRegressionModel(nn.Module): def __init__(self, input_dim=None) -> None: super().__init__() if input_dim is not None: torch.manual_seed(9) self.linear = nn.Linear(in_features=input_dim, out_features=1) else: self.linear = None self.input_dim = None # 这里的缩进要正确,属于else块 # 注意这里的缩进,和__init__平级 def forward(self, X: Tensor): if self.linear is None: input_dim = X.shape[1] torch.manual_seed(9) self.linear = nn.Linear(in_features=input_dim, out_features=1) return torch.sigmoid(self.linear(X))
第二步:解决优化器空参数列表的问题
这里给你两种可选方案:
方案A:提前指定输入维度(推荐,更直观)
初始化模型时直接传入input_dim,这样self.linear在__init__阶段就被创建,优化器能直接拿到可训练参数:
# 假设你的输入数据维度是10,根据实际情况替换 model = LogisticRegressionModel(input_dim=10) # 现在创建优化器就不会报错了 optimizer = optim.SGD(params=model.parameters(), lr=0.001)
方案B:支持延迟初始化(适合不想提前指定维度的场景)
如果确实想让模型自动从输入数据中识别维度,那需要在创建优化器之前,先给模型喂一个dummy数据触发forward,提前初始化self.linear层:
model = LogisticRegressionModel() # 生成一个和训练数据同维度的虚拟输入(比如batch_size=1,输入维度=10) dummy_X = torch.randn(1, 10) # 执行一次前向传播,让模型初始化linear层 model(dummy_X) # 现在再创建优化器就能获取到参数了 optimizer = optim.SGD(params=model.parameters(), lr=0.001)
3. 额外的优化建议
你当前用的是BCEWithLogitsLoss,这个损失函数本身已经包含了sigmoid的计算逻辑,而你的模型forward里又手动加了torch.sigmoid(),这样会导致两次sigmoid计算,不仅冗余还可能引发数值不稳定的问题。建议修改forward的返回值,去掉手动的sigmoid:
def forward(self, X: Tensor): if self.linear is None: input_dim = X.shape[1] torch.manual_seed(9) self.linear = nn.Linear(in_features=input_dim, out_features=1) return self.linear(X) # 直接返回线性层的输出,交给BCEWithLogitsLoss处理
这样调整后,你的模型不仅能解决报错,训练效率和数值稳定性也会更好~




