如何在只评分时使用sklearn的cross_validate加权样本?
我正在处理一个回归任务,数据集里有真实样本和增强样本。增强样本是通过对真实样本进行轻微的扰动生成的。我想用交叉验证来选择表现最好的模型,使用的是sklearn
这个库。
为此,我想要做到以下几点:
- 在一个包含真实样本和增强样本的集合上训练模型。我不想让模型在拟合时考虑样本的来源(也就是说,这就像运行
estimator.fit(..., sample_weights = [1,1,..., 1]
一样)。 - 根据模型在真实样本上的表现来评分。为此,我想把增强样本的权重设置为0(真实样本的权重设置为1)。
我该如何使用sklearn
的cross_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 这个功能里找到了我想要的东西,它可以让我们给评分器和估计器传递不同的参数。
使用这个功能的步骤如下:
- 首先,开启元数据路由功能:
sklearn.set_config(enable_metadata_routing=True)
- 然后,关闭估计器的路由功能:
RandomForestRegressor().set_fit_request(sample_weight=False)
- 接着,开启评分器的路由功能:
make_scorer(r2_score).set_score_request(sample_weight=True)
- 最后,把样本权重传递给交叉验证的参数:
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})