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
相关产品推荐
相关产品推荐

