如何将特异性定义为模型评估的可调用评分者

时间:2017-12-07 21:31:55

标签: python-3.x machine-learning scikit-learn

我正在使用此代码来比较许多模型的性能:

from sklearn import model_selection

X = input data
Y = binary labels

models = []
models.append(('LR', LogisticRegression()))
models.append(('LDA', LinearDiscriminantAnalysis()))
models.append(('KNN', KNeighborsClassifier()))
models.append(('CART', DecisionTreeClassifier()))

results = []
names = []
scoring = 'accuracy'

for name, model in models:
    kfold = model_selection.KFold(n_splits=10, random_state=7)
    cv_results = model_selection.cross_val_score(model, X, Y, cv=kfold,scoring=scoring)
    results.append(cv_results)
    names.append(name)
    msg = "%s: %.2f (%.2f)" % (name, cv_results.mean(), cv_results.std())
    print(msg)

我可以使用'准​​确度'并且'召回'作为评分,这些将提供准确性和敏感性。如何创建一个能够提供特异性'

的得分手

特异性= TN /(TN + FP)

其中TN和FP在混淆矩阵中是真阴性和假阳性值

我试过这个

def tp(y_true, y_pred): 
error= confusion_matrix(y_true, y_pred)[0,0]/(confusion_matrix(y_true,y_pred)[0,0] + confusion_matrix(y_true, y_pred)[0,1])
return error

my_scorer = make_scorer(tp, greater_is_better=True)

然后

cv_results = model_selection.cross_val_score(model, X,Y,cv=kfold,scoring=my_scorer)

但它不适用于n_split> = 10 我在计算my_scorer

时遇到此错误

IndexError:索引1超出轴1的大小为1

2 个答案:

答案 0 :(得分:0)

你不能在scikit中获得特异性,但实际得到的是fpr,即:

fpr = 1 - specificity 

因此,为了获得特异性,您只需要从1中减去fpr

fpr可以使用roc_curve计算。

import numpy as np
from sklearn.metrics import roc_curve
y_true = np.array([1, 1, 2, 2])
y_pred = np.array([0.1, 0.4, 0.35, 0.8])
fpr, tpr, thresholds = roc_curve(y_true, y_pred)

print(fpr)
# array([ 0. ,  0.5,  0.5,  1. ])

specificity = 1 - fpr
# array([ 1. ,  0.5,  0.5,  0. ])

但是要完成上述工作,你需要通过训练模型来计算y_pred。

如果你想在cross_val_score中使用它,你可以像这样制作一个自定义得分手:

from sklearn.metrics import roc_curve
def specificity(y_true, y_pred):
    fpr, tpr, thresholds = roc_curve(y_true, y_pred)
    speci = 1 - fpr
    return speci

from sklearn.metrics import make_scorer
scorer = make_scorer(specificity)

然后:

cv_results = model_selection.cross_val_score(model, X, Y, cv=kfold,scoring=scorer)

注意:上述代码仅为二进制y提供正确的结果。

答案 1 :(得分:0)

如果将二进制分类器的recall_score参数更改为pos_label=0,则会得到特异性(默认为灵敏度,pos_label=1

scoring = {
    'accuracy': make_scorer(accuracy_score),
    'sensitivity': make_scorer(recall_score),
    'specificity': make_scorer(recall_score,pos_label=0)
}

希望这会有所帮助