在管道中堆叠输入器
Stacking up imputers in a pipeline
我有一个关于在管道中堆叠多个 sklearn SimpleImputers 的问题:
import numpy as np
import pandas as pd
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
pipeline = Pipeline([
('si1', SimpleImputer(missing_values = np.nan,
strategy='constant',
fill_value=-1)),
('si2', SimpleImputer(missing_values = None,
strategy='constant',
fill_value=-1))
])
train = pd.DataFrame({'f1': [True, 1, 0], 'f2': [None,None,None]})
test1 = pd.DataFrame({'f1': [0, False, 0], 'f2': [np.nan, np.nan, np.nan]})
test2 = pd.DataFrame({'f1': [0, 0, 0], 'f2': [np.nan, np.nan, np.nan]})
pipeline.fit_transform(train)
pipeline.transform(test1)
pipeline.transform(test2)
该代码对于转换 test1(包含一个布尔值)工作正常,但对于 test2 失败:
ValueError: 'X' and 'missing_values' types are expected to be both
numerical. Got X.dtype=float64 and type(missing_values)=<class
'NoneType'>.
显然,在存在字符串或布尔值的情况下,转换工作正常,但在只有数值时会失败。
另一个奇怪的行为是当我在管道内切换输入器的顺序时:
pipeline = Pipeline([
('si2', SimpleImputer(missing_values = None,
strategy='constant',
fill_value=-1)),
('si1', SimpleImputer(missing_values = np.nan,
strategy='constant',
fill_value=-1))
])
在这种情况下,测试 1 和测试 2 的转换失败,分别出现以下错误:
ValueError: Input contains NaN
ValueError: Input contains NaN, infinity or a value too large for
dtype('float64').
我知道使用 pandas.DataFrame.replace 函数可以轻松完成这些类型的转换。但我对这种行为感到困惑,并感谢对每种情况下发生的事情的解释。
1. 第一个问题 - SimpleImputer 在满足以下条件时引发 ValueError (see documentation):
X.dtype.kind in ("f", "i", "u") and not isinstance(missing_values, numbers.Real)
供参考:isinstance(None, numbers.Real)
returns False
和 isinstance(np.nan, numbers.Real)
returns True
.
您管道中的输入器 'si1' 始终工作正常,因为 not isinstance(np.nan, numbers.Real)
始终是 False
并且整个条件是 False
.
Imputer 'si2' 是错误的原因:not isinstance(None, numbers.Real)
是 True
并且一切都取决于您传递给 SimpleImputer 的对象的数据类型。对于test1,它的dtype.kind是'o',但是对于test2,它的dtype.kind是'f'。因此,对于 test1,错误条件为 False,但对于 test2,错误条件为 True。
我不确定这种情况背后的意图是什么。可能的解决方法是单独使用 SimpleImputer 而不是将它们堆叠在管道中,并在将第一个 SimpleImputer 的结果传递给第二个之前更改 dtype。
2. 第二个问题 - 如果要传递给 SimpleImputer 的数组包含 np.nans,SimlpeImputer 需要 np.nan 作为 missing_value .否则会产生错误(see documentation).
我们只考虑test1,同样适用于test2。
a)考虑顺序:
pipeline = Pipeline([
('si1', SimpleImputer(missing_values = np.nan,
strategy='constant',
fill_value=-1)),
('si2', SimpleImputer(missing_values = None,
strategy='constant',
fill_value=-1))
])
当 test1 传递给 'si1' 时,它估算 np.nans,结果是
array([[0, -1],
[False, -1],
[0, -1]], dtype=object)
然后把这个数组传给'si2',结果就是
array([[0, -1],
[False, -1],
[0, -1]], dtype=object)
一切都很好。
b)现在考虑倒序:
pipeline = Pipeline([
('si2', SimpleImputer(missing_values = None,
strategy='constant',
fill_value=-1)),
('si1', SimpleImputer(missing_values = np.nan,
strategy='constant',
fill_value=-1))
])
test1 包括 np.nans,但 'si2' 不归因 np.nans。正如预期的那样,这将产生 ValueError。
我有一个关于在管道中堆叠多个 sklearn SimpleImputers 的问题:
import numpy as np
import pandas as pd
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
pipeline = Pipeline([
('si1', SimpleImputer(missing_values = np.nan,
strategy='constant',
fill_value=-1)),
('si2', SimpleImputer(missing_values = None,
strategy='constant',
fill_value=-1))
])
train = pd.DataFrame({'f1': [True, 1, 0], 'f2': [None,None,None]})
test1 = pd.DataFrame({'f1': [0, False, 0], 'f2': [np.nan, np.nan, np.nan]})
test2 = pd.DataFrame({'f1': [0, 0, 0], 'f2': [np.nan, np.nan, np.nan]})
pipeline.fit_transform(train)
pipeline.transform(test1)
pipeline.transform(test2)
该代码对于转换 test1(包含一个布尔值)工作正常,但对于 test2 失败:
ValueError: 'X' and 'missing_values' types are expected to be both numerical. Got X.dtype=float64 and type(missing_values)=<class 'NoneType'>.
显然,在存在字符串或布尔值的情况下,转换工作正常,但在只有数值时会失败。
另一个奇怪的行为是当我在管道内切换输入器的顺序时:
pipeline = Pipeline([
('si2', SimpleImputer(missing_values = None,
strategy='constant',
fill_value=-1)),
('si1', SimpleImputer(missing_values = np.nan,
strategy='constant',
fill_value=-1))
])
在这种情况下,测试 1 和测试 2 的转换失败,分别出现以下错误:
ValueError: Input contains NaN
ValueError: Input contains NaN, infinity or a value too large for dtype('float64').
我知道使用 pandas.DataFrame.replace 函数可以轻松完成这些类型的转换。但我对这种行为感到困惑,并感谢对每种情况下发生的事情的解释。
1. 第一个问题 - SimpleImputer 在满足以下条件时引发 ValueError (see documentation):
X.dtype.kind in ("f", "i", "u") and not isinstance(missing_values, numbers.Real)
供参考:isinstance(None, numbers.Real)
returns False
和 isinstance(np.nan, numbers.Real)
returns True
.
您管道中的输入器 'si1' 始终工作正常,因为 not isinstance(np.nan, numbers.Real)
始终是 False
并且整个条件是 False
.
Imputer 'si2' 是错误的原因:not isinstance(None, numbers.Real)
是 True
并且一切都取决于您传递给 SimpleImputer 的对象的数据类型。对于test1,它的dtype.kind是'o',但是对于test2,它的dtype.kind是'f'。因此,对于 test1,错误条件为 False,但对于 test2,错误条件为 True。
我不确定这种情况背后的意图是什么。可能的解决方法是单独使用 SimpleImputer 而不是将它们堆叠在管道中,并在将第一个 SimpleImputer 的结果传递给第二个之前更改 dtype。
2. 第二个问题 - 如果要传递给 SimpleImputer 的数组包含 np.nans,SimlpeImputer 需要 np.nan 作为 missing_value .否则会产生错误(see documentation).
我们只考虑test1,同样适用于test2。
a)考虑顺序:
pipeline = Pipeline([
('si1', SimpleImputer(missing_values = np.nan,
strategy='constant',
fill_value=-1)),
('si2', SimpleImputer(missing_values = None,
strategy='constant',
fill_value=-1))
])
当 test1 传递给 'si1' 时,它估算 np.nans,结果是
array([[0, -1],
[False, -1],
[0, -1]], dtype=object)
然后把这个数组传给'si2',结果就是
array([[0, -1],
[False, -1],
[0, -1]], dtype=object)
一切都很好。
b)现在考虑倒序:
pipeline = Pipeline([
('si2', SimpleImputer(missing_values = None,
strategy='constant',
fill_value=-1)),
('si1', SimpleImputer(missing_values = np.nan,
strategy='constant',
fill_value=-1))
])
test1 包括 np.nans,但 'si2' 不归因 np.nans。正如预期的那样,这将产生 ValueError。