【问题标题】:How can I make my pipeline execute the imputation stage?如何让我的管道执行插补阶段?
【发布时间】:2021-01-31 21:25:27
【问题描述】:

我正在尝试运行一个基本模型,但似乎我的管道的插补阶段失败了,我真的不明白为什么。

这是最小的可复制代码

如果您愿意,可以找到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,cb_col),
                              (oh,oh_col),
                              (obj_imp,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。我估算后为什么要这样做?我该如何解决?

【问题讨论】:

  • 您的一些分类列既没有使用您的样本数据进行估算也没有转换:“类型”和“内容评级”。这是故意的吗?
  • @BillHuang 无意。感谢那。 oh_col 应该是 len(x[i].unique())&lt;10 而不是 &gt;。我会修复它。错误仍然存​​在。有什么想法吗?
  • 你有理由坚持make_column_transformermake_pipeline吗?它似乎不适用于对象列上的 Imputer。 Scaler 在管道中的行为也很奇怪,如果不使用数据管道,则不会出现 ValueError。如果没有原因,那么我想我已经解决了......

标签: python pandas scikit-learn feature-selection feature-engineering


【解决方案1】:

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

我猜主要问题是由CatBoostEncoder 引起的。它是requires column y as input,所以它可能不适用于make_column_transformer(),至少不符合manual 的描述。它的输出格式也和其他的transformer不同,如固定代码所示。

修复

首先,您的索引搞砸了,必须在加载后修复。

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, num),
    (oh, obj),
)

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

  • oh 失败,ValueError: Input contains NaN
  • sc failed with ValueError: Input contains NaN, infinity or a value too large for dtype('float64'). 当只有 x[num] 被传递到管道中,加上 obj_impoh 被关闭时,会发生这种情况。

这是我决定放弃管道的主要原因,因为管道中转换器的行为与我在固定代码中观察到的有很大差异。

【讨论】:

  • 谢谢。你是一颗宝石。这里已经很晚了,所以我无法尝试您的修复,但我会在明天首先尝试并告诉您结果。再次感谢。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-05
  • 2018-01-28
  • 2021-03-25
  • 2014-03-29
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多