多层神经网络运行报错求助:optimizer参数列表为空
问题排查与修正方案
这个错误ValueError: optimizer got an empty parameter list的核心原因很明确:你的MultiLayerPerceptron类里没有定义任何可训练的参数层——你现在的fc1、fc2、fc3只是单纯的Sigmoid激活函数,而不是带有权重和偏置的线性层(nn.Linear),所以model.parameters()返回的是空列表,优化器自然找不到参数来更新。
除此之外,你的代码还有几个其他问题会导致后续运行异常,我一起帮你梳理并修正:
主要问题梳理
- 缺少可训练的线性层:激活函数本身没有可学习的参数,必须先定义
nn.Linear层来生成权重,再搭配激活函数 - 模型实例化语法错误:
model = MultiLayerPerceptron)少了括号,应该是model = MultiLayerPerceptron() - 激活函数与损失函数不匹配:你用了
nn.CrossEntropyLoss,这个损失函数默认会对输入的logits做Softmax,最后一层不需要加Sigmoid;而且你在forward里给Sigmoid又套了ReLU,这会导致特征表达混乱 - 不必要的
Variable使用:PyTorch 0.4.0之后,Variable已经被整合进Tensor,直接用torch.from_numpy(...).float()就可以,不需要再包一层Variable
修正后的完整代码
import numpy as np import torch import torch.nn as nn import torch.nn.functional as F from sklearn.datasets import make_moons from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score # 生成数据集并划分训练测试集 X, y = make_moons(200, noise=0.2, random_state=42) X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.30, random_state=1, stratify=y) # 修正后的三层神经网络 class MultiLayerPerceptron(nn.Module): def __init__(self): super(MultiLayerPerceptron, self).__init__() # 定义线性层:输入维度是2(make_moons的特征数),中间层可以自定义维度,最后输出2类的logits self.fc1 = nn.Linear(2, 16) # 第一层线性层:2输入→16隐藏单元 self.fc2 = nn.Linear(16, 8) # 第二层线性层:16→8隐藏单元 self.fc3 = nn.Linear(8, 2) # 第三层线性层:8→2输出(对应二分类) def forward(self, x): x = F.relu(self.fc1(x)) # 线性层后接ReLU激活 x = F.relu(self.fc2(x)) x = self.fc3(x) # 最后一层输出logits,交给CrossEntropyLoss处理 return x # 实例化模型(修正括号问题) model = MultiLayerPerceptron() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) loss_fn = nn.CrossEntropyLoss() epochs = 1000 def print_(loss): print(f"Loss: {loss:.4f}") # 转换数据为PyTorch Tensor(去掉不必要的Variable) x_train = torch.from_numpy(X_train).float() y_train = torch.from_numpy(y_train).long() # 训练循环 for epoch in range(1, epochs + 1): model.train() # 显式设置训练模式 y_pred = model(x_train) loss = loss_fn(y_pred, y_train) # 每20轮打印一次损失,避免输出过多 if epoch % 20 == 0: print(f"Epoch #{epoch}") print_(loss.item()) optimizer.zero_grad() loss.backward() optimizer.step() # 测试阶段 model.eval() x_test = torch.from_numpy(X_test).float() with torch.no_grad(): # 测试阶段不需要计算梯度 pred = model(x_test) pred = pred.detach().numpy() print(f"Test Accuracy: {accuracy_score(y_test, np.argmax(pred, axis=1)):.4f}")
关键修正点说明
- 添加线性层:每个
fc层都用nn.Linear定义,这样模型就有了可训练的权重和偏置参数,优化器就能正常获取参数列表 - 调整激活与损失的搭配:
CrossEntropyLoss要求输入是未经过Softmax的logits,所以最后一层不需要激活函数;中间层用ReLU是更常用的选择,避免Sigmoid的梯度消失问题 - 修复语法错误:补全模型实例化的括号
- 简化数据处理:去掉过时的
Variable,添加model.train()和model.eval()规范训练/测试模式,用torch.no_grad()减少测试阶段的内存消耗
这样修正后,代码应该能正常运行,并且在make_moons数据集上达到不错的分类准确率。
内容的提问来源于stack exchange,提问作者learningtoprogram123




