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

J J*_*Joe 5 machine-learning python-3.x 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)
Run Code Online (Sandbox Code Playgroud)

我可以使用“准确性”和“回忆”作为评分,这些将提供准确性和敏感性。我怎样才能创建一个给我“特异性”的记分员

特异性= 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)
Run Code Online (Sandbox Code Playgroud)

进而

cv_results = model_selection.cross_val_score(model, X,Y,cv=kfold,scoring=my_scorer)
Run Code Online (Sandbox Code Playgroud)

但它不适用于 n_split >=10 我在计算 my_scorer 时收到此错误

索引错误:索引 1 超出轴 1 的范围,大小为 1

小智 12

如果您更改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)
}
Run Code Online (Sandbox Code Playgroud)


Viv*_*mar -1

你无法在 scikit 中获得特异性,但你实际上可以获得的是fpr

fpr = 1 - specificity 
Run Code Online (Sandbox Code Playgroud)

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

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. ])
Run Code Online (Sandbox Code Playgroud)

但要使上述方法发挥作用,您需要通过训练模型来计算 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)
Run Code Online (Sandbox Code Playgroud)

进而:

cv_results = model_selection.cross_val_score(model, X, Y, cv=kfold,scoring=scorer)
Run Code Online (Sandbox Code Playgroud)

注意:上面的代码只会给出二进制的正确结果y