ValueError: Input contains NaN, infinity or a value too large for dtype('float64').
...
9 fits failed out of a total of 10.
The score on these train-test partitions for these parameters will be set to nan.
Below are more details about the failures:
...
ValueError: Input contains NaN, infinity or a value too large for dtype('float64').
import pandas as pd
import numpy as np
from sklearn.model_selection import cross_val_score
from sklearn.metrics import mean_squared_error
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.linear_model import LinearRegression
from feature_engine.wrappers import SklearnTransformerWrapper
from feature_engine.selection import DropFeatures
from sklearn.compose import ColumnTransformer
# Sample Data
n = 20000
df = pd.DataFrame({
"a": [["alpha", "beta", "gamma", "delta"][np.random.randint(4)] for i in range(n)],
"b": [np.random.random() * 100 for i in range(n)],
"c": [np.random.random() * 200 for i in range(n)],
"d": [["east", "west"][np.random.randint(2)] for i in range(n)],
})
def make_y(x):
add_1 = 100 if x.a in ["alpha", "beta"] else 200
add_2 = 100 if x.d in ["east"] else 300
return 2*x.b + 3*x.c + 2*add_1 + 5*add_2 + np.random.normal(10)
df["y"] = df.apply(make_y, axis=1)
# Test function for reproducing error
def do_test(df, pipeline, cv=True):
X = df.drop(columns=["y"])
y = df[["y"]]
if cv:
return cross_val_score(pipeline, X, y, scoring="neg_mean_squared_error", cv=10)
else:
pipeline.fit(X, y)
y_pred = pipeline.predict(X)
return mean_squared_error(y, y_pred)
# SklearnTransformerWrapper-based Pipeline structure where cross-validation fails
# Will run correctly if categoricals remove, or validate on entire test set (see comments below)
pipeline_new = Pipeline(steps=[
("scale_b_c", SklearnTransformerWrapper(
transformer=StandardScaler(),
variables=["b", "c"]
)
),
# Comment out this step for cross-validation to not fail
("encode_a_d", SklearnTransformerWrapper(
transformer=OneHotEncoder(drop="first", sparse=False),
variables=["a", "d"]
)
),
("cleanup", DropFeatures(["a", "d"])),
("model", LinearRegression())
])
# Old-style Pipeline with ColumnTransformer that works correctly:
pipeline_old = Pipeline(steps=[
(
"xform", ColumnTransformer([
("cat", OneHotEncoder(drop="first"), ["a", "d"]),
("num", StandardScaler(), ["b", "c"])
])
),
("model", LinearRegression())
])
# Run only this line to see new Pipeline issue (and comment out other do_test())
# Set cv to False to successfully score entire training set
do_test(df, pipeline_new, cv=True)
# Run only this line to see old Pipeline run correctly (and comment out other do_test())
#do_test(df, pipeline_old, cv=True)
Describe the bug
I am finding that when I create an sklearn Pipeline that uses the SklearnTransformerWrapper to wrap a OneHotEncoder, I get the following error when trying to run cross-validation:
If I do things the "old way" with an sklearn ColumnTransformer, I do not get the error.
I also don't get errors if I either: A) Score without cross-validation or B) Don't use the categorical features (i.e. remove the one-hot encoding).
To Reproduce
See code at end
Expected behavior
Cross-validation should run correctly without
nan.Desktop (please complete the following information):
Additional context
Code was copied from notebook since I could not attach it, sorry for any strange structure
Note: I am not doing train/test separation, in order to keep the question shorter.
Note: I posted on StackOverflow as well. I can remove the post if you think it's redundant - thanks!
Code