如何使用简单的 imputer(自定义函数)进行估算

数据挖掘 机器学习 Python scikit-学习 训练 数据插补
2022-02-27 16:55:09

我正在使用来自 sklearn 的简单输入器输入我的数据。我想测试对数据应用转换的许多不同方法。即对于逻辑回归,我想

  • 删除 nans 并替换为 mode
  • 将 +infs 替换为 max,将 -infs 替换为 min
  • 使用标准定标器。

然后使用 xgboost 我想:

  • 只需将 -infs/+infs 替换为非常大或 -ve 大的数字。

我一直在玩 sklearn 管道,我想知道如何通过管道传递自定义输入器?例如:

logistic_pipeline = Pipeline( steps = [('imputer', SimpleImputer(strategy = 'most frequent') ),
                                  ( 'std_scaler', StandardScaler() ),
                        ( 'model', LinearRegression() )] )

但是我如何将以下函数合并到其中我将训练数据(df)中的 infs 替换为该列的最大值。然后使用此最大值将其填充到测试中。我如何使用管道来做到这一点?

def replace_pos_inf(df, dftest, numeric_features):

    for col in df[numeric_features].columns:
        m = df.loc[df[col] != np.inf, col].max()
        df[col].replace(np.inf,m,inplace=True)
        dftest[col].replace(np.inf,m,inplace=True)


    for col in df[numeric_features].columns:
        mini = df.loc[df[col] != -np.inf, col].min()
        df[col].replace(-np.inf,mini,inplace=True)
        dftest[col].replace(-np.inf,mini,inplace=True)

    return df,dftest
1个回答

由于您想保存训练最小值/最大值并使用它们来替换测试集中的 inf,因此您需要一个自定义转换器。要构建强大的转换器,您应该使用 sklearn 的一些验证功能。最好在 numpy 中工作,因为正如您指出的那样,管道中的早期转换器已经将输入数据帧转换为 nparray。(你可以坚持使用数据帧,或者在你的转换器中进行转换(失去一些效率),或者确保你的转换器总是在管道中排在第一位(好吧,如果你是唯一使用你的代码的人)。)

然后,这是一个简单的版本。我选择不使用numeric_featuresas 输入;你可能最好使用 aColumnTransformer为你做那种选择。

from sklearn.utils import check_array
from sklearn.utils.validation import check_is_fitted
from sklearn.base import TransformerMixin, BaseEstimator

class ReplaceInf(TransformerMixin, BaseEstimator):
    '''Replace +-np.inf with the max/min finite values in each column.
    Attributes
    ----------
    mins_ : np.ndarray
        Per-column minimum finite values.
    maxs_ : np.ndarray
        Per-column maximum finite values.
    '''

    def fit(self, X, y=None):
        # validate and convert if possible:
        X = check_array(X, force_all_finite=False)
        # using `where=np.isfinite(X)`, nan's won't affect the min/max calculation,
        #  and using `clip` to transform will preserve nan's as well.
        self.mins_ = np.amin(X, axis=0, where=np.isfinite(X), initial=np.inf)
        self.maxs_ = np.amax(X, axis=0, where=np.isfinite(X), initial=-np.inf)
        return self

    def transform(self, X):
        X = check_array(X, force_all_finite=False)
        return np.clip(X, self.mins_, self.maxs_)