【问题标题】:Using sample_weight in GridSearchCV在 GridSearchCV 中使用 sample_weight
【发布时间】: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 很好的发现,谢谢。

标签: python scikit-learn


【解决方案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 的较新版本是否以更直观的方式工作。 stackoverflow.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) -- 参见此线程 stackoverflow.com/questions/30972029/…
    猜你喜欢
    • 2018-09-09
    • 2017-11-23
    • 1970-01-01
    • 2018-06-27
    • 2019-08-12
    • 1970-01-01
    • 2018-10-19
    • 2014-05-12
    相关资源
    最近更新 更多