You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

多层神经网络运行报错求助:optimizer参数列表为空

问题排查与修正方案

这个错误ValueError: optimizer got an empty parameter list的核心原因很明确:你的MultiLayerPerceptron类里没有定义任何可训练的参数层——你现在的fc1fc2fc3只是单纯的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}")

关键修正点说明

  1. 添加线性层:每个fc层都用nn.Linear定义,这样模型就有了可训练的权重和偏置参数,优化器就能正常获取参数列表
  2. 调整激活与损失的搭配CrossEntropyLoss要求输入是未经过Softmax的logits,所以最后一层不需要激活函数;中间层用ReLU是更常用的选择,避免Sigmoid的梯度消失问题
  3. 修复语法错误:补全模型实例化的括号
  4. 简化数据处理:去掉过时的Variable,添加model.train()model.eval()规范训练/测试模式,用torch.no_grad()减少测试阶段的内存消耗

这样修正后,代码应该能正常运行,并且在make_moons数据集上达到不错的分类准确率。

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

火山引擎 最新活动