为什么-MissForest-在预测任务中失败-你需要牢记的关键局限性

为什么 MissForest 在预测任务中失败:你需要牢记的关键局限性

towardsdatascience.com/why-missforest-fails-in-prediction-tasks-a-key-limitation-you-need-to-know/

本文的目标是解释,在预测设置中,插补必须始终在训练集保存的参数或模型上估计。然后,应将这些参数或模型不变地应用于测试、超时或应用数据,以避免数据泄露并确保对泛化性能的无偏评估。

我想感谢所有花时间阅读并参与我的文章的人。你们的支持和反馈非常受重视。

在实践中,大多数现实世界的数据集都包含缺失值,这使得缺失数据成为统计建模中最常见的挑战之一。如果处理不当,可能会导致系数估计偏差、统计功效降低,并最终得出错误的结论(Van Buuren,2018)。在预测建模中,通过进行完全案例分析或排除具有缺失值的预测变量来忽略缺失数据,可能会限制模型的适用性,并导致偏差或次优性能。

三种缺失数据机制

为了解决这个问题,统计学家将缺失数据分为三种机制,这些机制描述了值缺失的方式和原因。MCAR(完全随机缺失)指的是缺失完全随机发生,并且与观测变量和未观测变量都无关的情况。MAR(随机缺失)意味着缺失的概率取决于观测变量,但不取决于缺失值本身。MNAR(非随机缺失)描述了最复杂的情况,其中缺失的概率取决于未观测值本身。

经典方法及其处理缺失数据的局限性

在 MAR 假设下,可以使用观测变量中包含的信息来预测缺失值。基于这一想法的经典方法包括基于回归的插补、k-最近邻(kNN)插补以及通过链式方程进行的多重插补(MICE)。这些方法被认为是多元的,因为它们明确地将插补条件建立在观测变量上。这些方法明确地将插补条件建立在观测数据上,但有一个显著的局限性:它们处理混合数据库(连续 + 分类)不佳,并且难以捕捉非线性关系和复杂交互。

在 R 中实现的 MissForest 的兴起

正是为了克服这些限制,MissForest(Stekhoven & Bühlmann,2012)已经确立了自己作为基准方法的地位。基于随机森林,MissForest 可以捕捉变量之间的非线性关系和复杂交互,通常优于传统的插补技术。然而,当在一个需要可泛化建模过程的项目上工作时——具有适当的训练/测试分割和超时验证——我们遇到了一个重大限制。missForest包的 R 实现一旦拟合了插补模型参数就不会存储。

MissForest 在预测设置中的关键局限性

这创造了一个实际挑战:不可能在训练集上训练插补模型,然后将完全相同的参数应用到测试集上。这种限制在模型评估过程中引入了信息泄露的风险,或者降低了插补的质量和一致性。

现有解决方案及其风险

在寻找一种允许在预测建模设置中一致插补的替代解决方案时,我们问自己一个简单但关键的问题:

我们如何以与在训练数据上学习到的插补完全一致的方式插补测试数据?

探讨这个问题引导我们讨论CrossValidated,在那里另一位用户遇到了完全相同的问题并询问:

“如何在 R 中使用 missForest 进行测试数据插补?”

提出了两种主要解决方案来克服这一限制。第一种是在运行插补之前合并训练集和测试集。这种方法通常可以提高插补的质量,因为算法有更多的数据可以学习,但它引入了数据泄露,因为测试集影响了插补模型。第二种方法是从训练集独立地插补测试集,这防止了信息泄露,但迫使算法仅使用测试数据构建一个全新的插补模型,而测试数据通常要小得多。这可能导致插补结果不稳定,并可能降低预测性能。

即使是著名的教程李安·摩根也得出类似的解决方案。他提出的解决方案包括插补训练集,拟合预测模型,然后合并训练集和测试集进行最终插补步骤:

# 1) Impute the training set
imp_train_X <- missForest(train_X)$ximp

# 2) Build the predictive model
rf <- randomForest(x = imp_train_X, y = train$creditability)

# 3) Combine train and test, then re-impute
train_test_X <- rbind(test_X, imp_train_X)
imp_test_X <- missForest(train_test_X)$ximp[1:nrow(test_X), ] 

尽管这种方法通常可以提高插补质量,但它与第 1 种方法具有相同的弱点:测试数据间接参与了学习过程,这可能会夸大模型性能指标,并导致对泛化的过度乐观估计。

这些例子突出了一个基本困境:

  • 我们如何在不偏倚模型评估的情况下插补缺失值?

  • 我们如何确保应用于测试集的插补值与在训练集上学习到的值保持一致?

研究问题和动机

这些问题促使我们探索一种更稳健的解决方案,该方案能够保持泛化能力,避免数据泄露,并产生适合预测建模管道的稳定插补值。

本文分为四个主要部分:

  • 第一部分介绍了识别和描述缺失值的过程,包括如何检测、量化和描述它们。

  • 第二部分讨论了 MCAR(完全随机缺失)机制,并介绍了在此假设下处理缺失数据的方法。

  • 第三部分专注于 MAR(缺失随机)机制,概述了适当的插补策略,并解答了关键问题:为什么 R 中的 MissForest 实现预测设置失败?

  • 第四部分探讨了 MNAR(缺失非随机)机制,并探索了在机制依赖于未观察到的值本身时处理缺失数据的方法。

1. 缺失值的识别与特征描述

此步骤至关重要,应与所有利益相关者(包括模型开发者、领域专家和模型的未来用户)密切合作进行。目标是识别所有缺失值并将它们标记出来。

在 Python 中,尤其是在使用PandasNumPyScikit-Learn等库时,缺失值表示为 NaN。标记为 NaN 的值在许多操作(如 sum()count())中被忽略。您可以使用 Pandas DataFrame 中相关列的 replace() 函数标记缺失值。

一旦标记了缺失值,下一步就是评估每个变量的分布。可以使用 isnull() 函数将所有 NaN 值标记为 True,并结合 sum() 函数来计算每列的缺失值数量。

理解缺失值的分布至关重要。有了这些信息,利益相关者可以评估缺失模式的合理性。它还允许您根据每个变量的性质定义可接受的缺失阈值。例如,您可能决定对于连续变量,最多 10%的缺失值是可以接受的,而分类变量的阈值应保持在 0%。

在选择建模的相关变量后,包括那些对于预测重要的包含缺失值的变量,将数据集分为三个样本是至关重要的:

  • 训练集用于估计参数和训练模型,

  • 测试集用于评估模型在未见数据上的性能,

  • 离线集(OOT)用于验证模型的时序稳健性。

这种划分应执行以保持每个子样本的统计代表性——例如,如果目标变量不平衡,则使用分层抽样。

缺失值的分析应仅在训练集上进行:

  • 使用统计测试确定它们的机制(MCAR、MAR、MNAR),

  • 选择合适的插补方法,

  • 在训练集上训练缺失值插补模型。

在此步骤中获得的插补参数和模型必须直接应用于测试集和 Out-of-Time 集。这一步骤对于避免信息泄露并确保正确评估模型的泛化性能至关重要。

在下一节中,我们将详细检查 MCAR 机制,并介绍最适合此类缺失数据的插补方法。

2. 理解 MCAR 并选择合适的插补方法

简而言之,MCAR(完全随机缺失)描述了一种情况,其中数据值缺失的事实与该值本身或数据集中的任何其他变量完全无关。从数学的角度来看,这意味着数据点缺失的概率不依赖于变量的值也不依赖于任何其他变量的值:缺失是完全随机的。

在正式定义 MCAR 机制之前,让我们介绍本节和整篇文章中将使用的符号:

  • 考虑一个独立同分布的 n 个观测值的样本:

y[i] = (y[i1], . . ., y[ip])^T, i = 1, 2, . . ., n

其中 p 是具有缺失值的变量的数量,n 是样本大小。

  • YR^(nxp)表示可能包含缺失值的变量。这是我们希望进行插补的集合。

  • 我们将Y的观测值和缺失值分别表示为Y[o]Y[m]

  • XR^(nxq)表示完全观测到的变量,这意味着它们不包含缺失值。

  • 为了指示y[i]的哪些组成部分是观测到的或缺失的,我们定义指示向量:

r[i] = (r[i1], . . ., r[ip])^T, i = 1, 2, . . ., n

其中r[ik] = 1 如果y[ik]是观测到的,否则为 0。

  • 将这些向量堆叠得到存在/不存在指标的全矩阵:

R = (r[1], . . ., r[n])^T

然后定义MCAR 假设为:

Pr(R|Y[m] ,Y[o], X) = Pr(R). (1)

这意味着缺失的指标与缺失数据 Ym 和观测数据Y[o]都完全独立。注意,这里的 R 也与协变量X独立。在介绍在 MCAR 假设下处理缺失值的方法之前,我们首先将介绍一些简单的技术来评估 MCAR 假设是否可能成立。

2.1 评估 MCAR 假设

在本节中,我们将模拟一个在 MCAR 假设下具有 10,000 个观察值和四个变量的数据集:

  • 一个包含 20% 缺失值的连续变量和一个有两个水平(0 和 1)的分类变量,包含 10% 的缺失值。

  • 一个完全观察到的连续变量和一个分类变量,没有缺失值。

  • 最后,一个名为 target二进制目标变量,取值为 0 和 1。

import numpy as np
import pandas as pd

# --- Reproducibility ---
np.random.seed(42)

# --- Parameters ---
n = 10000

# --- Utility Functions ---
def generate_continuous(mean, std, size, missing_rate=0.0):
    """Generate a continuous variable with optional MCAR missingness."""
    values = np.random.normal(loc=mean, scale=std, size=size)
    if missing_rate > 0:
        mask = np.random.rand(size) < missing_rate
        values[mask] = np.nan
    return values

def generate_categorical(levels, probs, size, missing_rate=0.0):
    """Generate a categorical variable with optional MCAR missingness."""
    values = np.random.choice(levels, size=size, p=probs).astype(float)
    if missing_rate > 0:
        mask = np.random.rand(size) < missing_rate
        values[mask] = np.nan
    return values

# --- Variable Generation ---
variables = {
    "cont_mcar": generate_continuous(mean=100, std=20, size=n, missing_rate=0.20),
    "cat_mcar": generate_categorical(levels=[0, 1], probs=[0.7, 0.3], size=n, missing_rate=0.10),
    "cont_full": generate_continuous(mean=50, std=10, size=n),
    "cat_full": generate_categorical(levels=[0, 1], probs=[0.6, 0.4], size=n),
    "target": np.random.choice([0, 1], size=n, p=[0.5, 0.5])
}

# --- Build DataFrame ---
df = pd.DataFrame(variables)

# --- Display Summary ---
print(df.head())
print("\nMissing value counts:")
print(df.isnull().sum())

在执行任何分析之前,将数据集分为两部分:训练集和测试集是至关重要的。

2.1.1 准备分析 MCAR 的训练和测试数据

在确保代表性的同时,将数据集分为训练集和测试集是至关重要的。这保证了模型和插补方法仅在训练集上学习,然后在测试集上评估。这样做可以防止数据泄露,并提供对模型泛化到未见数据能力的无偏估计。

from sklearn.model_selection import train_test_split
import pandas as pd

def stratified_split(df, strat_vars, test_size=0.3, random_state=None):
    """
    Split a DataFrame into train and test sets with stratification
    based on one or multiple variables.

    Parameters
    ----------
    df : pandas.DataFrame
        The input dataset.
    strat_vars : list or str
        Column name(s) used for stratification.
    test_size : float, default=0.3
        Proportion of the dataset to include in the test split.
    random_state : int, optional
        Random seed for reproducibility.

    Returns
    -------
    train_df : pandas.DataFrame
        Training set.
    test_df : pandas.DataFrame
        Test set.
    """
    # Ensure strat_vars is a list
    if isinstance(strat_vars, str):
        strat_vars = [strat_vars]

    # Create a combined stratification key
    strat_key = df[strat_vars].astype(str).fillna("MISSING").agg("_".join, axis=1)

    # Perform stratified split
    train_df, test_df = train_test_split(
        df,
        test_size=test_size,
        stratify=strat_key,
        random_state=random_state
    )

    return train_df, test_df

# --- Application ---
# Stratification sur cat_mcar, cat_full et target
train_df, test_df = stratified_split(df, strat_vars=["cat_mcar", "cat_full", "target"], test_size=0.3, random_state=42)

print(f"Train size: {train_df.shape[0]}  ({len(train_df)/len(df):.1%})")
print(f"Test size:  {test_df.shape[0]}  ({len(test_df)/len(df):.1%})")

2.1.1 对具有缺失值的连续变量分析 MCAR 假设

第一步是创建一个二进制指示器 R(其中 1 表示观察到的值,0 表示缺失值),并比较两组(观察值与缺失值)中 Yo、Ym 和 X 的分布。

让我们以变量 cont_mcar 为例说明此过程。我们将比较 cont_fullcont_mcar 缺失和观察到的观察值之间的分布,使用箱线图和 Kolmogorov–Smirnov 测试。然后,我们将对分类变量 cat_full 执行类似的分析,使用条形图和卡方测试比较两组的比例。

import matplotlib.pyplot as plt
import seaborn as sns

# --- Step 1: Train/Test Split with Stratification ---
train_df, test_df = stratified_split(
    df,
    strat_vars=["cat_mcar", "cat_full", "target"],
    test_size=0.3,
    random_state=42
)

# --- Step 2: Create the R indicator on the training set ---
train_df = train_df.copy()
train_df["R_cont_mcar"] = np.where(train_df["cont_mcar"].isnull(), 0, 1)

# --- Step 3: Prepare the data for comparison ---
df_obs = pd.DataFrame({
    "cont_full": train_df.loc[train_df["R_cont_mcar"] == 1, "cont_full"],
    "Group": "Observed (R=1)"
})

df_miss = pd.DataFrame({
    "cont_full": train_df.loc[train_df["R_cont_mcar"] == 0, "cont_full"],
    "Group": "Missing (R=0)"
})

df_all = pd.concat([df_obs, df_miss])

# --- Step 4: KS Test before plotting ---
from scipy.stats import ks_2samp
stat, p_value = ks_2samp(
    train_df.loc[train_df["R_cont_mcar"] == 1, "cont_full"],
    train_df.loc[train_df["R_cont_mcar"] == 0, "cont_full"]
)

# --- Step 5: Visualization with KS result ---
plt.figure(figsize=(8, 6))
sns.boxplot(
    x="Group", 
    y="cont_full", 
    data=df_all,
    palette="Set2",
    width=0.6,
    fliersize=3
)

# Add red diamonds for means
means = df_all.groupby("Group")["cont_full"].mean()
for i, m in enumerate(means):
    plt.scatter(i, m, color="red", marker="D", s=50, zorder=3, label="Mean" if i == 0 else "")

# Title and KS test result
plt.title("Distribution of cont_full by Missingness of cont_mcar (Train Set)",
          fontsize=14, weight="bold")

# Add KS result as text box
textstr = f"KS Statistic = {stat:.3f}\nP-value = {p_value:.3f}"
plt.gca().text(
    0.05, 0.95, textstr,
    transform=plt.gca().transAxes,
    fontsize=10,
    verticalalignment='top',
    bbox=dict(boxstyle="round,pad=0.3", facecolor="white", alpha=0.8)
)

plt.ylabel("cont_full", fontsize=12)
plt.xlabel("")
sns.despine()
plt.legend()
plt.show()

图片

import seaborn as sns
import matplotlib.pyplot as plt
from scipy.stats import chi2_contingency

# --- Step 1: Build contingency table on the TRAIN set ---
contingency_table = pd.crosstab(train_df["R_cont_mcar"], train_df["cat_full"])
chi2, p_value, dof, expected = chi2_contingency(contingency_table)

# --- Step 2: Compute proportions for each group ---
# --- Recompute proportions but flip the axes ---
props = contingency_table.div(contingency_table.sum(axis=1), axis=0)

# Transform for plotting: Group (R) on x-axis, Category as hue
df_props = props.reset_index().melt(
    id_vars="R_cont_mcar",
    var_name="Category",
    value_name="Proportion"
)

# Map R values to clear labels
df_props["Group"] = df_props["R_cont_mcar"].map({1: "Observed (R=1)", 0: "Missing (R=0)"})

# --- Plot: Group on x-axis, bars show proportions of each category ---
sns.set_theme(style="whitegrid")
plt.figure(figsize=(8,6))

sns.barplot(
    x="Group", y="Proportion", hue="Category",
    data=df_props, palette="Set2"
)

# Title and Chi² result
plt.title("Proportion of cat_full by Observed/Missing Status of cont_mcar (Train Set)",
          fontsize=14, weight="bold")

# Add Chi² result as a text box
textstr = f"Chi² = {chi2:.3f}, p = {p_value:.3f}"
plt.gca().text(
    0.05, 0.95, textstr,
    transform=plt.gca().transAxes,
    fontsize=10,
    verticalalignment='top',
    bbox=dict(boxstyle="round,pad=0.3", facecolor="white", alpha=0.8)
)

plt.xlabel("Observed / Missing Group (R)")
plt.ylabel("Proportion")
plt.legend(title="cat_full Category")
sns.despine()
plt.show()

图片

上面的两个图表明,在 MCAR 假设下,无论 R 的值(1 = 观察,0 = 缺失)如何,Y、Ym 和 X 的分布保持不变。这些结果进一步得到 Kolmogorov–Smirnov 和卡方测试的支持,这些测试确认了观察组和缺失组之间没有显著差异。

对于分类变量,可以执行与上述相同的分析。虽然这些单变量检查可能耗时,但当变量数量较少时,它们是有用的,因为它们提供了对缺失数据机制的快速直观了解。然而,对于更大的数据集,应考虑使用多变量方法。

2.1.3 MCAR 假设的多变量分析

根据我所知,只有一种多变量统计测试被广泛用于在数据集级别评估 MCAR 假设:Little 的 chi2 测试,用于测试 MCAR 假设,称为 mcartest。此测试是在 R 语言中开发的,它比较了不同缺失数据模式下的观察变量分布,并计算一个遵循卡方分布的全局测试统计量。

然而,其主要局限性在于它不适合分类变量,因为它依赖于变量正态分布的强烈假设。我们现在转向在 MCAR 假设下填充缺失值的方法。

2.2 处理 MCAR 下缺失数据的方法。

在 MCAR 假设下,缺失指示符 R 独立于 Y[o]、Y[m]和 X。由于数据完全随机缺失,删除不完整观测值不会引入偏差。然而,当缺失值的比例较高时,这种方法变得效率低下。

在这种情况下,简单的填充方法,如用均值、中位数或最频繁的类别替换缺失值,通常更受欢迎。它们易于实现,计算工作量小,可以在不增加模型复杂性情况下随时间管理。虽然这些方法不会产生偏差,但它们往往低估方差,并可能扭曲变量之间的关系。

相比之下,像基于回归的填充、kNN 或多重填充这样的高级方法可以在缺失数据比例较大时提高统计效率并帮助保留信息。它们的主要缺点在于算法复杂性高、计算成本高,以及在生产环境中维护它们所需的努力更大。

为了预测目的在 MCAR 假设下填充缺失值,请按以下步骤操作:

  1. 从训练集中学习填充值,对于连续变量使用均值,对于分类变量使用最频繁的类别。

  2. 应用这些值来替换训练集和测试集中的缺失数据。

  3. 在测试集上评估模型,确保在填充过程中没有使用测试集的信息。

import pandas as pd

def compute_impute_values(df, cont_vars, cat_vars):
    """
    Compute imputation values (mean for continuous, mode for categorical)
    from the training set only.
    """
    impute_values = {}
    for col in cont_vars:
        impute_values[col] = df[col].mean()
    for col in cat_vars:
        impute_values[col] = df[col].mode().iloc[0]
    return impute_values

def apply_imputation(train_df, test_df, impute_values, vars_to_impute):
    """
    Apply the learned imputation values to both train and test sets.
    """
    train_df[vars_to_impute] = train_df[vars_to_impute].fillna(value=impute_values)
    test_df[vars_to_impute] = test_df[vars_to_impute].fillna(value=impute_values)
    return train_df, test_df

# --- Example usage ---
train_df, test_df = stratified_split(
    df,
    strat_vars=["cat_mcar", "cat_full", "target"],
    test_size=0.3,
    random_state=42
)

# Variables to impute
cont_vars = ["cont_mcar"]
cat_vars = ["cat_mcar"]
vars_to_impute = cont_vars + cat_vars

# 1\. Learn imputation values on TRAIN
impute_values = compute_impute_values(train_df, cont_vars, cat_vars)
print("Imputation values learned from train:", impute_values)

# 2\. Apply them consistently to TRAIN and TEST
train_df, test_df = apply_imputation(train_df, test_df, impute_values, vars_to_impute)

# 3\. Check
print("Remaining missing values in train:\n", train_df[vars_to_impute].isnull().sum())
print("Remaining missing values in test:\n", test_df[vars_to_impute].isnull().sum()) 

本节关于理解 MCAR 和选择适当的填充方法提供了在 MAR 假设下处理类似策略的清晰基础。

3. 理解 MAR 并选择合适的填充方法

MAR 假设定义为:

Pr(R|Y[m] ,Y[o], X) = Pr(R|Y[o], X) (2)

换句话说,缺失指示符的分布仅取决于观察数据。即使在 R 仅依赖于协变量 X 的情况下,

Pr(R|Y[m] ,Y[o], X) = Pr(R|X) (3)

这仍然属于 MAR 假设。

3.1 分析具有缺失值的变量的 MAR 假设

在 MAR 假设下,缺失指示符𝑅仅依赖于观察变量 Y[o]和 X,但不依赖于缺失数据𝑌。

为了间接评估这个假设的合理性,可以通过比较有缺失值和无缺失值的组之间观察变量的分布来应用常见的统计测试(Student 的t检验、Kolmogorov-Smirnov、卡方检验等)。

对于多元分析,也可以使用 R 中实现的mcartest,它将 Little 的 MCAR 测试扩展到评估假设(3),即在变量的多元正态性假设下,Pr(R|Y[m] ,Y[o], X) = Pr(R|X)

如果这个测试没有被拒绝,考虑到辅助变量 X,缺失数据机制可以合理地被认为是 MAR(假设 3)。

我们现在可以转向如何推断这类缺失数据的问题。

3.2 在完全随机应答(MAR)假设下处理缺失数据的方法。

在 MAR 假设下,缺失概率 R 仅取决于观察变量 Y[o]和协变量 X。在这种情况下,具有缺失值的变量 Y^k 可以使用其他可用变量 Y[o]和 X 来解释,这促使使用基于监督学习的先进推断方法。

这些方法涉及构建一个预测模型,其中不完整的变量 Y^k 作为目标,其他观察变量 Y[o]和 X 作为预测变量。模型在完整案例([Y^k][o] of Y)上训练,然后应用于估计 Y^k 的缺失值[Y^k​][m]。

文献中最常用的推断方法包括:

  • k-最近邻(KNNimpute,Troyanskaya 等人,2001),主要应用于连续数据;

  • 饱和多项式模型(Schafer,1997),用于分类数据;

  • 多元链式方程(MICE,Van Buuren 和 Oudshoorn,1999),适用于混合数据集,但依赖于调整参数和参数模型的指定。

所有这些方法都依赖于对潜在数据分布的假设或所选模型能够充分捕捉变量之间关系的假设。

最近,MissForest(Stekhoven 和 Bühlmann,2012)作为一种基于随机森林的非参数替代方案出现,非常适合混合数据类型,并且对交互作用和非线性关系都具有鲁棒性。

MissForest 算法依赖于随机森林(RF)来推断缺失值。作者提出了以下程序:

MissForest 算法

来源:[2] Stekhoven 等人(2012

如定义,MissForest 算法不能直接用于预测目的。对于每个变量,在步骤 6 和 7 之间,用于从 xmis 预测 ymis 的随机森林模型 M[s]不保存。因此,在生产中,从业者依赖 MissForest 作为预测模型既不太可能也不太可取。

缺乏存储的模型M[s]推断参数(在此为训练集)使得评估新数据上的泛化性能变得困难。尽管有些人试图通过遵循Liam Morgan的方法来解决这个问题,但挑战仍然没有解决。

此外,这种限制增加了算法复杂性和计算成本,因为必须为每个新的数据集从头开始重新运行整个算法(例如,当使用单独的训练集和测试集时)。

应该怎么做?是否仍然应该使用 MissForest 算法?

如果目标是仅针对现有数据集开发用于分类或分析的模型,没有将其应用于新数据的意图,那么强烈推荐使用 MissForest,因为它提供了高精度和鲁棒性。

然而,如果目标是构建一个将应用于新数据集的预测模型,应避免使用 MissForest,原因如上所述。在这种情况下,最好使用一个明确存储插补模型或从训练集估计的参数的算法。

幸运的是,现在存在一个适应版本:MissForestPredict,自 2024 年以来在 R 和 Python 中均可使用,专门为预测任务设计。有关更多详细信息,请参阅[Albu, Elena, 等人 (2024)]。](https://arxiv.org/pdf/2407.03379)

使用 MissForestPredict 算法进行预测包括将标准的 MissForest 程序应用于训练数据。然而,与原始 MissForest 不同,这个版本返回并存储与每个变量关联的个体模型 M[s],这使得它们可以用于在新的数据集中插补缺失值。

说明

基于模型保存的 MissForestPredict 插补

来源:[4] Albu 等人 (2024)。

下面的算法说明了如何将MissForestPredict应用于新的观测值,无论它们来自测试集时间外样本还是应用数据集

说明

MissForestPredict 应用于新观测值的说明

来源:[4] Albu 等人 (2024)。

我们现在已经拥有了处理引言中提出的问题所需的所有元素。在进入结论之前,让我们转向最终的机制,MNAR

4. 理解 MNAR

当缺失数据机制直接依赖于未观察到的值时,就会发生缺失非随机(MNAR)。换句话说,如果一个变量 Y 包含缺失值,那么指示变量 R(如果 Y 被观察,则 R=1,否则 R=0)仅依赖于缺失部分 Y[m]。

由于建模依赖性所需的信息正是缺失的,因此没有通用的统计方法来处理这种类型的机制。在这种情况下,建议依靠领域专业知识来理解非响应背后的原因,并定义针对特定上下文的策略来分析和处理缺失值。

然而,重要的是要强调,仅基于观察数据,通常无法从经验上区分MAR 和 MNAR

结论

本文的目的是展示如何在不偏倚模型性能评估的情况下,为了预测目的进行缺失值插补。为此,我们介绍了生成缺失数据的主要机制(MCAR、MAR、MNAR),评估其合理性的统计测试,以及最适合每种情况的插补方法。

我们的分析强调,在完全随机缺失(MCAR)的情况下,简单的插补方法通常是首选的,因为它们可以节省大量时间而不引入偏差。在实践中,缺失数据机制通常是缺失完全随机(MAR)。在这种情况下,基于机器学习模型的先进插补方法,如 MissForest,特别合适。

然而,当目标是构建预测模型时,使用存储从训练数据中学习到的插补参数或模型,并在测试、超时或应用数据集上持续复制的的方法是至关重要的。这正是MissForestPredict(于 2024 年引入,可在 R 和 Python 中使用)的贡献,它解决了原始 MissForest(2012 年)的局限性,该方法最初并非为预测任务而设计。

因此,在没有进行适配的情况下使用 MissForest 进行预测可能会导致偏差结果,除非实施纠正措施。对于在生产中部署了 MissForest 的从业者来说,分享他们开发用于克服这一局限性的策略将非常有价值。

参考文献

[1] Audigier, V., White, I. R., Jolani, S., Debray, T. P., Quartagno, M., Carpenter, J., … & Resche-Rigon, M. (2018). 对具有连续和二元变量的多级数据进行多重插补。

[2] Stekhoven, D. J., & Bühlmann, P. (2012). MissForest—针对混合类型数据的非参数缺失值插补。 生物信息学, 28(1), 112-118.

[3] Li, C. (2013). 完全随机缺失的 Little 测试。 Stata 期刊, 13(4), 795-809.

[4] Albu, E., Gao, S., Wynants, L., & Van Calster, B. (2024). missForestPredict–针对预测设置的缺失数据插补。 arXiv 预印本 arXiv:2407.03379.

图片来源

本文中的所有图像和可视化都是由作者使用 Python(pandas、matplotlib、seaborn 和 plotly)和 excel 创建的,除非另有说明。

免责声明

我写作是为了学习,所以犯错误是常态,尽管我尽力了。请,当你发现它们时,告诉我。我也很欣赏对新主题的建议!

posted @ 2026-03-28 10:08  布客飞龙III  阅读(1)  评论(0)    收藏  举报