scikit-learn RFECV偶发不执行特征选择、特征数卡滞问题咨询
问题原因
这不是RFECV跳过了特征选择流程,是参数设置和随机性问题共同导致的,核心原因如下:
- 未固定随机种子导致结果随机波动
RFECV的运行逻辑是:从全量特征起步,每轮训练当前的estimator,删除重要性最低的一批特征,直到降到你设置的最小特征数阈值,最终返回所有测试过的特征子集中,交叉验证平均得分最高的子集。
你设置cv=5时没有传入固定随机种子的交叉验证拆分器,如果使用的self.model_object本身是带随机性的模型(比如树集成模型、带随机初始化的线性模型、逻辑回归等)也没有固定随机种子,每次运行RFECV时会出现两个不确定因素:- 交叉验证的训练、验证集拆分结果每次都不一样
- 每轮训练输出的特征重要性排序每次都不一样
两者叠加后,各特征子集的交叉验证得分会出现波动:前3次运行时,388个全量特征的得分高于所有筛减后的子集,RFECV就会返回全量特征;后续某次运行中,筛减到318个特征的子集得分反超全量特征,就会返回318个特征的结果,下一轮同理得到255个特征的结果。
- 复用同一模型实例造成状态污染
你在循环中每次都把同一个self.model_object实例传入RFECV,RFECV在fit过程中会反复训练这个模型对象,上一轮循环结束后模型已经留存了训练后的权重、参数状态,下一轮再传入RFECV时模型初始状态不一致,会进一步放大结果的波动。 - step参数的整数截断存在逻辑隐患
你计算删除步长的代码为step = int(n_features_to_drop / 10),整数截断会让实际步长小于预期:比如你原本计划每次删除待删特征总量的1/10,但截断后实际每次删除的特征数更少;当后续循环特征数降低,满足n_features_to_drop < 10时,这个计算式会得到step=0,直接触发参数错误,只是当前运行轮次还没触发这个问题。
补充说明:你的循环逻辑是直接把上一轮RFECV输出的特征子集作为下一轮的输入,只要某轮RFECV判定全量特征最优、没有删除特征,下一轮的输入特征数就不会变化,自然会反复出现"starting at 388"的输出,直到某轮RFECV判定筛减后的特征更优,循环才会进入下一个特征数阶段。
内容的提问来源于stack exchange,提问作者Jeroen Vermunt
相关产品推荐
相关产品推荐

