首次使用CatBoostRegressor遇TypeError:Singleton数组无效
解决CatBoostRegressor + GridSearchCV 出现的 TypeError 问题
嘿,我看你第一次实现CatBoostRegressor的时候遇到了这个棘手的TypeError,而且已经删掉大部分特征排查过输入集问题,还是没搞定对吧?先给你说清楚问题出在哪:
你报错的核心原因是GridSearchCV是Scikit-learn的工具,它不认识CatBoost的Pool对象。你手动把数据转成Pool传给grid_search.fit(),但Sklearn的内部函数会把这个Pool当成一个单元素数组,没办法识别成有效的数据集,所以就抛出了那个"Singleton array cannot be considered a valid collection"的错误。
而且你已经用了Pipeline和ColumnTransformer来处理数值特征,CatBoostRegressor本身又支持直接接收带分类列的DataFrame(只要你在初始化时指定了cat_features参数),完全没必要提前把数据转成Pool对象。
解决方案:去掉Pool,直接传入原始数据
把你代码里创建Pool和用Pool做fit的部分换掉,直接用df_x和df_y作为fit()的参数就行。修改后的关键代码如下:
if feature_selection == 1: models = dict() paramsrf = { 'est__max_depth':[5, 9, 18, 32], 'est__n_estimators': [10, 50, 100, 200], 'est__min_samples_split': [0.1, 1.0, 2], 'est__min_samples_leaf': [0.1, 0.5, 1] } paramscat = { 'est__depth': np.linspace(4,10,4,endpoint=True), 'est__iterations':[250,100,500,1000], 'est__learning_rate':[0.001,0.01,0.1,0.3], 'est__bagging_temperature': [0,5,10,25,50], 'est__border_count':[5,10,20,50,100] } #models['rf'] = [RandomForestRegressor(), paramsrf] models['catb'] = [CatBoostRegressor(cat_features = cat_cols, verbose = 0), paramscat] for key, value in models.items(): start_time = timeit.default_timer() scorer = ['neg_mean_squared_error', 'neg_mean_absolute_error', 'r2'] if key == 'catb': preprocessor = ColumnTransformer(transformers = [('num', MinMaxScaler(feature_range = (0,1)), num_cols)]) all_pipe = Pipeline(steps = [('prep', preprocessor), ('est', value[0])]) search_space = value[1] # 删掉原来创建pooled的代码,直接用df_x和df_y grid_search = GridSearchCV(all_pipe, search_space, cv=5, verbose=1, refit = 'neg_mean_squared_error', scoring = scorer, return_train_score = True, n_jobs = -1) grid_search.fit(df_x, df_y) # 这里直接传原始的特征和标签
为什么这样改能解决问题?
- CatBoost的Regressor实现了Scikit-learn的接口,完全可以和Pipeline、GridSearchCV无缝配合,不需要额外转成Pool。
- 你已经在
CatBoostRegressor初始化时指定了cat_features=cat_cols,模型会自动识别这些列是分类特征,不需要手动处理成Pool的格式。 - Pipeline里的ColumnTransformer已经帮你处理了数值特征的归一化,这部分逻辑会正常生效。
这样改完之后,GridSearchCV就能正常识别你的输入数据,不会再抛出那个类型错误了。
内容的提问来源于stack exchange,提问作者Ali Kılınç
相关产品推荐
相关产品推荐

