基于树的插补

R 中的缺失值填补处理

Michal Oleszak

Machine Learning Engineer

基于树的插补方法

用机器学习模型预测缺失值!

  • 非参数方法:不对变量关系作假设。
  • 能捕捉复杂的非线性模式。
  • 相比简单统计模型,常有更好的预测表现。

本课使用:missForest 包,基于 randomForest

R 中的缺失值填补处理

决策树

一张决策树示意图,展示示例模型如何决策。模型基于不同的身高与体重组合,分配不同的糖尿病概率。

R 中的缺失值填补处理

随机森林

一张展示随机森林工作原理的示意图。原始数据生成三个装袋数据集并随机选取列子集。分别拟合决策树,最后聚合各树的结果。

R 中的缺失值填补处理

missForest 算法

  1. 先用均值插补对缺失值做初始猜测。
  2. 按缺失比例从低到高对变量排序。
  3. 对每个变量 x
    • x 的观测部分(其他变量作自变量)拟合随机森林。
    • 用其预测 x 的缺失部分。
  4. 重复第 3 步,直到插补结果基本不再变化。
R 中的缺失值填补处理

missForest 实践

nhanes %>% is.na() %>% colSums()
Age     Gender     Weight     Height   Diabetes    TotChol      Pulse PhysActive 
  0          0          9          8          1         85         32         26
library(missForest)
imp_res <- missForest(nhanes)
nhanes_imp  <- imp_res$ximp
nhanes_imp %>% is.na() %>% colSums()
Age     Gender     Weight     Height   Diabetes    TotChol      Pulse PhysActive 
  0          0          0          0          0          0          0          0
R 中的缺失值填补处理

插补误差

missForest() 提供袋外(OOB)插补误差估计:

  • 连续变量:标准化均方根误差(NRMSE)。
  • 分类变量:误分类占比(PFC)。

两者中,值越接近 0 表示效果越好,接近 1 表示较差。

imp_res <- missForest(nhanes)
imp_res$OOBerror
      NRMSE         PFC 
0.147687025 0.003676471
R 中的缺失值填补处理

插补误差

missForest() 提供袋外(OOB)插补误差估计:

  • 连续变量:标准化均方根误差(NRMSE)。
  • 分类变量:误分类占比(PFC)。

两者中,值越接近 0 表示效果越好,接近 1 表示较差。

imp_res <- missForest(nhanes, variablewise = TRUE)
imp_res$OOBerror
    MSE       PFC       MSE       MSE       PFC       MSE       MSE       MSE 
0.00000   0.00000 285.79563  40.42142   0.00735   0.53444 129.03609   0.17576
R 中的缺失值填补处理

速度-精度权衡

训练多个随机森林可能耗时较长。

思路:牺牲少量精度,缩小森林规模以减少计算时间。

  • 减少每个森林的树数(ntree 参数)。
  • 减少用于分裂的变量数(mtry 参数)。

对计算时间的影响不同:

  • 降低 ntree 呈线性加速。
  • 降低 mtry 在变量很多时加速更明显。
R 中的缺失值填补处理

实践中的速度-精度权衡

默认设置:

start_time <- Sys.time()
imp_res <- missForest(nhanes)
end_time <- Sys.time()
print(imp_res$OOBerror)
print(end_time - start_time)
      NRMSE         PFC 
0.147687025 0.003676471
Time difference of 5.496582 secs

缩小森林:

start_time <- Sys.time()
imp_res <- missForest(nhanes,
                      ntree = 10,
                      mtry = 2)
end_time <- Sys.time()
print(imp_res$OOBerror)
print(end_time - start_time)
      NRMSE         PFC 
0.162420139 0.007425743
Time difference of 0.516367 secs
R 中的缺失值填补处理

Passons à la pratique !

R 中的缺失值填补处理

Preparing Video For Download...