SKORCH结合PyCaret处理回归问题时目标y维度报错如何解决
PyCaret集成Skorch实现回归任务维度报错修复
问题描述
参考PyCaret+Skorch构建PyTorch神经网络的分类任务示例,将方案迁移到回归场景时触发维度不匹配错误。
复现代码
import pycaret import numpy as np import torch.nn as nn import torch.nn.functional as F from skorch import NeuralNetRegressor from sklearn.pipeline import Pipeline from skorch.helper import DataFrameTransformer from pycaret.regression import * from pycaret.datasets import get_data data = get_data('boston') target = "medv" reg1 = setup(data = data, target = target, train_size = 0.8, fold = 5, session_id = 123, silent = True) class RegressorModule(nn.Module): def __init__( self, num_units=100, nonlin=F.relu, ): super(RegressorModule, self).__init__() self.num_units = num_units self.nonlin = nonlin self.dense0 = nn.Linear(14, num_units) self.nonlin = nonlin self.dense1 = nn.Linear(num_units, 10) self.output = nn.Linear(10, 1) def forward(self, X, **kwargs): X = self.nonlin(self.dense0(X)) X = F.relu(self.dense1(X)) X = self.output(X) return X net_regr = NeuralNetRegressor( RegressorModule, max_epochs=20, lr=0.1, device='cuda' ) nn_pipe = Pipeline( [ ("transform", DataFrameTransformer()), ("net", net_regr), ] ) skorch_model = create_model(nn_pipe)
报错信息
ValueError: 目标数据不能为1维结构,需为2维格式,第二维度大小需与回归目标数量一致(通常为1),请将目标数据reshape为2维格式(例如y = y.reshape(-1, 1))。
手动验证结果
手动完成数据归一化、目标维度调整预处理后,直接传入Skorch训练可正常运行,对应代码如下:
X = data.copy().to_numpy().astype(np.float32) mean = X.mean(axis=0) X -= mean std = X.std(axis=0) X /= std y = data[target].to_numpy().astype(np.float32) y = y.reshape(-1, 1) net_regr.fit(X, y)
运行效果截图:
问题根因
PyCaret内部基于DataFrame格式存储训练数据,传入Skorch转换为PyTorch可用张量时,目标值y始终保持1维结构。该结构适配分类任务的输入要求,但Skorch的NeuralNetRegressor强制要求y为2维格式,因此触发报错。
解决方案
不需要修改PyCaret内部处理逻辑,通过子类化原生Skorch回归器增加维度自动适配逻辑即可解决问题,同时修正原代码中输入层维度的错误(波士顿房价数据集特征数为13,原代码误写为14)。
修复后完整可运行代码
import numpy as np import torch.nn as nn import torch.nn.functional as F from skorch import NeuralNetRegressor from sklearn.pipeline import Pipeline from skorch.helper import DataFrameTransformer from pycaret.regression import * from pycaret.datasets import get_data # 适配PyCaret输入格式的Skorch回归器补丁类 class SkorchRegressorAdaptor(NeuralNetRegressor): def fit(self, X, y, **fit_params): # 将PyCaret传入的1维y转为2维float32格式,满足Skorch输入要求 y = y.to_numpy().astype(np.float32).reshape(-1, 1) return super().fit(X, y, **fit_params) def predict(self, X): # 将模型输出的2维预测结果转为1维,适配PyCaret评估逻辑 y_pred = super().predict(X) return y_pred.flatten() data = get_data('boston') target = "medv" reg1 = setup(data = data, target = target, train_size = 0.8, fold = 5, session_id = 123, silent = True) class RegressorModule(nn.Module): def __init__( self, num_units=100, nonlin=F.relu, ): super(RegressorModule, self).__init__() self.num_units = num_units self.nonlin = nonlin # 修正输入维度:数据集共13个数值特征 self.dense0 = nn.Linear(13, num_units) self.dense1 = nn.Linear(num_units, 10) self.output = nn.Linear(10, 1) def forward(self, X, **kwargs): X = self.nonlin(self.dense0(X)) X = F.relu(self.dense1(X)) X = self.output(X) return X net_regr = SkorchRegressorAdaptor( RegressorModule, max_epochs=20, lr=0.1, device='cuda', # 关闭Skorch自带的训练集拆分,完全使用PyCaret的交叉验证逻辑 train_split=None ) nn_pipe = Pipeline( [ ("transform", DataFrameTransformer()), ("net", net_regr), ] ) skorch_model = create_model(nn_pipe)
关键修复点说明
- 自定义
SkorchRegressorAdaptor继承原生NeuralNetRegressor:重写fit方法自动完成目标y的维度转换,重写predict方法将输出转换回PyCaret兼容的1维格式,全程不需要侵入修改PyCaret内部流程 - 修正神经网络第一层输入维度为13,匹配波士顿房价数据集的实际特征数量,避免矩阵乘法维度不匹配错误
- 增加
train_split=None参数,禁用Skorch自带的内部验证集拆分,完全使用PyCaret的交叉验证拆分规则,避免数据泄露
内容的提问来源于stack exchange,提问作者user1910714
相关产品推荐
相关产品推荐

