机器学习中缺失值的 kNN 估算

数据集可能存在缺失值,这会给许多机器学习算法带来问题。

因此,在对预测任务进行建模之前,最好识别并替换输入数据中每列的缺失值。这称为缺失数据插补,或简称插补。

处理缺失数据的一种流行方法是使用模型来预测缺失值。这需要为每个具有缺失值的输入变量创建一个模型。尽管可以使用一系列不同的模型中的任何一个来预测缺失值,但 k-近邻(KNN)算法已被证明通常是有效的,通常被称为“近邻填充”。

在本教程中,您将了解如何在机器学习中使用近邻填充策略来处理缺失数据。

完成本教程后,您将了解:

  • 缺失值必须用 NaN 值标记,并可以用近邻估计值替换。
  • 如何加载带缺失值的 CSV 文件,用 NaN 值标记缺失值,并报告每列缺失值的数量和百分比。
  • 如何在评估模型时将缺失值填充为近邻模型,以及在拟合最终模型以对新数据进行预测时。

开始您的项目,阅读我的新书 数据准备机器学习,其中包含分步教程和所有示例的Python源代码文件。

让我们开始吧。

  • 2020年6月更新:更改了示例中用于预测的列。
kNN Imputation for Missing Values in Machine Learning

机器学习中缺失值的 kNN 估算
照片由 portengaround 提供,保留部分权利。

教程概述

本教程分为三个部分;它们是:

  1. k-近邻填充
  2. 马疝气数据集
  3. 使用 KNNImputer 进行近邻填充
    1. KNNImputer 数据转换
    2. KNNImputer 与模型评估
    3. KNNImputer 与不同数量的邻居
    4. 进行预测时 KNNImputer 转换

k-近邻填充

一个数据集可能包含缺失值。

这些是数据行,其中一个或多个值或该行中的列不存在。值可能完全缺失,也可能用特殊字符或值标记,例如问号“?”。

值缺失的原因可能有很多,通常取决于特定于问题域的原因,可能包括测量损坏或不可用等原因。

大多数机器学习算法需要数值输入,并且数据集中的每一行和每一列都需要存在一个值。因此,缺失值会给机器学习算法带来问题。

通常需要识别数据集中的缺失值并用数值替换它们。这称为数据填充或缺失数据填充。

… 可以进行缺失数据填充。在这种情况下,我们可以利用训练集预测变量中的信息,来估计其他预测变量的值。

— 第42页,《应用预测建模》,2013年。

一种有效的数据填充方法是使用模型来预测缺失值。为每个有缺失值的特征创建一个模型,将其他输入值作为输入。

一种流行的填充技术是 K-近邻模型。通过查找训练集中“最接近”新样本的样本,并平均这些附近的点来填充值。

— 第42页,《应用预测建模》,2013年。

如果输入变量是数值型的,则可以使用回归模型进行预测,这种情况很常见。可以使用一系列不同的模型,尽管简单的 k-近邻(KNN)模型在实验中被证明是有效的。使用 KNN 模型预测或填充缺失值被称为“近邻填充”或“KNN 填充”。

我们发现 KNNimpute 似乎为缺失值估计提供了一种更稳健和敏感的方法 […] 并且 KNNimpute 超越了常用的行平均方法(以及用零填充缺失值)。

DNA 微阵列的缺失值估计方法, 2001。

KNN 填充的配置通常涉及选择距离度量(例如欧氏距离)以及每个预测的贡献邻居数量,即 KNN 算法的 k 超参数。

现在我们熟悉了用于缺失值填充的近邻方法,让我们来看一个带有缺失值的数据集。

想开始学习数据准备吗?

立即参加我为期7天的免费电子邮件速成课程(附示例代码)。

点击注册,同时获得该课程的免费PDF电子书版本。

马疝气数据集

马疝气数据集描述了患有疝气的马匹的医学特征以及它们是存活还是死亡。

有300行和26个输入变量,一个输出变量。这是一个二元分类预测任务,涉及预测马匹存活为1,死亡为2。

在这个数据集中,我们可以选择预测许多字段。在这种情况下,我们将预测问题是否为手术(列索引23),使其成为一个二元分类问题。

该数据集中许多列存在许多缺失值,每个缺失值都用问号字符(“?”)标记。

下面提供了数据集中带有标记缺失值的行示例。

你可以在此处了解更多关于此数据集的信息:

无需下载数据集,我们将在工作示例中自动下载。

在加载的数据集中使用 Python 将缺失值标记为 NaN(非数字)是一种最佳实践。

我们可以使用 Pandas 的 read_csv() 函数加载数据集,并指定“na_values”将“?”的值加载为缺失值,用 NaN 值标记。

加载后,我们可以查看加载的数据,以确认“?”值已标记为 NaN。

然后我们可以枚举每一列,并报告该列中带有缺失值的行数。

总而言之,下面列出了加载和汇总数据集的完整示例。

运行该示例首先加载数据集并总结前五行。

我们可以看到,原来用“?”字符标记的缺失值已经被NaN值取代了。

接下来,我们可以看到数据集中所有列的列表以及缺失值的数量和百分比。

我们可以看到,有些列(例如列索引1和2)没有缺失值,而其他列(例如列索引15和21)有许多甚至大部分缺失值。

现在我们熟悉了带有缺失值的马匹疝气数据集,让我们看看如何使用近邻填充。

使用 KNNImputer 进行近邻填充

scikit-learn 机器学习库提供了 KNNImputer 类,支持近邻填充。

在本节中,我们将探讨如何有效地使用KNNImputer类。

KNNImputer 数据转换

KNNImputer是一个数据转换器,它首先根据用于估计缺失值的方法进行配置。

默认的距离度量是欧氏距离度量,它是 NaN 感知的,例如,在计算训练数据集成员之间的距离时不会包含 NaN 值。这可以通过“metric”参数设置。

邻居数量默认设置为五,可以通过“n_neighbors”参数进行配置。

最后,距离度量可以根据实例(行)之间的距离成比例加权,尽管默认情况下它设置为均匀加权,这由“weights”参数控制。

然后,将 imputer 拟合到数据集上。

然后,将拟合后的 imputer 应用于数据集,创建一个数据集的副本,其中每列的缺失值都用估计值替换。

我们可以通过在转换前后汇总数据集中缺失值的总数,来演示其在马疝气数据集上的用法并确认其有效性。

完整的示例如下所示。

运行该示例首先加载数据集并报告数据集中缺失值的总数为1,605。

转换已配置、拟合并执行,并且生成的​​新数据集没有缺失值,这证实了它的执行符合预期。

每个缺失值都已替换为模型估计的值。

KNNImputer 与模型评估

使用k折交叉验证在数据集上评估机器学习模型是一种良好的实践。

为了正确地应用近邻缺失数据填充并避免数据泄露,要求对每列计算的模型仅在训练数据集上计算,然后应用于数据集中每个折叠的训练集和测试集。

这可以通过创建建模管道来实现,其中第一步是近邻填充,第二步是模型。这可以使用 Pipeline 类 来实现。

例如,下面的 Pipeline 使用KNNImputer(默认策略),后跟随机森林模型。

我们可以使用重复的 10 折交叉验证来评估马匹疝气数据集的填充数据集和随机森林建模管道。

完整的示例如下所示。

运行该示例会正确地将数据插补应用于交叉验证过程的每个折叠。

注意:您的结果可能有所不同,这取决于算法的随机性、评估程序的随机性或数值精度的差异。请考虑运行示例几次并比较平均结果。

该管道使用三次重复的 10 折交叉验证进行评估,并报告了数据集上的平均分类准确率约为 86.2%,这是一个合理的分数。

我们如何知道使用默认的五个邻居数量对这个数据集是好的或最佳的?

答案是我们不知道。

KNNImputer 与不同数量的邻居

KNN 算法的关键超参数是k;它控制用于贡献预测的最近邻的数量。

测试k的一系列不同值是一个好习惯。

下面的示例评估模型管道,并比较从 1 到 21 的奇数k值。

运行示例使用重复交叉验证在马匹疝气数据集上评估每个k值。

注意:您的结果可能有所不同,这取决于算法的随机性、评估程序的随机性或数值精度的差异。请考虑运行示例几次并比较平均结果。

为具有每个k值的填充管道报告了平均分类准确率。

在这种情况下,我们可以看到较大的 k 值可以带来更好的模型性能,而k=1可以达到最佳性能,准确率约为 86.7%。

运行结束时,会为每组结果创建一个箱线图和须状图,以便比较结果的分布。

该图表明,当填充缺失值时,k 值没有太大差异,平均性能(绿色三角形)周围存在小幅波动。

Box and Whisker Plot of Imputation Number of Neighbors for the Horse Colic Dataset

马匹疝气数据集填充邻居数量的箱线图

进行预测时 KNNImputer 转换

我们可能希望创建一个最终的建模管道,其中包含近邻填充和随机森林算法,然后对新数据进行预测。

这可以通过定义管道并将其拟合到所有可用数据,然后调用predict()函数并将新数据作为参数传入来实现。

重要的是,新数据行必须使用 NaN 值标记任何缺失值。

完整的示例如下所示。

运行该示例会在所有可用数据上拟合建模管道。

定义了一个新的数据行,其中缺失值标记为 NaN,并进行了分类预测。

进一步阅读

如果您想深入了解,本节提供了更多关于该主题的资源。

相关教程

论文

书籍

API

数据集 (Dataset)

总结

在本教程中,您了解了如何在机器学习中使用近邻填充策略来处理缺失数据。

具体来说,你学到了:

  • 缺失值必须用 NaN 值标记,并可以用近邻估计值替换。
  • 如何加载带缺失值的 CSV 文件,用 NaN 值标记缺失值,并报告每列缺失值的数量和百分比。
  • 如何在评估模型时将缺失值填充为近邻模型,以及在拟合最终模型以对新数据进行预测时。

你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。

掌握现代数据准备!

Data Preparation for Machine Learning

在几分钟内准备好您的机器学习数据

...只需几行python代码

在我的新电子书中探索如何实现
机器学习数据准备

它提供**自学教程**,并附有关于以下内容的**完整工作代码**:
*特征选择*、*RFE*、*数据清洗*、*数据转换*、*缩放*、*降维*,以及更多...

将现代数据准备技术引入
您的机器学习项目


查看内容

52 条对机器学习中的 kNN 缺失值填充的回复

  1. Kanchan 2020年6月27日 上午2:25 #

    对于缺失值百分比大于 95% 的情况,我们可以应用 knn 填充吗?我们是否应该处理这些特征?

    • Jason Brownlee 2020年6月27日 上午5:35 #

      哎哟。

      也许,但填充的值可能不会带来太多价值。测试一下看看。

  2. jade 2020年6月27日 晚上10:05 #

    很棒的博客……
    但我们必须看看值会是什么

    • Jason Brownlee 2020年6月28日 上午5:50 #

      您必须尝试一下,找出它是否能为您的项目带来价值。

      • Roju 2020年9月16日 晚上9:30 #

        当我显式地在填充数据上训练模型(没有交叉验证)时,训练数据集的准确率达到了 1.0。这是一个很大的问题!您认为可能哪里出错了?请查看下面的代码以获取清晰的说明。

        import numpy as np
        from pandas import read_csv
        from sklearn.ensemble import RandomForestClassifier
        from sklearn.impute import KNNImputer
        from sklearn.pipeline import Pipeline

        # 加载数据集
        url = ‘https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv’

        data = read_csv(url, header=None, na_values=’?’)

        ix = [i for i in range(data.shape[1]) if i !=23]

        y, X = data.values[:, 23], data.values[:,ix]

        model = RandomForestClassifier()
        imputer = KNNImputer()

        pipeline = Pipeline(steps=[(‘i’, imputer), (‘m’, model)])

        pipeline.fit(X,y)

        print(pipeline.score(X,y))

        # 输出
        1.0

        [程序已完成]

        • Jason Brownlee 2020年9月17日 上午6:46 #

          在最佳情况下,准确率在训练集上应始终为 100%。

          忽略训练集上的性能,关注保留集上的性能。

  3. dsanz 2020年6月29日 下午6:51 #

    杰森,帖子很棒!
    我认为有一个错误列被用作“y”/预测。最后一列指的是“cp_data”(是否有病理学,根据“horse-colic.names”是无关紧要的,因为这些病例没有包含或收集病理学数据)。
    我猜预测应该是在第23列上进行的;“outcome”,值为1=存活,2=死亡或3=被安乐死。

  4. Mitra mir 2020年7月8日上午2:30 #

    嘿 Jason,我想知道KNN插补是否也可以应用于时间序列?

    • Jason Brownlee 2020年7月8日上午6:34 #

      也许吧。我猜保持性(persistence)会是一个更好的方法。

  5. Sara 2020年7月9日上午6:33 #

    你好,感谢你的精彩教程。

    我们如何仅评估KNN插补器?我的意思是,例如,如果我们想比较数据集中两个不同插补器的性能,我们该如何测试它们?

    谢谢

  6. Lily 2020年8月30日上午9:39 #

    Jason你好,这是一个很棒的教程,谢谢!
    我在对一个相对较大的数据集使用KNN插补器时遇到了一个问题。
    我尝试在一个数据集上进行测试——大约有10万行和50个特征。当我使用这种方法插补缺失值时,我遇到了内存问题。我应该分块拟合和转换(即迭代处理大约1000行)吗?我不确定这是否是解决这个问题的最佳方法。

    谢谢!

    • Jason Brownlee 2020年8月31日上午6:04 #

      听到这个消息我很难过。

      也许你可以在内存更多的机器上尝试?
      也许你可以使用你的数据集的一个较小样本来拟合插补器,然后应用它?
      也许你可以使用不同的插补技术,比如统计方法?

  7. Georgia 2020年9月22日晚上9:10 #

    Jason你好,感谢你的教程!我将此代码应用于我的训练数据集,但是测试集也包含缺失值。那么,我是否也应该为测试集创建一个KNN插补器?

    • Jason Brownlee 2020年9月23日上午6:38 #

      在训练集上拟合转换,然后将其应用于训练集和测试集。

      或者使用管道自动处理。

  8. Victor 2020年9月27日上午3:00 #

    Jason你好,感谢这篇博文。
    我的数据集形状是56K x 52,在对我的数据集应用KNN插补后,我注意到列数从52增加到了97,这可能是哪里出错了?
    我完全不知道,谢谢。

    • Jason Brownlee 2020年9月27日上午6:55 #

      我不知道,也许试着调试你的代码来找出原因。

  9. Nirmala 2020年10月8日晚上11:14 #

    Jason你好,感谢这篇博文。
    为什么你不创建一个代码来同时处理不同类型的缺失值,如均值、中位数和数据缩放技术?这对我帮助很大。
    提前感谢

  10. Steve 2020年11月1日上午8:08 #

    嗨,Jason,

    谢谢你的文章——它非常棒。有没有我可以引用的代码库?我查看了GitHub,看起来你没有任何公开的代码。

  11. garanktal 2020年12月8日晚上7:36 #

    from sklearn.impute import KNNImputer

    ImportError: cannot import name ‘KNNImputer’ from ‘sklearn.impute’ (C:\ProgramData\Anaconda3\lib\site-packages\sklearn\impute.py)

    python 3.7 失败
    如何修复

  12. Demetrios 2021年1月7日上午4:32 #

    嗨,Jason,

    感谢这篇很棒的文章/教程。

    我想知道在插补之前是否需要对数据进行缩放(因为我在其他地方看到过这种说法)?

    我在管道的开头为随机森林回归器使用此插补器。数据集,就像你的例子中的数据集一样,包含未缩放的特征。

    • Jason Brownlee 2021年1月7日上午6:22 #

      不客气。

      是的,如果在插补之前进行缩放,当变量具有不同尺度时会有所帮助。

  13. Pranav 2021年1月7日晚上11:41 #

    如何将KNNImpute应用于分类特征?

    • Jason Brownlee 2021年1月8日上午5:46 #

      也许可以对值进行序数编码,然后按正常方式应用。

      • Pranav 2021年1月8日晚上6:15 #

        嗨,Jason,

        谢谢您的回复。

        将序数编码应用于名义分类特征是否是正确的方法?

        处理分类特征缺失值的其他方法是什么?

        • Jason Brownlee 2021年1月9日上午6:40 #

          是的,你可以使用序数编码,用“统计众数”替换缺失值,然后进行独热编码或其他你喜欢的方式来开始建模。

  14. Mark Littlewood 2021年2月4日晚上7:56 #

    Jason你好,非常感谢,快速提问一下,如果你创建了一个管道,用KNN插补了缺失值,那么如何保存它(例如使用pickle),以便当你提供一个小的实时日数据文件给模型时,它能执行所有操作,特别是KNN插补。它是否存储了整个训练文件,从而能够在新数据上计算缺失值?我看到例如使用回归插补,它会创建一个可以存储的回归公式,但KNN呢?

    • Jason Brownlee 2021年2月5日上午5:37 #

      不客气。

      你可以直接pickle管道。

      是的,如果使用了knn插补,它会保存它将来需要插补的东西——例如,训练数据的kd树。

  15. Ethan 2021年2月23日上午8:38 #

    你好,感谢这个精彩的教程。我想知道是否有关于这部分内容的参考:“KNNImputer和模型评估”。

  16. Phil 2021年4月1日上午7:59 #

    HI Jason,我很喜欢你的网站!

    你有没有即将发布的关于使用其他变量对时间序列进行缺失值插补的材料?我看到一些使用神经网络的论文,例如以下,但没有实现。

    https://uwspace.uwaterloo.ca/bitstream/handle/10012/16561/Saad_Muhammad.pdf?sequence=5&isAllowed=y

    https://ieeexplore.ieee.org/abstract/document/8904638

    谢谢!

  17. Adnan Khan 2021年4月13日上午3:35 #

    KNN插补可以逐行应用吗?

  18. Ritvik Dhupkar 2021年5月24日晚上9:04 #

    嗨,Jason,
    尝试为推荐系统问题实现KNN插补。
    有没有办法将距离从欧氏距离改为余弦距离?
    谢谢,
    Ritvik

    • Jason Brownlee 2021年5月25日上午6:08 #

      是的,我相信你可以用任何你想要的距离度量来指定knn模型。

  19. Dave 2021年6月25日上午12:03 #

    嗨,Jason,

    插补分类变量中的nan的最佳方法是什么?我使用“zzz”或众数,但对此不满意。

    谢谢兄弟

    • Jason Brownlee 2021年6月25日上午6:17 #

      有许多方法可以进行插补,尝试一套方法并找出最适合你的模型和数据集的方法。

  20. Cho 2022年6月7日晚上9:52 #

    在我的情况下,运行“KNNimputer”后,列数减少了,我猜是因为删除了许多完全没有值的列。生成的列被命名为“1,2,3,...”。如何找回列名?

  21. Endrit 2022年7月6日晚上8:17 #

    嗨,Jason!

    感谢您的帖子;它非常有趣,并提供了KNN插补技术的详细解释:)

    我想就KNN和其他插补技术(例如MICE)的比较提供更多细节。具体来说,何时使用KNN优于MICE(以及为什么我们应该优先选择)?

    提前感谢!
    Endrit

  22. Dora 2023年7月3日晚上11:55 #

    嘿,我想知道你如何从这个管道中提取插补后的数据帧?谢谢

  23. Caio 2023年10月8日上午7:07 #

    嘿James,我想知道在应用KNN插补器(因为它基于欧氏距离)之前是否应该对变量进行归一化?

  24. mehrdad 2024年7月16日上午8:14 #

    你好,我需要一本书或文件来学习基于机器学习的插补方法的理论,例如KNN插补、SVM插补等等。

    • James Carmichael 2024年7月17日上午8:35 #

      Mehrdad你好…要学习基于机器学习的插补方法的理论,例如k-近邻(KNN)插补和支持向量机(SVM)插补,强烈推荐以下书籍

      ### 书籍推荐

      **《数据挖掘:概念与技术》作者:Jiawei Han, Micheline Kamber, and Jian Pei**

      这本书提供了数据挖掘的全面介绍,并包含对各种插补方法的详细讨论。虽然它涵盖了数据挖掘的广泛主题,但它也包括了缺失数据处理和插补技术的部分。

      ### 附加资源

      1. **《模式识别与机器学习》作者:Christopher M. Bishop**
      – 这本书提供了坚实的机器学习基础,并包含对各种算法的讨论,包括KNN和SVM。它也涉及数据预处理技术,其中包括插补方法。

      2. **研究论文和文章**
      – 对于更具体和高级的技术,你可以查阅Google Scholar或arXiv等平台上的研究论文。搜索“KNN imputation methods”、“SVM imputation methods”和“machine learning imputation”等术语。

      3. **在线教程和课程**
      – Coursera、edX和Udacity等网站提供机器学习课程,其中包括数据预处理和插补方法的模块。这些课程可以提供实际见解和理论知识。

      ### 在线资源

      – **Google Scholar**: 搜索“KNN imputation”和“SVM imputation”以查找学术论文。
      – **arXiv**: 使用相同的搜索词查找研究论文的预印本。

      这些资源应该能让你全面了解基于机器学习的插补方法的理论和应用。

Leave a Reply

Machine Learning Mastery 是 Guiding Tech Media 的一部分,Guiding Tech Media 是一家领先的数字媒体出版商,专注于帮助人们了解技术。访问我们的公司网站以了解更多关于我们的使命和团队的信息。