scikit-learn中如何为稀疏分类特征加权调整评分?
解决方案
一、核心思路纠正:区分特征加权与样本加权
你要的是特征加权而非样本加权,之前用sample_weight的思路方向错了,这也是交叉验证时权重长度不匹配报错的根源。sample_weight是给每个样本整体加权,而你的需求是降低稀疏分类特征对模型的影响,这属于特征层面的权重调整。
二、针对稀疏分类特征的特征加权方案
1. 特征工程阶段:对稀疏分类特征进行缩放
先统计每个分类特征下各类别的出现频次,对该特征的编码值乘以基于频次的权重系数,稀疏类别(频次低)的系数小于1,从而降低特征数值幅度,削弱其对模型的影响。
示例代码:
import pandas as pd # 假设df是数据集,cat_col是某稀疏分类特征列 freq = df['cat_col'].value_counts(normalize=True) # 定义权重映射:频次越低,权重越小 weight_map = freq.apply(lambda x: x**0.5).to_dict() # 对特征列进行加权缩放 df['cat_col_weighted'] = df['cat_col'].map(weight_map)
后续用加权后的特征列替代原分类特征列参与训练即可。
2. 高斯过程核函数自定义:给特征分配不同长度尺度
高斯过程核函数(如RBF、Matern)的length_scale参数控制特征对输出的影响:length_scale越大,特征变化对预测值的影响越小。给稀疏分类特征设置更大的length_scale,就能降低它们的权重。
示例代码(结合GridSearchCV优化):
from sklearn.gaussian_process import GaussianProcessRegressor from sklearn.gaussian_process.kernels import RBF, WhiteKernel from sklearn.model_selection import GridSearchCV # 假设共有10个特征,前3个是稀疏分类特征(已编码为数值),后7个是数值特征 n_features = 10 # 初始化核函数,length_scale数组对应每个特征的长度尺度 kernel = RBF(length_scale=[1.0]*n_features) + WhiteKernel() # 参数网格:给前3个稀疏特征设置更大的length_scale候选值 param_grid = { 'kernel__k1__length_scale': [ [5.0,5.0,5.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0], [10.0,10.0,10.0,1.0,1.0,1.0,1.0,1.0,1.0,1.0] ] } gpr = GaussianProcessRegressor(kernel=kernel) grid_search = GridSearchCV(gpr, param_grid, scoring='r2', cv=5) grid_search.fit(X, y)
通过GridSearchCV可自动找到最优的特征长度尺度组合,实现对稀疏特征的加权抑制。
三、若坚持使用样本加权(非最优方案)
如果需要针对包含稀疏特征的样本降低权重,可通过闭包捕获权重数组,利用样本索引提取对应权重,解决交叉验证时的长度不匹配问题:
from sklearn.metrics import r2_score from sklearn.metrics import make_scorer # 预计算全量样本权重:包含稀疏类别的样本权重更低 sample_weights = ... # 你的全量样本权重数组,长度为329 def create_weighted_r2_scorer(weights): def weighted_r2(y_true, y_pred, X_test): # 提取测试集样本对应的权重 test_indices = X_test.index test_weights = weights.loc[test_indices] return r2_score(y_true, y_pred, sample_weight=test_weights) # 设置needs_X=True,让scorer传入X_test以获取索引 return make_scorer(weighted_r2, greater_is_better=True, needs_X=True) # 创建scorer并传入GridSearchCV weighted_r2_scorer = create_weighted_r2_scorer(sample_weights) grid_search = GridSearchCV(gpr, param_grid, scoring=weighted_r2_scorer, cv=5)
内容的提问来源于stack exchange,提问作者David Siret Marquès
相关产品推荐
相关产品推荐

