【问题标题】:TPOT P@K custom scorerTPOT P@K 自定义记分器
【发布时间】:2019-12-17 11:49:47
【问题描述】:

我正在使用(并且喜欢)TPOT,但在实现自定义 P@K 记分器时遇到了麻烦。假设我想在 100 个预测(或任何数字 K)中获得尽可能多的真阳性,那么如何编码呢?我已经尝试使用下面的代码,但我一直收到管道尚未安装的错误,尽管标准记分器没有错误。

def pak(actual, predicted):
    k = 100
    if len(predicted) > k:
        predicted = predicted[:k]
    score = 0.0
    num_hits = 0.0

    for i, p in enumerate(predicted):
        if p in actual and p not in predicted[:i]:
            num_hits += 1.0
            score += num_hits / (i + 1.0)
    if not actual:
        return 0.0
    return score / min(len(actual), k)


my_custom_scorer = make_scorer(pak, greater_is_better=True)

【问题讨论】:

  • 仅运行此代码时是否遇到错误?如果没有,那么分享您收到错误的代码将有助于确定问题可能出在哪里。
  • 您能否提供一些关于您的得分手应该做什么的额外信息。我想这有问题。

标签: python scikit-learn precision-recall tpot


【解决方案1】:

实施算法以最大化真阳性数

我不建议这样做(请参阅最后的讨论),但根据我的理解,您希望最大限度地增加真阳性的数量。因此,您想创建一个自定义计分器并使用 TPOT 来优化真阳性率。我优化了您的功能,因为它取决于给定的数字k。如果您简单地计算真阳性率,则可以避免这种情况。我使用了来自 sklearn 的示例数据集,当然可以替换为任何其他数据集。

import numpy as np
import sklearn
from sklearn.metrics import make_scorer
import tpot
from tpot import TPOTClassifier
from sklearn.model_selection import train_test_split

def maximize_true_pos(y, y_pred):
    # true positives are marked with ones, all others with zeros
    true_pos = np.where((y==1) & (y_pred == 1), 1, 0)
    # sum true positives
    num_true_pos = np.sum(true_pos)
    # determine the true positive rate, how many of the positives were found?
    true_pos_div_total_tp = num_true_pos/np.sum(y)
    return true_pos_div_total_tp

iris = sklearn.datasets.load_breast_cancer()
# create the custom scorer 
max_true_pos_scorer = make_scorer(maximize_true_pos)
X_train, X_test, y_train, y_test = train_test_split(iris.data, iris.target,
                                                    train_size=0.75, test_size=0.25)
X_train.shape, X_test.shape, y_train.shape, y_test.shape

tpot = TPOTClassifier(verbosity=2, max_time_mins=2, scoring=max_true_pos_scorer)
tpot.fit(X_train, y_train)
y_pred = tpot.predict(X_test)

结果和方法的讨论

现在让我们通过查看y_pred 来了解这里优化了什么。

y_pred
array([1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
       1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1])

由于我们只想优化真阳性的数量,因此算法得知假阳性不会受到惩罚,因此将所有内容都设置为1 类(尽管y_true 并不总是1,因此准确度

要使用精确率或召回率(您可能知道,但为了完整起见我仍将其放在这里),可以简单地将 "precision""recall" 作为评分参数,以下列方式:

TPOTClassifier(scoring='recall')

【讨论】:

  • 也许我错了,但我的理解是 k 处的精确度并不仅仅最大化真阳性率。只需将所有预测设置为“1”,就可以最大化真阳性率。 k 处的精度询问在 k 处有多少真阳性 v 假阳性,因此奖励真阳性 惩罚 k 处的假阳性。还是我错过了什么?
  • 不,您是对的,但您要求从 100 个预测(或任何数字 K)中获得 尽可能多的真阳性,这就是我的自定义记分器所做的。如果您想获得具有最高 1 类概率的前 K 个项目的最高精度,请告诉我。我也可以为此写一个得分手
  • 我认为这不可能。如果我有 2000 个样本,其中 25% 是正例,并且我设置 K=100,那么您的算法如何选择具有最高水平的真正例的 100 个?它不会(平均)获得 25% 的真阳性吗?
猜你喜欢
  • 1970-01-01
  • 2019-10-30
  • 1970-01-01
  • 2021-07-27
  • 1970-01-01
  • 2019-06-13
  • 1970-01-01
  • 2014-05-24
  • 2013-01-09
相关资源
最近更新 更多