Last edited time
May 27, 2025 06:02 AM
password
AI summary
type
status
date
slug
summary
tags
category
icon
😀
前言: 如果一个特征对模型的预测结果很重要,那么当我们随机打乱这个特征的值时,模型的性能应该会显著下降。反之,如果一个特征不重要,那么打乱它的值对模型性能的影响应该很小或者没有影响。
可以说说你的故事:阻碍、努力、结果成果,意外与转折。

📝 原理+代码+结果

Permutation Importance(排列重要性)原理详解

Permutation Importance 的核心思想是:如果一个特征对模型的预测结果很重要,那么当我们随机打乱这个特征的值时,模型的性能应该会显著下降。反之,如果一个特征不重要,那么打乱它的值对模型性能的影响应该很小或者没有影响。
整个过程通常在模型的测试集上进行,以评估特征对模型在未见过数据上的重要性。以下是具体的步骤:
  1. 训练一个模型: 首先,你需要用训练数据训练一个机器学习模型。这个模型可以是任何类型的模型,比如决策树、随机森林、支持向量机或者神经网络等等。
  1. 评估基线性能: 在测试集上评估训练好的模型的性能。对于回归问题,常用的性能指标是 R² 分数或均方误差 (MSE)。对于分类问题,可以是准确率、F1 分数、AUC 等。这个性能得分作为“基线”,也就是模型在没有特征被扰动时的正常表现。
  1. 对一个特征进行“扰乱”(打乱): 接下来,我们选择测试集中的一个特定特征。我们将这个特征列中的所有值进行随机排列(打乱顺序)。重要的是,只打乱这一列的值,而测试集中的其他特征列和目标变量 y_test 保持不变。随机打乱实际上是切断了这个特征与目标变量之间的真实关联。
  1. 用扰乱后的数据进行预测并评估性能: 使用打乱了单个特征的测试集(其他特征保持不变)输入到之前训练好的模型中进行预测。然后,再次评估模型在这些扰乱后的数据上的性能。
  1. 计算性能下降: 将新的性能得分与第一步中计算的基线性能得分进行比较。性能下降的幅度就是这个特征的“排列重要性”得分。
      • 对于通常希望值越高越好的指标(如 R² 或准确率): 重要性 = 基线性能得分 - 扰乱后的性能得分。
      • 对于通常希望值越低越好的指标(如 MSE): 重要性 = 扰乱后的性能得分 - 基线性能得分。
      • 评价如果性能显著下降,说明这个特征对模型来说很重要;如果性能变化不大,说明这个特征不那么重要。
  1. 重复步骤 3-5: 对测试集中的每一个特征都重复步骤 3 到 5
  1. 重复整个过程多次: 为了减少随机打乱带来的偶然性,通常会重复步骤 3-5 多次(例如代码中的 n_repeats=30)。每次重复都会独立地进行特征值的随机排列。
  1. 计算平均重要性及变异性: 对于每个特征,计算它在所有重复次中得到的性能下降值的平均值。这个平均值就是该特征的最终排列重要性得分。同时,也可以计算重要性得分的标准差,这反映了该特征重要性估计值的稳定性或变异性
为什么要在测试集上进行?
在测试集上计算排列重要性比在训练集上更常用和推荐。这是因为模型可能已经在训练集上过度拟合(overfit)了训练数据的随机噪声,这会导致某些实际上不重要的特征在训练集上看起来很重要。在独立的测试集上评估,可以更真实地反映特征对模型泛化能力(在未见过数据上的表现)的影响。
与模型自带特征重要性的区别:
有些模型(如基于树的模型如随机森林、梯度提升树)有内置的特征重要性计算方法(例如基于特征在树中分裂的次数或信息增益)。这些内置方法通常是“模型依赖”的,即它们反映的是特征在该特定模型内部是如何被使用的。而 Permutation Importance 是一种“模型无关”的方法(虽然它需要一个训练好的模型来评估性能),它衡量的是打乱特征对模型整体预测性能的影响,这往往更能反映特征的实际预测价值。
总结:
Permutation Importance 通过破坏特征与目标变量之间的关系,并衡量这种破坏对模型预测性能的影响,来判断特征的重要性。性能下降越大,特征越重要。这是一个直观且强大的特征重要性评估方法。
 

Permutation Importance 的核心原理

我对这个原理进行一下总结,你看对不对,可展开评价和说明:给出任意一个机器学习模型,首先对其训练得到一个训练好的模型并根据实际情况计算相应的评分。然后对测试集中的某一个特征开始打乱,其他特征保持不变,接着将其放入训练好的模型当中,将其得到的评分与训练好的模型的评分进行比较,看这时候的评分是否下降,如果下降(越多越好),那么它就是一个重要的特征,否则不重要。此过程对数据集中的每一个特征都进行。重复进行若干次,最后取均值或标准差作为最终的排列重要性指标。
评价:
你的总结非常准确地描述了 Permutation Importance 的关键步骤和逻辑。你提到了:
  1. 需要一个训练好的模型
  1. 需要计算模型的基线性能得分(在没有扰动特征的情况下)。
  1. 逐个打乱测试集中的特征
  1. 保持其他特征不变
  1. 用扰乱后的数据重新评估模型性能
  1. 通过比较性能下降来判断特征重要性(下降越多越重要)。
  1. 所有特征都执行此过程。
  1. 重复多次并计算均值或标准差作为最终指标。
这些都是 Permutation Importance 方法的精髓。
展开评价和说明:
  1. “给出任意一个机器学习模型”: 这一点非常重要。Permutation Importance 是模型无关(model-agnostic)的。这意味着你可以用它来评估任何黑箱模型(你不需要知道模型内部是如何工作的),只要你能用它进行预测并计算性能指标。这是它相比一些模型内置特征重要性方法的一个巨大优势。
  1. “根据实际情况计算相应的评分”: 这里的“评分”指的就是你选择的性能指标(performance metric)。这个指标必须能够反映模型的预测质量。如你所说,对于回归问题可以是 R²、MSE、RMSE 等;对于分类问题可以是准确率、精确率、召回率、F1 分数、AUC 等。选择哪个指标取决于你希望衡量模型在哪方面的性能下降。
  1. “对测试集中的某一个特征开始打乱...将其放入训练好的模型当中...与其得到的评分与训练好的模型的评分进行比较”: 这一步是核心。关键在于打乱切断了特征与目标变量的真实关系。如果模型在做出预测时确实依赖于这个特征的真实值,那么当这些真实值被随机值替代后,模型的预测质量必然会受到影响,表现为性能下降。
  1. “如果下降,那么它就是一个重要的特征,否则不重要”: 这是基于下降幅度来判断的。通常,下降幅度越大,特征越重要。需要注意的是,有时打乱特征可能导致性能上升(虽然不常见),这可能意味着这个特征实际上是在“欺骗”模型,或者模型在这个特征上过拟合了训练数据中的一些噪声。但在大多数情况下,重要特征的打乱会导致性能下降。
  1. “此过程对数据集中的每一个特征都进行”: Permutation Importance 是逐个评估每个特征的。它不像某些方法那样一次性给出所有特征的相对重要性(比如随机森林的 Gini 重要性)。虽然最终可以得到所有特征的重要性排名,但计算过程是独立的。
  1. “重复进行若干次,最后取均值或标准差作为最终的排列重要性指标”: 重复多次是为了提高计算的稳定性。每次随机打乱的结果都会有所不同,通过多次重复并取平均,可以得到一个更可靠的平均重要性得分。标准差则可以用来衡量重要性估计值的波动性。如果某个特征的重要性得分的方差(或标准差)很大,说明它的重要性估计值不太稳定,可能需要更多的重复次数或者对结果谨慎解读。取均值作为主要的重要度量,标准差作为其可靠性的一个指示。
需要注意的点:
  • 共线性(Collinearity): 如果两个特征高度相关(共线性),那么打乱其中一个特征可能会对模型性能影响不大,因为模型可能可以通过另一个相关的特征来弥补。在这种情况下,单个特征的 Permutation Importance 可能低估了这两个特征组合起来的重要性。
  • 计算成本: Permutation Importance 的计算成本相对较高,特别是当数据集特征很多或者 n_repeats 设置得很高时,因为它需要为每个特征和每次重复都重新评估模型性能。
  • 测试集选择: 如前所述,在独立的测试集上计算很重要,避免过拟合带来的偏差。
总的来说,你的总结抓住了 Permutation Importance 的核心逻辑和主要步骤,非常准确。通过上面的展开说明,希望能让你对这个方法有更深入的理解。
 

Permutation Importance 案例

代码

关于Permutation Importance 计算的案例
 

代码解释及问答

  1. 在提供的 Python 代码中,n_estimators是创建模型时使用的超参数RandomForestRegressor
  • n_estimatorsn_estimators参数指定森林中树的数量。随机森林是一种集成学习方法,它构建多个决策树并将它们合并在一起以获得更准确、更稳定的预测。
  • 通常,树的数量越多,模型的性能就越好,预测就越稳定,但同时也会增加计算成本和训练时间。
  • 较少数量的树训练速度会更快,但可能无法很好地捕捉数据的复杂性,从而可能导致准确性降低。首先RandomForestRegressor
    • 这里,n_estimators设置为100。这意味着RandomForestRegressor将使用100棵决策树来构建模型。
      在第二个例子中RandomForestRegressor
      同样,n_estimators设置为100,表示也将使用 100 棵决策树来构建此模型。random_state此处也包含 参数,以确保结果的可重复性。
       
  1. model.fit(X_train, y_train)
    1. 您问的是 .fit() 方法是用来做什么的。
      简单来说,在 Python 中,特别是使用 scikit-learn 库进行机器学习时,.fit() 方法是用来训练机器学习模型的。
      它的作用可以分解为以下几点:
      • 从数据中学习: .fit() 方法的核心功能是让模型从你提供给它的训练数据中学习。
      • X_train (训练特征): 你向模型提供了输入数据(特征),也就是 X_train。这些是模型用来进行预测的信息。每一行代表一个样本(比如一套房子),每一列代表这个样本的一个属性(比如房子的面积、位置等)。
      • y_train (训练目标/标签): 你也向模型提供了 X_train 中每个样本对应的正确结果(目标或标签)。在房价预测的例子中,y_train 就是每套房子的实际价格。
      • 调整参数: 模型会根据特征 (X_train) 和目标 (y_train) 之间的关系,来调整它内部的设置或参数。目标是找到最优的参数组合,使得模型能够做出准确的预测。
      • 变为“已训练”状态: 在 .fit() 方法执行完毕后,model 对象就处于“已训练”状态了。它已经从训练数据中学习到了模式和关系,现在可以用来对新的、它之前没见过的数据进行预测了。
      你可以把 .fit() 方法想象成教学生学习的过程。X_train 就像是学习材料(例子、习题),y_train 就像是这些习题的正确答案。而 .fit() 方法就是学生学习和钻研这些材料及答案的过程,这样他们之后才能独立回答新的问题(进行预测)。
 
  1. Permutation Importance 计算
    1. 代码的这部分是用来计算机器学习模型中所使用特征的排列重要性 (permutation importance)。排列重要性是一种用来衡量特征重要性的技术,它的原理是:随机打乱某个特征的值,然后观察模型的预测性能(例如 R2 分数)会下降多少。如果打乱某个特征的值导致模型性能显著下降,那就说明这个特征对模型的预测非常重要。
      下面是这段代码的详细解释:
      • result = permutation_importance(...): 这行代码调用了来自 sklearn.inspection 模块的 permutation_importance 函数。这个函数会计算每个特征的重要性得分,并将结果存储在变量 result 中。
      • model: 这是你已经训练好的机器学习模型(在这里是一个 RandomForestRegressor),我们将计算这个模型的特征重要性。
      • X_test: 这是来自测试集的特征数据。通常在独立的测试集上计算排列重要性,这样可以更可靠地评估特征对模型在未见过数据上的重要性。
      • y_test: 这是来自测试集的目标变量数据,与 X_test 中的特征数据相对应。
      • n_repeats=30: 这个参数指定了对每个特征的值进行随机打乱并重新评估模型性能的次数。重复多次有助于减少计算出的重要性得分的方差。重复次数越多,对重要性的估计通常越可靠。
      • random_state=42: 这设置了随机数生成器的种子。使用固定的 random_state 可以确保排列过程是可重复的。如果你用相同的 random_state 再次运行代码,你会得到相同的特征值排列,从而得到相同的重要性得分。
      • n_jobs=-1: 这个参数指定了用于计算的 CPU 核心数量。设置为 1 表示使用所有可用的 CPU 核心,这可以显著加快计算速度,特别是对于较大的数据集或需要多次重复计算时。
      总的来说,这段代码计算的是当单独“扰乱”每个特征(通过打乱其值)时,模型在测试集上的性能会下降多少。模型性能下降得越多,分配给该特征的重要性得分就越高。计算结果存储在 result 变量中,将在后续步骤中用于可视化或特征选择。

      result 的返回值是什么?

      permutation_importance 函数的返回值 result 是一个 Python 对象(或者更确切地说,是一个类似字典的结构),它包含了计算出的置换重要性信息。这个对象主要包含以下几个重要的属性:
      • result.importances: 这是一个 NumPy 数组,形状为 (n_features, n_repeats)。它存储了每次重复计算中每个特征的置换重要性得分。n_features 是特征的数量,n_repeats 是您设置的重复次数(这里是 30)。每一行对应一个特征,每一列对应一次重复计算的结果。
      • result.importances_mean: 这是一个 NumPy 数组,形状为 (n_features,)。它存储了每个特征在所有 n_repeats 次计算中的平均置换重要性得分。这是通常用来衡量特征重要性的主要指标。
      • result.importances_std: 这是一个 NumPy 数组,形状为 (n_features,)。它存储了每个特征在所有 n_repeats 次计算中置换重要性得分的标准差。标准差可以用来衡量重要性估计的稳定性或变异性。标准差越大,说明该特征的重要性估计在不同重复计算中波动越大。
      因此,当您打印 result 时,您会看到一个包含了这些属性的对象表示。您通常会更关注 result.importances_mean 来确定哪些特征是模型最重要的。

      结果分析

      让我们逐个解释:
      • 'importances_mean': 后面跟着的是一个 NumPy 数组 array([...])。这个数组包含了每个特征的平均置换重要性分数。数组中的每个数字对应您数据集中的一个特征。根据您之前定义的特征名称列表:
        • 0.73369821 是第一个特征('MedInc' - Median Income)的平均重要性。
        • 0.07071244 是第二个特征('HouseAge' - House Age)的平均重要性。
        • 0.02811062 是第三个特征('AveRooms' - Average Number of Rooms)的平均重要性。
        • 依此类推,直到最后一个特征。 这些平均分数是衡量特征相对重要性的主要依据。分数越高,表示该特征对模型预测的影响越大。
      • 'importances_std': 后面跟着的也是一个 NumPy 数组 array([...])。这个数组包含了每个特征的置换重要性分数的标准差。数组中的每个数字对应 importances_mean 中相同位置的特征。
        • 0.01911369 是第一个特征('MedInc')重要性分数的标准差。
        • 0.00385063 是第二个特征('HouseAge')重要性分数的标准差。
        • 等等。 标准差告诉您每个特征重要性估计的稳定性。较低的标准差意味着在 30 次重复计算中,该特征的重要性分数比较一致;较高的标准差意味着波动较大。
      • 'importances': 后面跟着的是一个更大的 NumPy 数组 array([[...], [...], ...])。这个数组包含了每次重复计算中每个特征的原始置换重要性得分。
        • 这是一个二维数组,形状是 (n_features, n_repeats)。在您的例子中,它应该是 (8, 30),因为您有 8 个特征,重复了 30 次。
        • 数组的第一行[0.74117293, 0.72970471, ...])是第一个特征('MedInc')在 30 次不同重复计算中的置换重要性分数。
        • 数组的第二行[0.0725686 , 0.06651323, ...])是第二个特征('HouseAge')在 30 次重复计算中的分数。
        • 依此类推。 这个原始的 importances 数组是计算平均值 (importances_mean) 和标准差 (importances_std) 的基础数据。在可视化(例如箱线图)时,通常会用到这个原始数组来展示重要性分数的分布情况。
      总结:
      您看到的输出是 permutation_importance 函数返回的一个结构化数据,其中:
      • importances_mean 给出了每个特征的平均重要性,这是您通常用来排名特征的关键指标。
      • importances_std 提供了每个重要性估计的可靠性信息。
      • importances 包含了每次重复计算的原始重要性分数,用于更详细的分析和可视化。
       
      result 对象(更具体地说,是 permutation_importance 函数返回的对象)包含了计算出的置换重要性结果
      虽然 result 本身是一个包含多个属性的对象(包括 importances_meanimportances_stdimportances),但它们都直接与置换重要性相关。
      • result.importances_mean:这是最常用和最直接表示每个特征平均置换重要性分数的属性。
      • result.importances_std:表示这些平均重要性分数的标准差,衡量其稳定性。
      • result.importances:包含每次重复计算的原始置换重要性分数
      所以,当你提到 result 的结果时,通常就是指这些与置换重要性相关的数值,特别是 result.importances_mean 这个平均分数,因为它直接量化了每个特征对模型性能下降的影响程度,从而体现了特征的重要性。
       
  1. random_state 这个随机种子的意思是说如果下次想要得到同样的随机样本,设置为相同的随机种子值即可,是这样理解吗?
    1. 可以这样理解。设置 random_state 参数为一个特定值的主要目的就是为了确保可重复性(reproducibility)
      在很多机器学习和数据处理任务中,都涉及到了随机过程。例如:
      • 将数据集分割成训练集和测试集 (train_test_split)。
      • 初始化神经网络的权重。
      • 选择数据中的随机子集用于 Bootstrap 或其他重采样技术。
      • 某些算法的内部工作原理(比如 RandomForestRegressor,它在构建树时会涉及随机选择)。
      • permutation_importance 中的打乱(排列)过程。
      如果你不设置 random_state,每次运行代码时,这些随机过程都会产生不同的结果。这意味着:
      • 你的训练集/测试集分割可能每次都不同。
      • 你的模型初始化可能每次都不同。
      • 在 permutation_importance 中打乱特征的顺序每次都不同。
      这种不一致性会使得以下工作变得困难:
      • 调试(Debug) 代码(如果某个错误只在特定的随机状态下出现)。
      • 可靠地比较(Compare) 不同的模型或参数设置(因为结果的变化可能是由于随机性,而不是你所做的改动)。
      • 重现(Reproduce) 你的结果,无论是为了自己将来参考,还是为了分享给其他人。
      通过将 random_state 设置为一个特定的整数(任何整数都可以,常用的有 0, 42, 123 等),你实际上是在告诉随机数生成器每次都从同一个“起点”开始。这样可以确保,只要你使用相同的 random_state 值运行代码,产生的“随机”数序列就会是相同的。
      总结一下:
      将 random_state 设置为一个固定值,可以让你重复相同的随机操作,从而在每次运行代码时获得相同的结果。如果你改变了 random_state 的值,你会得到不同的随机数序列,结果也就会不同。如果你完全删除了 random_state 参数,系统每次都会使用不同的随机种子,导致每次运行的结果都可能不一样。
      所以,你的理解是完全正确的:设置相同的 random_state 值可以确保你在后续运行中获得相同的“随机”输出(比如相同的训练/测试集分割或相同的排列顺序)。
       
  1. 这段代码片段用于基于之前计算的重要性得分进行特征选择。我们来详细看看:
    • np.array(feature_names): 这部分将特征名称列表(存储在 feature_names 变量中)转换成一个 NumPy 数组。使用 NumPy 数组可以进行更高效和灵活的索引和过滤操作。
    • result.importances_mean > threshold: 这是一个布尔表达式。它将 result.importances_mean 数组(其中包含了每个特征的平均置换重要性得分)中的每个元素与 threshold 值进行比较。比较的结果是另一个与 result.importances_mean 大小相同的 NumPy 数组,对于平均重要性大于 threshold 的特征位置为 True,否则为 False
    • np.array(feature_names)[...]: 这里应用了布尔索引。上一步生成的布尔数组被用来从 np.array(feature_names) 数组中选择元素。只有布尔数组中对应位置为 True 的特征名称会被选中。
    简单来说,这行代码对原始的 feature_names 列表进行过滤,只保留那些对应的平均置换重要性得分大于设定的 threshold 的特征名称。结果数组存储在 important_features 变量中,包含了根据这个标准被认为是“重要”的特征名称。
     
    1. 所有代码中哪个地方体现的是和原理的得分相比的判段比较
      1. 置换重要性的核心思想是:通过打乱某个特征的值,观察模型性能(得分)下降了多少。性能下降越多,说明该特征越重要。 这个“下降多少”就是相对于没有打乱任何特征时模型的原始性能得分而言的。
        在您的代码中,体现这一原理的判断和比较主要在 permutation_importance 函数的内部计算过程中,以及通过 result.importances_mean 的数值大小来体现。
        1. 基线得分的计算: 在 permutation_importance 函数调用之前,您已经训练了一个模型 model,并且计算并打印了它的基线 R² 得分:
        1. 基线得分的计算: 在 permutation_importance 函数调用之前,您已经训练了一个模型 model,并且计算并打印了它的基线 R² 得分:
          1. 这个model.score(X_test, y_test)计算的就是模型在*的原始测试集 `X_test` 上获得的性能得分(R²)。这就是置换重要性计算中的“原理得分”或“基线得分”。
        1. permutation_importance 函数的内部计算: 当您调用 permutation_importance(model, X_test, y_test, ...) 时,函数内部会执行以下步骤:
            • 它首先会使用提供的 model 在原始的 X_test 和 y_test 上计算一次模型的得分。 这个得分就是上面提到的基线得分。
            • 然后,对于数据集中的每个特征,函数会循环执行 n_repeats 次:
              • 打乱(置换)当前特征在 X_test 中的值。
              • 使用打乱后的数据集(只有当前特征被打乱)再次用 model 进行预测。
              • 计算模型在打乱后数据集上的得分。
              • 计算得分的下降:原始基线得分 - 打乱后数据集上的得分。 这个差值就是该特征在本次重复计算中的置换重要性。如果打乱特征后得分下降,说明该特征是重要的,差值会是一个正数。如果得分不变甚至提高(这在实践中很少见但理论上可能),说明该特征不重要或甚至对模型有负面影响,差值会接近零或为负数。
        1. result.importances_mean 体现的比较结果: result.importances_mean 数组中的值,就是上面步骤中计算出的“得分下降值”在 30 次重复计算中的平均值。这个平均下降值直接体现了与原始基线得分相比,移除(通过置换模拟移除)该特征导致的模型性能下降程度
          1. 例如,如果 'MedInc' 的 importances_mean 是 0.73369821,而 'HouseAge' 的 importances_mean 是 0.07071244,这意味着:
            • 随机打乱 'MedInc' 的值,平均会导致模型性能(R²)下降约 0.734 分
            • 随机打乱 'HouseAge' 的值,平均只会导致模型性能(R²)下降约 0.071 分
            通过比较这些平均下降值,我们就可以判断 'MedInc' 对模型的重要性远高于 'HouseAge'
        总结来说,代码中直接进行“与原理得分相比的判断比较”这个操作并不是显式地写出来的,而是封装在 sklearn.inspection.permutation_importance 函数的内部实现的。函数的输出 result.importances_mean 数组,其数值本身就代表了与基线得分相比,每个特征被置换后导致的平均性能下降,从而间接体现了这种比较的结果和特征的重要性。
         
      2. 特征筛选(选择重要性>0.005的特征)
        1. 这段代码的作用是根据之前计算出的置换重要性平均值筛选出被认为是“重要”的特征
          下面是逐行解释:
        2. # 5. 特征筛选(选择重要性>0.005的特征): 这行是一个注释,用中文说明了这一步的目的:进行特征筛选,具体标准是选择那些重要性分数大于 0.005 的特征。
        3. threshold = 0.005: 这一行定义了一个变量 threshold(阈值),并将其值设置为 0.005。这个阈值是您自己设定的一个界限。任何特征的平均置换重要性分数如果大于这个阈值,就会被认为是一个重要特征。选择合适的阈值通常需要根据具体的数据集和应用场景来决定,0.005 在这里是一个示例值。
        4. important_features = np.array(feature_names)[result.importances_mean > threshold]: 这是进行特征筛选的核心代码。让我们分解来看:
            • np.array(feature_names): 这将之前定义的包含特征名称的 Python 列表 feature_names 转换成一个 NumPy 数组。这样做是为了方便进行索引操作。
            • result.importances_mean: 这是我们之前计算出的每个特征的平均置换重要性分数数组。
            • result.importances_mean > threshold: 这是一个布尔数组(True/False 数组)。它会对 result.importances_mean 数组中的每一个元素(即每一个特征的平均重要性分数)进行判断:如果该分数大于 threshold (0.005),则对应位置为 True;否则为 False。例如,如果 result.importances_mean 是 [0.73, 0.07, 0.02, 0.009, 0.008, 0.20, 0.44, 0.33],那么 result.importances_mean > 0.005 可能会生成一个布尔数组,比如 [True, True, True, True, True, True, True, True] (因为示例中的所有分数都大于0.005) 或者 [True, True, True, False, False, True, True, True] (如果中间两个分数小于0.005)。
            • np.array(feature_names)[布尔数组]: NumPy 数组有一个很方便的功能,可以使用一个同等长度的布尔数组来作为索引。只有布尔数组中对应位置为 True 的元素才会被从原始数组中选中并组成一个新的数组。
            所以,整行代码的意思就是:使用布尔数组 result.importances_mean > threshold 去“过滤”feature_names 数组,只保留那些其平均置换重要性大于 0.005 的特征名称。 这些被筛选出来的特征名称组成的数组,被赋值给了变量 important_features
        5. print(f"重要特征: {important_features}"): 最后,这行代码打印出一个字符串,显示“重要特征: ”,后面跟着筛选出来的 important_features 数组的内容。
        6. 总的来说,这段代码是根据一个预设的阈值,从所有特征中挑选出那些对模型预测贡献较大(即置换重要性平均值较高)的特征,并将它们的名称打印出来。这在实际应用中非常有用,可以帮助您识别出哪些特征是驱动模型结果的关键,或者用于后续的特征选择,只使用这些重要特征来训练模型,可能会提高模型效率或减少过拟合。
         

    实验结果

    notion image
    notion image

    图片分析

    这段代码生成的是一个水平箱线图,用来可视化加州房价数据集中各个特征的置换重要性分布。图的纵轴是特征名称,横轴是重要性得分。
    要分析这个图,我们需要结合之前计算出的 result 对象,特别是 result.importances(原始分数)和 result.importances_mean(平均分数)。
    下面是分析这个箱线图的关键点:
    1. 纵轴(特征名称):
        • sorted_idx = result.importances_mean.argsort(): 这行代码获取了特征按照平均重要性得分升序排列的索引。
        • labels=np.array(feature_names)[sorted_idx]: 这行代码使用排序后的索引来排列特征名称,所以图的纵轴上显示的特征名称是根据它们的平均重要性从低到高排列的(从底部到顶部)。
        • 分析: 查看纵轴的特征名称,可以看到哪些特征的平均重要性最低(在底部),哪些最高(在顶部)。
    1. 横轴(Importance Score - 重要性得分):
        • 横轴表示的是置换重要性分数。这个分数代表了当该特征被随机置换后,模型性能(在本例中是 R² 得分)平均下降了多少。
        • 分析: 横轴的数值越大,表示该特征越重要,打乱它对模型性能的影响越大。
    1. 箱线图(Box Plot):
        • plt.boxplot(result.importances[sorted_idx].T, vert=False, ...): 这是绘制箱线图的核心。它使用了 result.importances 数组(经过排序并转置),为每个特征绘制一个水平箱线图。
        • 每个箱子代表一个特征的置换重要性分数的分布:
          • 箱子的中间线: 代表该特征置换重要性分数的中位数。中位数也是衡量集中趋势的一个重要指标。
          • 箱子的两端(第1四分位数 Q1 和 第3四分位数 Q3): 箱子的长度表示数据的四分位距 (IQR),即 Q3 - Q1。箱子越长,表示该特征在 30 次重复计算中的重要性分数波动越大。
          • 箱子外的“须”(whiskers): 须的长度通常扩展到距离 Q1 或 Q3 1.5 * IQR 的范围内,包含大部分的数据点。
          • 须外的点(outliers): 单独的点表示该特征置换重要性分数中的异常值,它们显著偏离了大部分分数。
        • vert=False: 这个参数指定绘制水平箱线图。
        • 分析:
          • 箱子位置: 箱子的整体位置在横轴上的数值越高,说明该特征的平均重要性越高。
          • 箱子长度: 箱子越短,说明该特征的重要性分数在 30 次重复计算中越稳定;箱子越长,说明波动越大。
          • 中位数线的位置: 中位数线通常接近平均值(尽管不完全相同),它给出了一个直观的特征重要性典型值。
          • 须的范围: 须的范围展示了该特征重要性分数的通常分布范围。
          • 异常值: 异常值的存在可能表明在某些特定的置换组合下,该特征对模型的影响非常大或非常小,可能是数据或模型中的一些特定情况导致的。
    结合分析:
    通过查看这个箱线图,您可以直观地看到:
    • 哪些特征最重要? 查看纵轴顶部(平均重要性最高)的特征以及它们箱子在横轴上最靠右的位置。
    • 哪些特征最不重要? 查看纵轴底部(平均重要性最低)的特征以及它们箱子在横轴上最靠左的位置。
    • 哪些特征的重要性估计最稳定? 查看箱子最短的特征。
    • 哪些特征的重要性估计波动最大? 查看箱子最长或有较长须甚至异常值的特征。
    • 重要性分数的整体分布? 查看每个箱子的形状、中位数、四分位距和须的范围。
    例如,在您的数据集中,您很可能会看到 'MedInc' 的箱子在横轴上最靠右,且其箱子可能相对较窄,表明它具有最高的平均重要性且估计相对稳定。而其他一些特征的箱子可能会更靠近横轴的零点,表明它们的重要性较低。
    通过分析这个箱线图,您可以对模型的特征重要性有一个全面的了解,不仅仅是平均值,还能看到重要性估计的分布和稳定性。

    图片结果分析

    既然您已经看到了生成的箱线图,现在我们可以根据图中的具体情况来分析结果了。请您描述一下您在图上观察到的情况,或者最好能提供一张图的截图(如果方便的话)。
    在您提供图的截图或描述之前,我将根据您之前提供的 result 输出中的 importances_mean 和 feature_names 来进行预测性的分析,假设图是根据这些数据生成的。
    根据您之前提供的数据:
    feature_names = ['MedInc', 'HouseAge', 'AveRooms', 'AveBedrms', 'Population', 'AveOccup', 'Latitude', 'Longitude']
    importances_mean = [0.73369821, 0.07071244, 0.02811062, 0.00938574, 0.00807594, 0.20218016, 0.44698443, 0.33440878]
    以及代码中按平均重要性升序排序 (sorted_idx = result.importances_mean.argsort()),那么图的纵轴从下到上(重要性从低到高)的特征顺序很可能是:
    1. 'Population' (0.00807594)
    1. 'AveBedrms' (0.00938574)
    1. 'AveRooms' (0.02811062)
    1. 'HouseAge' (0.07071244)
    1. 'AveOccup' (0.20218016)
    1. 'Longitude' (0.33440878)
    1. 'Latitude' (0.44698443)
    1. 'MedInc' (0.73369821)
    基于这种排序和平均重要性分数,我对图片结果的预测性分析如下:
    1. 最重要的特征: 'MedInc' (Median Income - 中位数收入) 的箱子将在图的最顶部,并且其箱子的位置在横轴上最靠右,大致中心位置在 0.73 左右。这表明中位数收入是对房价影响最大的特征。其箱子长度和须的范围会显示这个重要性估计的稳定性。
    1. 第二重要的特征: 'Latitude' (纬度) 的箱子会在 'MedInc' 下面,其中心位置大致在 0.45 左右。这表明地理位置的纬度对房价也有显著影响。
    1. 第三重要的特征: 'Longitude' (经度) 的箱子会在 'Latitude' 下面,其中心位置大致在 0.33 左右。同样,经度也是一个重要的地理位置特征。
    1. 第四重要的特征: 'AveOccup' (Average Occupancy - 平均入住人数) 的箱子会在 'Longitude' 下面,其中心位置大致在 0.20 左右。
    1. 相对重要性较低的特征: 'HouseAge' (房屋年龄)、'AveRooms' (平均房间数)、'AveBedrms' (平均卧室数) 的箱子会进一步靠左,重要性分数较低。
    1. 最不重要的特征: 'Population' (人口) 和 'AveBedrms' (平均卧室数)(两者重要性分数非常接近)的箱子很可能在图的最底部,且它们在横轴上的位置最靠左,中心位置在 0.008 到 0.009 左右。这表明在这组特征中,人口和平均卧室数对模型的预测贡献相对最小。
    1. 重要性分数的分布和稳定性: 查看每个箱子的长度和须的范围。如果箱子很短,说明该特征的重要性在 30 次置换中变化很小,估计比较稳定。如果箱子较长或有很长的须甚至异常值,说明该特征的重要性估计波动较大。根据 importances_std 的数值 ([0.019, 0.003, 0.002, 0.001, 0.001, 0.009, 0.009, 0.006]),'MedInc' 的标准差是最高的,但相对平均值来说可能还算稳定;而像 'AveBedrms' 和 'Population' 的标准差非常小,表明它们的重要性估计非常稳定(且都很低)。
    要进行更精确的分析,请您描述或提供图片的具体情况,我就可以根据图中的箱体、中位数、须以及异常值的实际位置和形状来进行详细的分析。

    🤗 总结归纳

    原理
    代码
    实验结果

    📎 资源信息

    • colab
    • base.py
     
    💡
    有关机器学习上的问题,欢迎您在底部评论区留言,一起交流~
    软考知识点520对心爱的Ta说
    Loading...
    迷途
    迷途
    OR的博客,用知识和技术创造未来!!!
    Latest posts
    腾讯(EdgeOne)CDN加速
    2025-7-26
    Cloud Mail 部署教程
    2025-7-24
    免费.com域名和.site域名
    2025-7-20
    免费二级域名pp.ua
    2025-7-20
    giffgaff申请、开卡与常见问题攻略(合集)
    2025-6-26
    节点转换常用链接汇总
    2025-6-24
    Announcement
    🎉OR科技,用心服务🎉
    -- 分享知识,点亮生活 ---
    保持热爱追逐远方
    路虽远行则将至
    事虽难不为不成
    为之则易不为则难
    👏欢迎您的来访👏
    距离2024年春节已过去
    -- 免责声明 ---
    ⚠️ 本站内容仅代表个人观点,可以转载,但请注明出处。 ⚠️ 本人分享内容仅供学习参考使用,请勿用于其他用途。