如何使管道执行插补阶段?

问题描述

我正在尝试运行基本模型,但似乎管道的插补阶段正在失败,而且我并不十分了解为什么。

这是最小的可复制代码

如果愿意,您可以找到xy的数据。最初它们在一个公共文件中,我可以轻松地链接到它,但是我对其进行了一些转换,因此我将使用编辑后的输出减少必须阅读的代码。但是,如果需要,我可以轻松链接到原始代码和数据集。

import pandas as pd
import numpy as np
from sklearn.ensemble import RandomForestClassifier,AdaBoostRegressor,AdaBoostClassifier,RandomForestRegressor
from category_encoders import CatBoostEncoder,CountEncoder,TargetEncoder,SumEncoder
from sklearn.preprocessing import OneHotEncoder,StandardScaler
from sklearn.compose import make_column_transformer
from sklearn.pipeline import make_pipeline
from sklearn.impute import SimpleImputer
import datetime as dt

x = pd.read_csv("/home/user/Python Practice/Working/Playstore/x.csv",index_col=("Unnamed: 0"))
y = pd.read_csv("/home/user/Python Practice/Working/Playstore/y.csv",index_col=("Unnamed: 0"))

# Set up Imputers
strat = ["mean","median","most_frequent","constant"]
num_imp = SimpleImputer(strategy=strat[0])
obj_imp = SimpleImputer(strategy=strat[2])

# Set up the scaler
sc = StandardScaler()

# Set up Encoders
cb = CatBoostEncoder()
oh = OneHotEncoder()

# Set up columns
obj = list(x.select_dtypes(include="object"))
num = list(x.select_dtypes(exclude="object"))
cb_col = [i for i in obj if len(x[i].unique())>30]
oh_col = [i for i in obj if len(x[i].unique())<10]

# Col Transformation
col = make_column_transformer((cb,cb_col),(obj_imp,(oh,oh_col),(num_imp,num),(sc,num))

model = AdaBoostRegressor(random_state=(0))

#Second Pipeline
run = make_pipeline((col),(model))
run.fit(x,y)
print("The score is",run.score(x,y))

模型在.fit阶段崩溃,并显示错误消息:ValueError: Input contains NaN。当我估算后,为什么要这样做呢?而我该如何解决呢?

解决方法

我正在使用pandas v1.1.3和sklearn v0.23.2。

我猜主要问题是由CatBoostEncoder引起的。它requires column y as input,因此它可能无法与make_column_transformer()一起使用,至少不能按照manual的描述进行操作。如固定代码所示,其输出格式也与其他变压器不同。

修复

首先,您的索引混乱了,必须在加载后进行修复。

x.index[10470:10475]
Out[34]: Int64Index([10470,10471,10473,10474,10475],dtype='int64')

# fix
x.reset_index(drop=True,inplace=True)
y.reset_index(drop=True,inplace=True)

第二,使OneHotEncoder输出密集数组。

oh = OneHotEncoder(sparse=False)

第三,分解管道。

# 1. Impute
x[num] = num_imp.fit_transform(x[num])
x[obj] = obj_imp.fit_transform(x[obj])
assert x.isnull().sum().sum() == 0  # make sure no missing value exists

# 2. Transform
x = pd.concat([pd.DataFrame(sc.fit_transform(x[num])),cb.fit_transform(x[cb_col],y),pd.DataFrame(oh.fit_transform(x[oh_col]))
               ],axis=1)

最后,直接训练和评估模型。形状转换可禁止显示警告。

model = AdaBoostRegressor(random_state=0)
model.fit(x.values,y.values.reshape(-1))
print("The score is",model.score(x,y.values.reshape(-1)))

结果:

The score is 0.6329093797171869

其他信息

我试图忽略第三方CatBoostEncoder,而只在所有对象列上使用OneHotEncoder

col = make_column_transformer(
    (num_imp,num),(obj_imp,obj),(sc,(oh,)

但是,这种尝试以许多我不理解的奇怪方式失败了。

  • oh失败,ValueError: Input contains NaN
  • sc失败,发生ValueError: Input contains NaN,infinity or a value too large for dtype('float64').,只有将x[num]传递到管道中,并且obj_impoh被关闭时才会发生。 >

这是我决定放弃管道的主要原因,因为管道中的变压器行为与我在固定代码中观察到的情况大不相同。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...