当前位置: 首页 > article >正文

【漫话机器学习系列】256.用 k-NN 填补缺失值

用 k-NN 填补缺失值:原理、实现与应用

在实际的数据科学项目中,我们经常会遇到数据缺失(Missing Values)的问题。缺失值如果处理不当,不仅会影响模型训练,还可能导致最终结果偏差。

今天,我们来学习一种简单而有效的方法——使用 k 最近邻(k-Nearest Neighbors,简称 k-NN)来填补缺失值

下面是本文核心示意图:


(示意图来源:Chris Albon)


1. 为什么需要处理缺失值?

在机器学习中,大多数算法都要求输入的数据是完整的,即不能存在空缺值 (NaN)。而实际中由于采集错误、设备问题、用户行为等种种原因,数据集通常会出现不同程度的缺失。

常见的缺失值处理方法有:

  • 丢弃缺失的样本或特征

  • 使用均值、中位数、众数填充

  • 使用回归、插值等高级填补技术

  • 使用基于 k-NN 的方法进行填补

k-NN 填补是一种基于相似性的填补方法,通常能取得更好的效果,因为它考虑了数据的整体分布和结构。


2. 什么是 k-NN 填补缺失值?

简单来说,k-NN 填补就是:

找到与缺失样本最相似的 k 个样本,利用它们的特征值来填补缺失项。

根据上图,填补步骤可以总结为:

  1. 确定缺失值位置
    比如有一个样本在特征1、特征2上存在数据,但特征3缺失。

  2. 计算距离
    只基于已有特征(非缺失部分)计算该样本与其他样本之间的距离。

  3. 选取最近邻
    找到距离最近的 k 个样本(通常 k 取 5~10)。

  4. 填补缺失值
    取这 k 个样本在缺失特征上的中位数或者加权平均数,作为缺失值的估计。


3. 具体案例:基于 scikit-learn 实现

使用 scikit-learn,我们可以直接使用 KNNImputer 类来完成填补。示例代码如下:

from sklearn.impute import KNNImputer
import numpy as np# 假设我们的数据矩阵中有一些缺失值
X = np.array([[1, 2, np.nan],[3, 4, 3],[5, 6, 2],[np.nan, 8, 1]])# 创建一个k-NN填补器,设置k=2
imputer = KNNImputer(n_neighbors=2)# 执行填补
X_filled = imputer.fit_transform(X)print(X_filled)

输出结果示例

[[1.  2.  2.5][3.  4.  3. ][5.  6.  2. ][4.  8.  1. ]]

可以看到,缺失值已经被合理地填补。


4. 关键细节和注意事项

  • 标准化很重要
    在 k-NN 中,距离计算受特征量纲影响很大。因此,通常需要对数据先进行标准化(如使用 StandardScalerMinMaxScaler)。

  • 选择合理的 k 值
    k 值太小,容易受噪声干扰;k 值太大,又可能引入无关样本。通常可以交叉验证或经验选择 5~10。

  • 缺失太多不适用
    如果数据中缺失比例太高,k-NN 填补可能不够可靠,此时可以考虑模型预测或直接删除缺失严重的样本/特征。

  • 计算复杂度
    k-NN 填补在大数据集上会比较慢,因为每次都要计算距离。可以考虑使用近似最近邻算法加速。


5. 应用场景

  • 客户信息表缺失部分字段

  • 医疗数据(如血液指标)存在缺失

  • 设备传感器数据偶尔掉包

  • 用户行为数据不完整

在这些场景下,使用 k-NN 填补都能取得比简单均值填补更好的效果。


6. 总结

k-NN 填补缺失值,是一种基于数据本身结构的智能填补方法,简单、直观、效果良好。
虽然计算量较大、对尺度敏感,但在中小规模数据上,特别是特征之间具有明显结构或聚类性的场景下,非常值得使用。

建议在实际使用时搭配标准化处理,并根据数据特点合理选择 k 值!


如果觉得有用,欢迎点赞、收藏、评论交流~ 

http://www.lryc.cn/news/2378998.html

相关文章:

  • React组件(一):生命周期
  • 金格iWebOffice控件在新版谷歌Chrome中不能加载了怎么办?
  • 实验6分类汇总
  • 如何通过交流沟通实现闭环思考模式不断实现自身强效赋能-250517
  • Python 3.11详细安装步骤(包含安装包)Python 3.11详细图文安装教程
  • [深度解析] 服务器内存(RAM)演进之路(2025):DDR5 vs HBM vs CXL 内存技术与选型指南
  • C语言输入函数对比解析
  • 【Java-EE进阶】SpringBoot针对某个IP限流问题
  • 一个指令,让任意 AI 快速生成思维导图
  • 随言随语(十二):盖章
  • FPGA图像处理(六)------ 图像腐蚀and图像膨胀
  • Spring三级缓存的作用与原理详解
  • LVDS系列12:Xilinx Ultrascale系可编程输入延迟(二)
  • ARM (Attention Refinement Module)
  • 国产免费工作流引擎star 6.5k,Warm-Flow升级1.7.2(新增案例和修复缺陷)
  • 前端二进制数据指南:从 ArrayBuffer 到高级流处理
  • 如何选择高性价比的 1T 服务器租用服务​
  • 一个可拖拉实现列表排序的WPF开源控件
  • AI-02a5a6.神经网络-与学习相关的技巧-批量归一化
  • SVGPlay:一次 CodeBuddy 主动构建的动画工具之旅
  • 自己手写tomcat项目
  • 2025年渗透测试面试题总结-安恒[实习]安全工程师(题目+回答)
  • 生成对抗网络(Generative Adversarial Networks ,GAN)
  • 六、磁盘划分与磁盘配额
  • 在WSL中的Ubuntu发行版上安装Anaconda、CUDA、CUDNN和TensorRT
  • 小刚说C语言刷题—1230蝴蝶结
  • 代码随想录算法训练营第60期第三十九天打卡
  • 计算机网络体系结构深度解析:从理论到实践的全面梳理
  • Qwen2.5-VL模型sft微调和使用vllm部署
  • python打卡DAY22