You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用TabPFN扩展的特征选择工具时触发KeyError,交叉验证全部拟合失败

使用TabPFN扩展的特征选择工具时触发KeyError,交叉验证全部拟合失败

看起来你遇到的问题是TabPFN在特征选择过程中找不到指定的分类特征索引导致的,我来帮你分析下原因和解决办法:

问题根源

核心矛盾在于TabPFN模型初始化时固定了分类特征的索引,而顺序特征选择(SFS)会动态生成原始数据集的特征子集。当SFS把特征子集传给PFN的fit方法时,PFN还是用初始化时的原始分类列索引去访问新子集的列,这些索引在子集中根本不存在,自然触发KeyError,最终导致所有交叉验证的拟合任务失败。

另外你传入的feature_names=category_column_indexes也可能有问题——这个参数应该接收特征名称(字符串列表),但你传的是列索引(数字列表),这也可能干扰工具的特征匹配逻辑。

解决办法

办法一:自定义适配动态特征子集的PFN包装类

我们可以写一个PFN的子类,让它在每次fit时,根据当前传入的特征子集,自动更新有效的分类特征索引:

from tabpfn import TabPFNClassifier
import pandas as pd

class AdaptiveCategoricalPFN(TabPFNClassifier):
    def fit(self, X, y, **fit_params):
        # 针对DataFrame类型的输入,自动映射原始分类索引到当前子集的列位置
        if isinstance(X, pd.DataFrame):
            # 假设category_column_indexes是你原始数据集的分类列索引列表
            current_cat_indices = [
                idx for idx, col_name in enumerate(X.columns) 
                if col_name in category_column_indexes
            ]
            self.categorical_features_indices = current_cat_indices
        # 调用父类的fit方法完成训练
        return super().fit(X, y, **fit_params)

然后用这个包装类代替原始PFN,再调用特征选择工具:

# 初始化适配版PFN(传入你原来的参数)
PFN = AdaptiveCategoricalPFN(device='cpu', ...)

# 注意feature_names传入特征名称列表,而不是索引
sfs = interpretability.feature_selection.feature_selection(
    estimator=PFN,
    X=X_train,
    y=y_train,
    n_features_to_select=5,
    feature_names=X_train.columns.tolist(),
    error_score='raise'
)

办法二:提前转换分类特征类型,跳过PFN的自动处理

在做特征选择之前,手动把分类列转换成category类型,这样PFN就不需要再通过索引去识别分类特征了:

# 提前将原始数据集中的分类列转换为category类型
X_train[category_column_indexes] = X_train[category_column_indexes].astype('category')

# 初始化PFN时,关闭自动分类特征识别
PFN = TabPFNClassifier(categorical_features_indices=None, ...)

# 运行特征选择
sfs = interpretability.feature_selection.feature_selection(
    estimator=PFN,
    X=X_train,
    y=y_train,
    n_features_to_select=5,
    feature_names=X_train.columns.tolist(),
    error_score='raise'
)

办法三:手动使用sklearn的SFS,完全控制特征适配

如果不想用tabpfn_extensions的封装,可以直接用sklearn的SequentialFeatureSelector,每次训练PFN时都根据当前特征子集重新设置分类索引:

from sklearn.feature_selection import SequentialFeatureSelector
from tabpfn import TabPFNClassifier

def dynamic_pfn(X, y):
    # 根据当前特征子集,生成对应的分类特征索引
    current_cat_indices = [
        idx for idx, col_name in enumerate(X.columns) 
        if col_name in category_column_indexes
    ]
    # 每次都初始化适配当前子集的PFN
    pfn = TabPFNClassifier(categorical_features_indices=current_cat_indices, ...)
    pfn.fit(X, y)
    return pfn

# 定义顺序特征选择器
sfs = SequentialFeatureSelector(
    dynamic_pfn,
    n_features_to_select=5,
    direction="forward"
)

# 拟合并获取选中的特征
sfs.fit(X_train, y_train)
selected_features = X_train.columns[sfs.get_support()]

备注:内容来源于stack exchange,提问作者Adam

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.13 20:04:32