TPOT P @ K自定义评分器

时间:2019-08-09 17:58:30

标签: python scikit-learn precision-recall tpot

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

1 个答案:

答案 0 :(得分: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')