是否可以执行GridSearchCV
(以获得最佳的SVM的C),同时使用scikit-learn指定sample_weight
?
这是我的代码和我面临的错误:
gs = GridSearchCV(
svm.SVC(C=1),
[{
'kernel': ['linear'],
'C': [.1, 1, 10],
'probability': [True],
'sample_weight': sw_train,
}]
)
gs.fit(Xtrain, ytrain)
>> 值错误:估算器 SVC 的参数sample_weight无效
编辑:我通过获取最新的scikit-learn版本并使用以下方法解决了该问题:
gs.fit(Xtrain, ytrain, fit_params={'sample_weight': sw_train})
只是想结束这个悬而未决的问题......
您需要获取最新版本的 SKL 并使用以下内容:
gs.fit(Xtrain, ytrain, fit_params={'sample_weight': sw_train})
但是,将fit_params
传递给构造函数更符合文档:
gs = GridSearchCV(svm.SVC(C=1), [{'kernel': ['linear'], 'C': [.1, 1, 10], 'probability': [True], 'sample_weight': sw_train}], fit_params={'sample_weight': sw_train})
gs.fit(Xtrain, ytrain)
以前的答案现在已经过时了。字典fit_params
应传递给fit
方法。
来自 GridSearchCV 的文档:
fit_params:字典,可选
要传递给 fit 方法的参数。
自版本 0.19起已弃用:作为构造函数参数fit_params在版本 0.19 中已弃用,并将在版本 0.21 中删除。改为将拟合参数传递给拟合方法。
在 0.16.1 版本中,如果使用Pipeline
,则需要将参数传递给构造函数GridSearchCV
:
clf = pipeline.Pipeline([('svm', svm_model)])
model = grid_search.GridSearchCV(estimator = clf, param_grid=param_grid,
fit_params={'svm__sample_weight': sw_train})
以下作品在 Sklearn 0.23.1 中,
grid_cv = GridSearchCV(clf, param_grid=param_grid,
scoring='recall', n_jobs=-1, cv=10)
grid_cv.fit(x_train_orig, y=y_train_orig,
sample_weight=my_sample_weights)
OP的编辑和其他答案并不完全正确。虽然对于拟合fit_params={'sample_weight': weights}
有效,但这些权重不会用于计算验证损失!(GitHub问题)。
因此,交叉验证将报告未加权损失,因此超参数调整可能会被引导到错误的方向。
这是我使用准确性作为指标对类权重进行交叉验证的解决方法。还应与其他指标一起使用。
from sklearn.metrics import accuracy_score
from sklearn.utils import compute_sample_weight
from sklearn.metrics import make_scorer
def weighted_accuracy_eval(y_pred, y_true, **kwargs):
balanced_class_weights_eval = compute_sample_weight(
class_weight='balanced',
y=y_true
)
out = accuracy_score(y_pred=y_pred, y_true=y_true, sample_weight=balanced_class_weights_eval, **kwargs)
return out
weighted_accuracy_eval_skl = make_scorer(weighted_accuracy_eval)
gridsearch = GridSearchCV(
estimator=model,
scoring=weighted_accuracy_eval,
param_grid=paramGrid,
)
cv_result = gridsearch.fit(
X_train,
y_train,
fit_params=fit_params
)
很好的问题和伟大的答案!(感谢@Sycorax、@AN6U5和@user1771485)。所有这些都帮助我找到了特定情况的答案,我需要在 GridSearchCV 期间使用sample_weight,但我的估计器是使用 Pipeline 获得的。该问题与以前的解决方案不同,因为管道不支持fit_param;事实上,如果你尝试在(GridSearchCV)的拟合步骤中使用fit_param = {... }
,你会得到
Pipeline.fit 不接受 fit_param 参数。您可以使用stepname__parameter格式将参数传递给管道的特定步骤,例如
Pipeline.fit(X, y, logisticregression__sample_weight=sample_weight)
我使用的管道是
pipe = Pipeline(steps=[('normalizer', norm), ('estimator', svr)])
其中norm
是规范化步骤、svr = SVR()
和参数网格
parameters_svr = dict (estimator = [svr], estimator__kernel = ['rbf', 'sigmoid'], ...)
然后,按照@user1771485的建议
grid = GridSearchCV (estimator = pipe, param_grid = parameters_svr, cv = 3,
scoring = 'neg_mean_squared_error',
return_train_score = True, refit = True, n_jobs = -1)
最后,(真正重要的部分)
grid.fit (X,y, estimator__sample_weight= weights)
在scikit-learn版本1.1.1中,你可以将sample_weight
直接传递给GridSearchCV
的fit()
。
例如:
def get_weights(cls):
class_weights = {
# class-labels based on your dataset.
0: 1,
1: 4,
2: 1,
}
return [class_weights[cl] for cl in cls]
grid = {
"max_depth": [3, 4, 5, 6],
"n_estimators": range(20, 70, 10),
"learning_rate": np.arange(0.25, 0.50, 0.05),
}
xgb_clf = XGBClassifier(random_state=42, n_jobs=-1)
xgb_cvm = GridSearchCV(estimator=xgb_clf, param_grid=grid, n_jobs=-1, cv=5)
xgb_cvm.fit(X, y, sample_weight=get_weights(y))