使用预测模型估算缺失值

Posted

技术标签:

【中文标题】使用预测模型估算缺失值【英文标题】:imputing missing values using a predictive model 【发布时间】:2017-01-12 04:58:16 【问题描述】:

我正在尝试在 Python 中估算缺失值,而 sklearn 似乎没有超出平均值(平均值、中位数或众数)估算的方法。 Orange imputation model 似乎提供了一个可行的选择。但是,Orange.data.Table 似乎无法识别np.nan,或者以某种方式估算失败。

import Orange
import numpy as np

tmp = np.array([[1, 2, np.nan, 5, 8, np.nan], [40, 4, 8, 1, 0.2, 9]])
data = Orange.data.Table(tmp)
imputer = Orange.feature.imputation.ModelConstructor()
imputer.learner_continuous = Orange.classification.tree.TreeLearner(min_subset=20)
imputer = imputer(data )
impdata = imputer(data)
for i in range(0, len(tmp)):
    print impdata[i]

输出是

[1.000, 2.000, 1.#QO, 5.000, 8.000, 1.#QO]
[40.000, 4.000, 8.000, 1.000, 0.200, 9.000]

知道我错过了什么吗?谢谢!

【问题讨论】:

您是否尝试将np.nan 替换为None 当我尝试None 时,我得到了这个TypeError: invalid arguments for constructor (domain or examples or both expected) 【参考方案1】:

问题似乎在于 Orange 中的缺失值表示为 ?~。奇怪的是,Orange.data.Table(numpy.ndarray) 构造函数并没有推断出numpy.nan 应该转换为?~,而是将它们转换为1.#QO。下面的自定义函数pandas_to_orange() 解决了这个问题。

import Orange
import numpy as np
import pandas as pd

from collections import OrderedDict

# Adapted from https://github.com/biolab/orange3/issues/68

def construct_domain(df):
    columns = OrderedDict(df.dtypes)

    def create_variable(col):
        if col[1].__str__().startswith('float'):
            return Orange.feature.Continuous(col[0])
        if col[1].__str__().startswith('int') and len(df[col[0]].unique()) > 50:
            return Orange.feature.Continuous(col[0])
        if col[1].__str__().startswith('date'):
            df[col[0]] = df[col[0]].values.astype(np.str)
        if col[1].__str__() == 'object':
            df[col[0]] = df[col[0]].astype(type(""))
        return Orange.feature.Discrete(col[0], values = df[col[0]].unique().tolist())
    return Orange.data.Domain(list(map(create_variable, columns.items())))

def pandas_to_orange(df):
    domain = construct_domain(df)
    df[pd.isnull(df)]='?'
    return Orange.data.Table(Orange.data.Domain(domain), df.values.tolist())

df = pd.DataFrame('col1':[1, 2, np.nan, 4, 5, 6, 7, 8, 9, np.nan, 11], 
                    'col2': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110.]) 

tmp = pandas_to_orange(df)
for i in range(0, len(tmp)):
    print tmp[i]

输出是:

[1.000, 10.000]
[2.000, 20.000]
[?, 30.000]
[4.000, 40.000]
[5.000, 50.000]
[6.000, 60.000]
[7.000, 70.000]
[8.000, 80.000]
[9.000, 90.000]
[?, 100.000]
[11.000, 110.000]

我想正确编码缺失值的原因是我可以使用 Orange 插补库。然而,库中的预测树模型似乎只做简单的均值插补。具体来说,它为所有缺失值估算相同的值。

imputer = Orange.feature.imputation.ModelConstructor()
imputer.learner_continuous = Orange.classification.tree.TreeLearner(min_subset=20)
imputer = imputer(tmp )
impdata = imputer(tmp)
for i in range(0, len(tmp)):
    print impdata[i]

这是输出:

[1.000, 10.000]
[2.000, 20.000]
[5.889, 30.000]
[4.000, 40.000]
[5.000, 50.000]
[6.000, 60.000]
[7.000, 70.000]
[8.000, 80.000]
[9.000, 90.000]
[5.889, 100.000]
[11.000, 110.000]

我一直在寻找可以在完整案例上拟合模型的东西,比如 kNN,并使用拟合模型来预测缺失的案例。 fancyimpute (a Python 3 package) 会这样做,但会在我的 300K+ 输入上抛出 MemoryError

from fancyimpute import KNN

df = pd.DataFrame('col1':[1, 2, np.nan, 4, 5, 6, 7, 8, 9, np.nan, 11], 
                    'col2': [10, 20, 30, 40, 50, 60, 70, 80, 90, 100, 110.]) 

X_filled_knn = KNN(k=3).complete(df)
X_filled_knn

输出是:

array([[   1.        ,   10.        ],
       [   2.        ,   20.        ],
       [   2.77777784,   30.        ],
       [   4.        ,   40.        ],
       [   5.        ,   50.        ],
       [   6.        ,   60.        ],
       [   7.        ,   70.        ],
       [   8.        ,   80.        ],
       [   9.        ,   90.        ],
       [   9.77777798,  100.        ],
       [  11.        ,  110.        ]])

我可能会找到一种解决方法或将数据集拆分为多个块(不理想)。

【讨论】:

我想知道您是否遇到过任何解决 fancyimpute MemoryError 的方法?【参考方案2】:

在 Orange v2 中,您可以将 numpy 掩码数组传递给 Orange.data.Table 构造函数。修改你的例子:

import Orange
import numpy as np

tmp = np.array([[1, 2, np.nan, 5, 8, np.nan], [40, 4, 8, 1, 0.2, 9]])
tmp_masked = np.ma.masked_array(tmp, mask=np.isnan(tmp))
data = Orange.data.Table(tmp_masked)
imputer = Orange.feature.imputation.ModelConstructor()
imputer.learner_continuous = Orange.classification.tree.TreeLearner(min_subset=20)
imputer = imputer(data )
impdata = imputer(data)
for i in range(0, len(tmp)):
    print impdata[i]

【讨论】:

以上是关于使用预测模型估算缺失值的主要内容,如果未能解决你的问题,请参考以下文章

机器学习数据预处理之缺失值:预测填充(回归模型填充分类模型填充)

集成学习模型(xgboostlightgbmcatboost)进行回归预测构建实战:异常数据处理缺失值处理数据重采样resample独热编码预测特征检查特征可视化预测结构可视化模型

拓端tecdat|R语言编程指导用线性模型进行臭氧预测: 加权泊松回归,普通最小二乘,加权负二项式模型,多重插补缺失值

预测句子中的缺失词 - 自然语言处理模型 [关闭]

ML 模型无法估算值

R语言缺失值的处理——回归预测法