scikit-learn中GradientBoostingRegressor3维输出报错解决方法
尝试使用scikit-learn库中的RandomForestRegressor和GradientBoostingRegressor模型,实现13维输入数据到3维输出数据的映射。RandomForestRegressor可正常运行,但GradientBoostingRegressor训练时抛出如下ValueError:
ValueError: y should be a 1d array, got an array of shape (16127, 3) instead.
两类模型均以决策树为弱学习器,仅GradientBoostingRegressor出现该报错。直接将3维输出标签转换为1维数组的方式无法满足3维向量映射需求,需要找到使用梯度提升模型实现3维输出回归的可行方案。
原实现代码如下:
import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn.ensemble import RandomForestRegressor from sklearn.ensemble import GradientBoostingRegressor # Read data from csv files Input_data_features = pd.read_csv("C:/Users/wi9632/Desktop/TestData_InputFeatures.csv", sep=';') Input_data_labels = pd.read_csv("C:/Users/wi9632/Desktop/TestData_OutputLabels.csv", sep=';') Input_data_features = Input_data_features.values Input_data_labels = Input_data_labels.values # standardize input features X and output labels Y scaler_standardized_X = StandardScaler() Input_data_features = scaler_standardized_X.fit_transform(Input_data_features) scaler_standardized_Y = StandardScaler() Input_data_labels = scaler_standardized_Y.fit_transform(Input_data_labels) # Split dataset into train, validation, an test index_X_Train_End = int(0.7 * len(Input_data_features)) index_X_Validation_End = int(0.9 * len(Input_data_features)) X_train = Input_data_features[0: index_X_Train_End] X_valid = Input_data_features[index_X_Train_End: index_X_Validation_End] X_test = Input_data_features[index_X_Validation_End:] Y_train = Input_data_labels[0: index_X_Train_End] Y_valid = Input_data_labels[index_X_Train_End: index_X_Validation_End] Y_test = Input_data_labels[index_X_Validation_End:] #Define a random forest model and train it model_randomForest = RandomForestRegressor( ) model_randomForest.fit(X_train, Y_train) #Predict the test data with Random Forest Y_pred_randomForest = model_randomForest.predict(X_test) print(f"Random Forest Prediction: {Y_pred_randomForest}") #Define a gradient boosting model and train it (-->Here I get the ValueError) model_gradientBoosting = GradientBoostingRegressor( ) model_gradientBoosting.fit(X_train, Y_train) #Predict the test data with Gradient Boosting Y_pred_gradientBoosting = model_gradientBoosting.predict(X_test) print(f"Gradient Boosting Prediction: {Y_pred_gradientBoosting}")
问题补充:该问题暂未解决,需要可行的解决思路。
scikit-learn原生的GradientBoostingRegressor在设计上不原生支持多输出回归任务,这和模型是否基于决策树构建没有直接关系。RandomForestRegressor在代码实现层面原生适配了多输出场景,训练时会为每个输出维度独立构建对应的随机森林子模型,因此可以直接传入shape为(n_samples, n_outputs)的二维标签训练。但传统GradientBoostingRegressor的实现逻辑仅支持单目标回归,训练时会强制校验输入标签为一维数组,直接传入3维标签就会触发上述报错。
方案1:使用MultiOutputRegressor包装器适配多输出
这是scikit-learn官方提供的多输出任务通用适配方案,改动代码量最小。其原理是为每个输出维度单独训练一个独立的GradientBoostingRegressor模型,预测时将所有子模型的输出拼接为最终的多维预测结果,完全匹配3维输出的需求。
修改步骤:
- 导入多输出包装器:
from sklearn.multioutput import MultiOutputRegressor
- 替换原代码中GBDT模型的定义、训练逻辑,其余代码保持不变:
# 用MultiOutputRegressor包装原生GBDT,适配多输出回归 model_gradientBoosting = MultiOutputRegressor(GradientBoostingRegressor()) model_gradientBoosting.fit(X_train, Y_train) # 预测结果直接为shape (n_samples, 3)的矩阵,和随机森林输出格式一致 Y_pred_gradientBoosting = model_gradientBoosting.predict(X_test) print(f"Gradient Boosting Prediction: {Y_pred_gradientBoosting}")
注意:该方案下每个输出维度的GBDT模型独立训练,不会建模不同输出维度之间的相关性。
方案2:替换为原生支持多输出的梯度提升实现
如果希望模型原生支持多输出、无需额外包装,可以直接替换为已经内置多输出回归支持的梯度提升实现:
- 优先选用scikit-learn官方的
HistGradientBoostingRegressor:这是scikit-learn推出的直方图优化GBDT实现,训练速度远快于传统GradientBoostingRegressor,接口和原有模型完全兼容,原生支持多输出回归,无需额外包装。使用时仅需修改导入和模型定义代码即可:from sklearn.ensemble import HistGradientBoostingRegressor model_gradientBoosting = HistGradientBoostingRegressor() # 后续fit、predict逻辑和原代码完全一致,直接传入二维Y_train即可正常训练 - 也可以根据需求替换为XGBoost、LightGBM、CatBoost等主流梯度提升框架的回归接口,这些框架均原生支持多输出回归,同时提供更丰富的调参选项和更快的训练速度。
内容的提问来源于stack exchange,提问作者PeterBe

