在 GridSearchCV 中使用 sample_weight

Posted

技术标签:

【中文标题】在 GridSearchCV 中使用 sample_weight【英文标题】:Using sample_weight in GridSearchCV 【发布时间】:2012-10-14 15:21:48 【问题描述】:

是否可以执行 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)

>> ValueError:估计器 SVC 的参数 sample_weight 无效


编辑:我通过获取最新的 scikit-learn 版本并使用以下内容解决了这个问题:

gs.fit(Xtrain, ytrain, fit_params='sample_weight': sw_train)

【问题讨论】:

如果您有答案,请将其作为答案发布并接受。否则,问题就会悬而未决。 我确认fit_params 技巧是正确的答案。请回答你自己并验证你的答案。 @ogrisel 会不会导致 fit 被调用时使用每个折叠的整个权重列表,而不仅仅是折叠中数据点的权重? 这是一个很好的评论,但这种情况实际上是由内部交叉验证例程正确处理的:github.com/scikit-learn/scikit-learn/blob/master/sklearn/… @ogrisel 很好的发现,谢谢。 【参考方案1】:

只是想解决这个长期悬而未决的问题......

您需要获取最新版本的 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 方法 sw_train的形状是什么?我试过sw_train=[1:1],但它不起作用。任何帮助表示赞赏。【参考方案2】:

以前的答案现在已经过时了。字典fit_params 应该传递给fit 方法。

来自GridSearchCV 的文档:

fit_params:字典,可选

传递给 fit 方法的参数。

自 0.19 版起已弃用:作为构造函数参数的 fit_params 在 0.19 版中已弃用,并将在 0.21 版中删除。而是将 fit 参数传递给 fit 方法。

【讨论】:

有没有人确认这可以与sample_weight 一起正常工作? GridSearchCV 使用 Xtrainytrain 的不同子集重复调用估计器的 fit() 方法。它是否每次都使用相应的样本权重子集?我猜它没有;它每次只调用fit(..., **fit_params)。这对于 verbose 等与特定样本无关的参数非常有效。 我曾经对sample_weight 过去的工作方式有过类似的疑问。您可以在此处查看问题和答案;我认为这个问题的动机与你在这里表达的同样的担忧,但它有点老了。我不知道sklearn 的较新版本是否以更直观的方式工作。 ***.com/questions/49581104/… 谢谢。我进行了更多搜索,发现github.com/scikit-learn/scikit-learn/issues/2879,这表明GridSearchCV 现在被编程为在每次调用估计器的fit() 方法时传递sample_weight 的正确子集。人们仍然不满意,因为没有简单的方法可以使用sample_weightGridSearchCV 中进行评分。 啊!有趣的。很高兴知道至少在这方面取得了一些进展。我链接的线程中的解决方案是功能性的,但在简单性方面确实有一些不足之处。【参考方案3】:

在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)

【讨论】:

这里是讨论,我注意到这种行为仍然存在于 0.17 sourceforge.net/p/scikit-learn/mailman/message/34191031 sw_train的形状是什么?我试过sw_train=[1:1],但它不起作用。任何帮助表示赞赏。 @AzizJaved 参数可以在特定classifier 的文档中找到。在这种情况下,它是一个一维数组,每个样本有一个权重(示例)。【参考方案4】:

以下适用于 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)

【讨论】:

【参考方案5】:

OP 的编辑和其他答案并不完全正确。虽然拟合 fit_params='sample_weight': weights 有效,但这些权重不会用于计算验证损失! (github issue)。

因此,交叉验证将报告未加权损失,因此超参数调整可能会被引导到错误的方向。

这是我使用准确性作为指标对类权重进行交叉验证的解决方法。还应该与其他指标一起使用。

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
)

【讨论】:

您能详细说明一下吗?在这种情况下,fit_params 应该是什么?是class_weight: weights_array吗?这是否适合并使用指定的权重数组进行评估?我不清楚这段代码应该做什么。 如您所见,这是一个非常高级和复杂的示例。 OP 已经提供了一个答案以及其他答案,说“使用fit_params,所以我在这里的答案确实是另一种情况。如果我要写一个关于权重拟合的适当教程,然后解释我的解决方法,它会变成一篇中等文章。 尽管如此,fit_params 是一个参数字典,将传递给估计器的 .fit 方法。当使用 sklearn 管道与编写自定义循环时,您突然无法控制深层行为,例如API 不提供为不平衡训练指定 class_weights 的方法。但是您可以使用fit_params 所以,fit_params 中的 class_weights 应该符合 estimator.fit(..., class_weights=weights_array) -- 参见此线程 ***.com/questions/30972029/…

以上是关于在 GridSearchCV 中使用 sample_weight的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Scikit-Learn 的详细输出中估计 GridSearchCV 的进度?

pipeline结合GridSearchCV的一点小介绍

随机森林过拟合

为啥在 GridSearchCV 中使用 StandardScaler 时会得到不同的结果?

我正在使用 GridSearchCV 训练一个 Ann 机器学习模型,但在 gridSearchCV 中遇到了 IndexError

如何在 python 中使用交叉验证执行 GridSearchCV