【问题标题】:Getting a Scoring Function by Name in scikit-learn在 scikit-learn 中按名称获取评分函数
【发布时间】:2021-06-22 03:11:36
【问题描述】:

scikit-learn 中,有一个评分函数的概念。如果我们有一些预测标签和真实标签,我们可以通过调用scoring(y_true, y_predict) 来获得分数。这种评分函数的一个例子是sklearn.metrics.accuracy_score

评分函数不要与scorer混淆,它是一个可以称为scorer(estimator, X, y_true)的对象。

scikit-learn 中有很多内置记分器。可以通过他们的字符串名称找到这些得分手。例如,我们可以通过调用sklearn.metrics.get_scorer("accuracy")/

来获取名称'accuracy'对应的scorer

但事实证明,没有明显的机制可以通过名称在运行时通过将名称作为字符串传入来访问内置评分函数 >。例如,无法通过名称accuracy 访问sklearn.metrics.accuracy_score

例如,如果在运行时,程序知道评分函数的名称包含在变量 name 中,我正在寻找一种机制 get_scoring_function(),这样,get_scoring_function(name) 将返回评分函数句柄.请注意,此名称 name 在编写脚本时是未知的。

有没有办法在运行时通过将名称作为字符串传递来访问内置的评分函数

【问题讨论】:

  • 我的意思是我想通过它的名字来访问这个函数——即“准确度”
  • 我稍微澄清了这个问题,强调我试图通过它的字符串名称来获取一个函数,并且我追求的是一个函数,而不是一个记分员。
  • 这不是我真正的问题。我真正的问题是通过他们的名字来获得内置的评分功能。例如,'f1' 应该给我 f1 评分功能,accuracy 应该给我准确度评分功能,f1-macro 应该给我 f1-macro 评分功能。我正在寻找与 sklearn.metrics.get_scorer() 平行的访问器,但返回的是函数而不是记分器。
  • 我想我明白了现在的困惑所在。这是因为我没有说我想在运行时按名称获取函数。在运行时似乎是强调的关键词。对此感到抱歉。

标签: scikit-learn


【解决方案1】:

您可以使用get_scorer()函数,它接受一个字符串作为参数,然后获取返回对象的_score_func属性。

例如

from sklearn.metrics import get_scorer

get_scorer('accuracy')._score_func(y_true, y_pred) 

等价于

from sklearn.metrics import accuracy_score

accuracy_score(y_true, y_pred)

【讨论】:

    【解决方案2】:

    我自己也面临过这个任务,我还没有找到比sklearn.metrics.get_scorer 函数更好的按名称访问指标的方法,但它的缺点是你必须在那里传递一个估计器,而不是预测。我尝试使用@collinb9 建议,但你看,你必须在那里访问一个受保护的方法,在我的例子中,它导致了令人不快的后果,即错误计算的指标。

    这是一个显示此问题的简短示例。

    from sklearn import datasets, model_selection, linear_model, metrics
    
    features, labels = datasets.make_regression(1000, random_state=123)
    train_features, test_features, train_labels, test_labels = model_selection.train_test_split(features, labels, test_size=0.1, random_state=567)
    model = linear_model.LinearRegression()
    model.fit(train_features, train_labels)
    
    print(f'variant 1 neg_mse = {metrics.get_scorer("neg_mean_squared_error")(model, test_features, test_labels)}')
    print(f'variant 1 neg_rmse = {metrics.get_scorer("neg_root_mean_squared_error")(model, test_features, test_labels)}\n')
    
    preds = model.predict(test_features)
    print(f'variant 2 mse = {metrics.mean_squared_error(test_labels, preds)}')
    print(f'variant 2 rmse = {metrics.mean_squared_error(test_labels, preds, squared=False)}\n')
    
    print(f'protected neg_mse = {metrics.get_scorer("neg_mean_squared_error")._score_func(test_labels, preds)}')
    print(f'protected neg_rmse = {metrics.get_scorer("neg_root_mean_squared_error")._score_func(test_labels, preds)}')
    

    这个程序的输出将是:

    variant 1 neg_mse = -2.142587870436064e-25
    variant 1 neg_rmse = -4.628809642268803e-13
    
    variant 2 mse = 2.142587870436064e-25
    variant 2 rmse = 4.628809642268803e-13
    
    protected neg_mse = 2.142587870436064e-25
    protected neg_rmse = 2.142587870436064e-25
    

    您会看到,使用受保护方法计算的指标不同。首先,我们下令得到负值,但得到了正值(应该提到,对于variant 2 指标,我们并不暗示负值)。其次,neg_mseneg_rmse 的值相等但应该不同。

    如果我们去sklearn metrics的源代码,我们会看到:

    1. This is how _score_func is called:乘以符号,这就是我们失去负值的地方。
    2. This is how scorers are made:你看,neg_root_mean_squared_error_scorer 有额外的参数squared=False。此参数在metrics.mean_squared_error 中明确说明为可选参数,因此您不会出错。我们可以将此参数作为关键字参数传递给_score_fun,至少我们会得到一个正确的绝对值:
    print(f'protected neg_rmse = {metrics.get_scorer("neg_root_mean_squared_error")._score_func(test_labels, preds, squared=False)}')
    
    protected neg_rmse = 4.628809642268803e-13
    

    为了简单起见,据我所知,我已经展示了按名称获取 sklearn 指标的唯一方法(顺便说一句,您可以找到完整的名称列表 here),并且使用 protected 是不安全的你不应该使用的方法。顺便说一句,我使用的是 sklearn version=0.24.2。

    【讨论】:

      猜你喜欢
      • 2018-05-14
      • 2014-12-05
      • 2019-03-16
      • 1970-01-01
      • 1970-01-01
      • 2016-04-22
      • 2017-10-21
      • 2014-08-09
      相关资源
      最近更新 更多