2

我正在使用(并且喜欢)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)
4

1 回答 1

2

实现算法以最大化真阳性的数量

我不建议这样做(请参阅最后的讨论),但根据我的理解,您希望最大限度地增加真阳性的数量。因此,您想创建一个自定义评分器并使用 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,因此准确率 < 1)。根据您的用例召回率(找到多少正面标记的案例)或精度(有多少正面标记的案例是相关的)比简单地让算法了解它应该将所有内容标记为正面是更好的指标。

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

TPOTClassifier(scoring='recall')
于 2019-08-14T21:40:52.493 回答