Laz*_*val 4 python encoding pipeline scikit-learn imputation
我正在使用 sklearn 的管道转换器实现预处理管道。我的管道包括 sklearn 的 KNNImputer 估计器,我想用它来估算数据集中的分类特征。(我的问题类似于这个线程,但它不包含我的问题的答案:How to implement KNN to impute categorical features in a sklearn pipeline)
我知道分类特征必须在插补之前编码,这就是我遇到麻烦的地方。使用标准标签/序数/onehot 编码器,当尝试使用缺失值 (np.nan) 对分类特征进行编码时,您会收到以下错误:
ValueError: Input contains NaN
Run Code Online (Sandbox Code Playgroud)
我设法通过创建一个自定义编码器来“绕过”它,我将 np.nan 替换为“Missing”:
class CustomEncoder(BaseEstimator, TransformerMixin):
def __init__(self):
self.encoder = None
def fit(self, X, y=None):
self.encoder = OrdinalEncoder()
return self.encoder.fit(X.fillna('Missing'))
def transform(self, X, y=None):
return self.encoder.transform(X.fillna('Missing'))
def fit_transform(self, X, y=None, **fit_params):
self.encoder = OrdinalEncoder()
return self.encoder.fit_transform(X.fillna('Missing'))
preprocessor = ColumnTransformer([
('categoricals', CustomEncoder(), cat_features),
('numericals', StandardScaler(), num_features)],
remainder='passthrough'
)
pipeline = Pipeline([
('preprocessing', preprocessor),
('imputing', KNNImputer(n_neighbors=5))
])
Run Code Online (Sandbox Code Playgroud)
但是,在这种情况下,我找不到一种合理的方法,然后在使用 KNNImputer 进行输入之前将编码的“缺失”值设置回 np.nan。
我已经读过我可以在此线程上使用 OneHotEncoder 转换器手动执行此操作:Scikit-learn 中 OneHotEncoder 和 KNNImpute 之间的循环循环,但同样,我想在管道中实现所有这些以自动化整个预处理阶段。
有没有人设法做到这一点?有人会推荐替代解决方案吗?使用 KNN 算法进行估算可能不值得麻烦,我应该使用简单的估算器吗?
提前感谢您的反馈!
恐怕这行不通。如果您对分类数据进行一次性编码,您的缺失值将被编码为一个新的二进制变量,而 KNNImputer 将无法处理它们,因为:
无论如何,您有几个选项可以使用 scikit-learn 来估算缺失的分类变量:
sklearn.impute.SimpleImputerusing strategy="most_frequent":这将使用每列中最频繁的值替换缺失值,无论它们是字符串还是数字数据sklearn.impute.KNNImputer有一些限制:您必须首先将分类特征转换为数字特征,同时保留NaN值(请参阅:将缺失值保留为 'NaN' 的 LabelEncoder),然后您可以使用KNNImputer仅使用最近的邻居作为替换(如果您使用不止一个邻居,它会呈现一些毫无意义的平均值)。例如: import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.impute import KNNImputer
df = pd.DataFrame({'A': ['x', np.NaN, 'z'], 'B': [1, 6, 9], 'C': [2, 1, np.NaN]})
df = df.apply(lambda series: pd.Series(
LabelEncoder().fit_transform(series[series.notnull()]),
index=series[series.notnull()].index
))
imputer = KNNImputer(n_neighbors=1)
imputer.fit_transform(df)
In:
A B C
0 x 1 2.0
1 NaN 6 1.0
2 z 9 NaN
Out:
array([[0., 0., 1.],
[0., 1., 0.],
[1., 2., 0.]])
Run Code Online (Sandbox Code Playgroud)
sklearn.impute.IterativeImputer并复制MissForest 插补器(但您必须将数字特征与分类特征分开处理)。例如: import numpy as np
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer
from sklearn.ensemble import RandomForestRegressor, RandomForestClassifier
df = pd.DataFrame({'A': ['x', np.NaN, 'z'], 'B': [1, 6, 9], 'C': [2, 1, np.NaN]})
categorical = ['A']
numerical = ['B', 'C']
df[categorical] = df[categorical].apply(lambda series: pd.Series(
LabelEncoder().fit_transform(series[series.notnull()]),
index=series[series.notnull()].index
))
print(df)
imp_num = IterativeImputer(estimator=RandomForestRegressor(),
initial_strategy='mean',
max_iter=10, random_state=0)
imp_cat = IterativeImputer(estimator=RandomForestClassifier(),
initial_strategy='most_frequent',
max_iter=10, random_state=0)
df[numerical] = imp_num.fit_transform(df[numerical])
df[categorical] = imp_cat.fit_transform(df[categorical])
print(df)
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2838 次 |
| 最近记录: |