0%

Scikit-learn Imputation of missing values

处理缺失值常用的方法:

  • 直接移除缺失值的行
  • 以均值/中位数等方法填充
  • 以一些常数(-1/-999/etc.)代替
  • 重构,比如以通过模型来预测缺失值
  • 选择一些能处理缺失值的模型,比如XGBoost和CatBoost

Scikit-learn整理了几种方法,对应了上述的思路

Univariate feature imputation

使用SimpleImputer对缺失值进行填充,其提供meanmedianmost_frequent以及constant等方法,如果使用constant方法则需fill_value参数来指定常数

import numpy as np
from sklearn.impute import SimpleImputer

# Mean imputer
imp = SimpleImputer(missing_values=np.nan, strategy='mean')
imp.fit_transform([[1, 2], [np.nan, 3], [7, 6]])

# Constant imputer
imp = SimpleImputer(missing_values=np.nan, strategy='constant', fill_value=999)
imp.fit_transform([[1, 2], [np.nan, 3], [7, 6]])

对于categorical数据,可以试试most_frequent方法

import pandas as pd

imp = SimpleImputer(missing_values=np.nan, strategy='most_frequent')
X = pd.DataFrame([['a', 'x'], [np.nan, 'y'], ['a', 'z'], ['b', 'x']], dtype="category")
imp.fit_transform(X)

Multivariate feature imputation

使用Iterative Imputer类来填充缺失值

将每个缺失值的特征作为其他特征的函数来建模,它使用该函数的值作为估算。在每次迭代中,选择一个特征作为输出y,其他所有特征作为输入的X。然后在X和y上训练一个回归器,最后用来预测y的缺失值

从上述官方翻译来的解释,并不太好理解(其实是我不怎么理解);刚好在R语言中有个非常好用的补缺包-MissForest包,而sklearn的Iterative Imputer类则相当整合了这些常用工具(missForest,mice等等)的算法,因此可以通过MissForest的算法来帮助理解

MissForest的思路:

  • 假设有个X特征矩阵,其特征S(1,...,p)有缺失值,γ是迭代次数
  • 对矩阵中缺失值做初始更新,比如平均数填充等常用方法
  • 对X特征矩阵中特征S按照缺失值数目(缺失率)大小进行排序
  • 开始迭代,先取缺失率最小的特征S,此时将X矩阵分成4部分:S特征中有缺失部分定义为y(s)mis,S特征中无缺失部分定义为y(s)obs,除S特征以外的所有变量中对应S特征缺失索引的部分定义为X(s)mis,除S特征以外的所有变量中对应S特征无缺失索引的部分定义为X(s)obs
  • 通过RF回归算法来拟合y(s)obs和X(s)obs,然后预测X(s)mis对应的y(s)mis
  • 将上述预测值y(s)mis更新至X矩阵中,接着取第二小缺失率的特征S,循环所有特征S(有缺失值的),并将RF模型预测值填充至X矩阵中
  • 此时只是第一次迭代,接着将更新后的X矩阵跟初始X矩阵做比较,通过收敛函数的收敛至是否满足设定的阈值;如果不满足则开始第二次迭代,直至收敛值满足阈值或者迭代次数达到设定的γ

以上参考自MissForest文献(发表自Bioinformatics):MissForest—non-parametric missing value imputation for mixed-type data

文献中有个伪算法图:

MissForest

IterativeImputer可支持对个回归estimators,默认是BayesianRidge,其他参数可根据实际情况进行选择

from sklearn.experimental import enable_iterative_imputer
from sklearn.impute import IterativeImputer

imp = IterativeImputer(max_iter=10, random_state=0)
imp.fit_transform([[1, 2], [3, 6], [4, 8], [np.nan, 4]])  

此外sklearn还对不同estimators在IterativeImputer中的效果做了比较:Imputing missing values with variants of IterativeImputer,以及如何在build model前处理缺失值:Imputing missing values before building an estimator

IterativeImputer不仅支持上述文章中所提到的几个estimators,还支持Catboost(虽然Catboost本身就支持有缺失值的特征矩阵),但是LightGBM和XGBoost则不行

Nearest neighbors imputation

除了sklearn之外,还有两个常用的缺失值插补的包impytue和fancyimpute,除了简单的单变量之外,还支持多变量插补。比如fancyimpute的KNN方法

sklearn也把KNNImputer整合到inpute方法中(最新版0.22),方便在统一的框架下调用不同的补缺方法。。。。

from sklearn.impute import KNNImputer

imp = KNNImputer(n_neighbors=2, weights="uniform")
imp.fit_transform([[1, 2], [3, 6], [4, 8], [np.nan, 4]])

Marking imputed values

MissingIndicator可以用于将数据集转化为二进制矩阵(展示特征值是否有缺失);通过调节features参数可以选择只展示缺失的特征missing-only(默认)或者展示全部特征all

from sklearn.impute import MissingIndicator

indicator = MissingIndicator()
indicator.fit_transform([[np.nan,1,2], [3,5,np.nan]])
indicator = MissingIndicator(features="all")
indicator.fit_transform([[np.nan,1,2], [3,5,np.nan]])

如果想在estimators中整合MissingIndicator的结果,则可以考虑用FeatureUnion或者ColumnTransformer,以前者为例:

from sklearn.pipeline import FeatureUnion

X = [[np.nan, 2, 3], [4, np.nan, 6], [10, np.nan, 9]]
transformer = FeatureUnion(
        transformer_list=[
                ('features', SimpleImputer(strategy='mean')),
                ('indicators', MissingIndicator())])
transformer.fit_transform(X)

上述FeatureUnion的作用:

FeatureUnion把若干个transformer object组合成一个新的estimators,原先独立的transoformers 输出的样本特征向量被以end-to-end的方式拼接成为一个更大的特征向量

现在sklearn为SimpleImputerIterativeImputer提供了一个add_indicator参数(默认是Flase),就是为了达到整合MissingIndicator的目的,避免繁琐的使用FeatureUnion,如这个issues所提到的;因此简单加上这个参数就能达到上述FeatureUnion的作用,如:

X = [[np.nan, 2, 3], [4, np.nan, 6], [10, np.nan, 9]]
imp = SimpleImputer(missing_values=np.nan, strategy='mean', add_indicator=True)
imp.fit_transform(X)

参考资料:

Imputation of missing values
[特征工程]数据预处理的方法和技巧

本文出自于http://www.bioinfo-scrounger.com转载请注明出处