如何在只评分时使用sklearn的cross_validate加权样本?

0 投票
1 回答
30 浏览
提问于 2025-04-14 16:18

我正在处理一个回归任务,数据集里有真实样本和增强样本。增强样本是通过对真实样本进行轻微的扰动生成的。我想用交叉验证来选择表现最好的模型,使用的是sklearn这个库。

为此,我想要做到以下几点:

  • 在一个包含真实样本和增强样本的集合上训练模型。我不想让模型在拟合时考虑样本的来源(也就是说,这就像运行estimator.fit(..., sample_weights = [1,1,..., 1]一样)。
  • 根据模型在真实样本上的表现来评分。为此,我想把增强样本的权重设置为0(真实样本的权重设置为1)。

我该如何使用sklearncross_validate来实现这一点呢?

我尝试了以下代码:

from sklearn import model_selection
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score, mean_squared_error, make_scorer
import numpy as np

n_smpl, n_feats = 100, 5
arr_source = np.random.random((n_smpl, n_feats))
arr_target = np.random.random((n_smpl, n_feats))
arr_weight = np.random.randint(0, 2, n_smpl)  # 0 for augmented, 1 for authentic

model = RandomForestRegressor()
kfold_splitter = model_selection.KFold(n_splits=5, random_state=7, shuffle=True)
my_scorers = {
    "r2_weighted": make_scorer(r2_score, sample_weight=arr_weight),
    "mse_weighted": make_scorer(mean_squared_error, greater_is_better=False, sample_weight=arr_weight)
}

cv_results = model_selection.cross_validate(model, arr_source, arr_target, scoring = my_scorers, cv=kfold_splitter)

但是这返回了ValueError: Found input variables with inconsistent numbers of samples: [20, 20, 100]的错误。我明白这是因为cross_validate无法根据折叠来划分样本权重。

有没有办法让这个通过交叉验证运行?或者有什么其他的方法吗?

1 个回答

0

我在 Metadata-routing 这个功能里找到了我想要的东西,它可以让我们给评分器和估计器传递不同的参数。

使用这个功能的步骤如下:

  1. 首先,开启元数据路由功能:sklearn.set_config(enable_metadata_routing=True)
  2. 然后,关闭估计器的路由功能:RandomForestRegressor().set_fit_request(sample_weight=False)
  3. 接着,开启评分器的路由功能:make_scorer(r2_score).set_score_request(sample_weight=True)
  4. 最后,把样本权重传递给交叉验证的参数:model_selection.cross_validate(..., params={"sample_weight": arr_weight})

完整的代码如下:

from sklearn import model_selection, set_config
from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score, mean_squared_error, make_scorer
import numpy as np

n_smpl, n_feats = 100, 5
arr_source = np.random.random((n_smpl, n_feats))
arr_target = np.random.random((n_smpl, n_feats))
arr_weight = np.random.randint(0, 2, n_smpl)  # 0 for augmented, 1 for authentic

set_config(enable_metadata_routing=True)
model = RandomForestRegressor().set_fit_request(sample_weight=False)
kfold_splitter = model_selection.KFold(n_splits=5, random_state=7, shuffle=True)
my_scorers = {
    "r2_weighted": make_scorer(r2_score).set_score_request(sample_weight=True),
    "mse_weighted": make_scorer(mean_squared_error, greater_is_better=False).set_score_request(sample_weight=True)
}

cv_results = model_selection.cross_validate(model, arr_source, arr_target, scoring = my_scorers, cv=kfold_splitter, params={"sample_weight": arr_weight})

撰写回答