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

PyTorch/Skorch回归神经网络性能指标全为零,求技术支援

解决Skorch+PyTorch回归任务指标全为0的问题

问题分析与修复步骤

1. 修正nn.LazyLinear参数错误

nn.LazyLinear仅需指定输出特征数,它会在首次前向传播时自动推断输入维度。你原代码将输入、输出维度写反,导致网络结构异常,无法正常学习。

错误写法:

self.dense0 = nn.LazyLinear(input_size, num_units)

修正后:

self.dense0 = nn.LazyLinear(num_units)
self.dense1 = nn.LazyLinear(num_units_d1)
self.dense2 = nn.LazyLinear(num_units_d2)
self.output = nn.LazyLinear(1)

2. 移除nn.Module中的training_step方法

training_step是PyTorch Lightning的专属API,skorch的NeuralNetRegressor不支持该方法。自定义损失与日志需通过skorch的参数配置实现,而非在Module中重写训练逻辑。直接删除RegressorModule内的training_step方法即可,skorch会自动为回归任务使用MSE损失。

3. 恢复训练集划分逻辑

你设置train_split=None会导致skorch不划分验证集,PyCaret计算指标时因无有效验证数据输出全0。建议使用默认交叉验证划分:

train_split=CVSplit(cv=5)  # 5折交叉验证拆分训练/验证集

4. 降低学习率

原代码lr=0.1过高,会引发训练不稳定、损失无法收敛甚至指标异常。建议调整为0.001或更小,后续可根据收敛情况微调。

5. 优化目标变量处理

简化MyNet的fit方法,使用更通用的维度转换逻辑:

class MyNet(NeuralNetRegressor):
    def fit(self, X, y):
        if y.ndim == 1:
            y = y.reshape(-1, 1)  # 兼容numpy数组与pandas Series
        return super().fit(X, y)

修正后的完整代码

import torch
import torch.nn as nn
import torch.nn.functional as F
from skorch import NeuralNetRegressor
from skorch.helper import DataFrameTransformer
from skorch.dataset import CVSplit
from skorch.callbacks import EarlyStopping

target = "Price"
exp = setup(data = train, 
             test_data = test,
             target = target)

class RegressorModule(nn.Module):
    def __init__(
            self,
            num_units=150,
            num_units_d1=100,
            num_units_d2=50,
            nonlin=F.relu,
    ):
        super(RegressorModule, self).__init__()
        self.nonlin = nonlin
        self.dense0 = nn.LazyLinear(num_units)
        self.dense1 = nn.LazyLinear(num_units_d1)
        self.dense2 = nn.LazyLinear(num_units_d2)
        self.output = nn.LazyLinear(1)

    def forward(self, X, **kwargs):
        X = self.nonlin(self.dense0(X))
        X = self.nonlin(self.dense1(X))
        X = self.nonlin(self.dense2(X))
        X = self.output(X)
        return X

class MyNet(NeuralNetRegressor):
    def fit(self, X, y):
        if y.ndim == 1:
            y = y.reshape(-1, 1)
        return super().fit(X, y)

net_regr = MyNet(
    module=RegressorModule(),
    max_epochs=20,
    lr=0.001,
    train_split=CVSplit(cv=5),
    verbose=1,  # 开启训练日志,便于观察收敛状态
    callbacks=[EarlyStopping(patience=3)]  # 添加早停防止过拟合
)

nn_pipe = Pipeline(
    [
        ("transform", DataFrameTransformer()),
        ("net", net_regr),
    ]
)

skorch_model = exp.create_model(nn_pipe)

额外建议

  • 开启verbose=1可查看训练过程中的损失变化,确认模型是否在收敛。
  • 神经网络对数据尺度敏感,若指标仍异常,检查特征是否做了标准化/归一化处理。

内容的提问来源于stack exchange,提问作者Isabel van der Steenhoven

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 06:53:15