使用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
相关产品推荐
相关产品推荐

