混淆的 AUC ROC 分数

数据挖掘 分类 随机森林 逻辑回归 交叉验证 奥克
2021-10-09 06:36:29

我正在研究二进制分类问题,我尝试评估一些分类算法(LR、决策树、随机森林......)的性能。我正在使用AUC ROC作为评分函数的交叉验证技术(以避免过度拟合)来比较算法的性能,但是使用Random forestAdbBoost我得到了一个奇怪的结果,我有一个完美的AUC_ROC分数(即 = 1)尽管该算法的召回率(TPR)和FPR分别不同于1和0。

在此处输入图像描述

def FPR(y_true, y_pred):
    tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
    result = fp / (fp+tn)
    return result
def FNR(y_true, y_pred):
    tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
    result = fn / (tp+fn)
    return result
FPR_scorer = make_scorer(FPR)
FNR_scorer = make_scorer(FNR)   

def get_CrossValResults2(model,cv_rst,bestIndx):
    best=pd.DataFrame.from_dict(cv_rst).iloc[bestIndx]
    roc="{:.12f}".format(best['mean_test_roc_auc'])
    acc ="{:.0%}".format(best['mean_test_accuracy'])
    prec ="{:.0%}".format(best['mean_test_precision'])
    rec ="{:.0%}".format( best['mean_test_recall'])
    f1 ="{:.0%}".format(best['mean_test_f1'])
    r2="{:.2f}".format(best['mean_test_r2'])
    g_mean="{:.2f}".format(best['mean_test_gmean'])
    pr_auc="{:.8f}".format(best['mean_test_pr'])
    fnr="{:.0%}".format(best['mean_test_fnr'])
    fpr="{:.0%}".format(best['mean_test_fpr'])
    rst = pd.DataFrame([[ model, acc,prec,rec,fpr,fnr,f1,roc,pr_auc,g_mean,r2]],columns = ['Model', 'Accuracy', 'Precision', 'Recall','FPR','FNR', 'F1-Score','ROC_auc','PR_auc','gmean','r2'])
    return rst
      
cross_val_rst = pd.DataFrame(columns = ['Model', 'Accuracy', 'Precision', 'Recall','FPR','FNR', 'F1-Score','ROC_auc','PR_auc','gmean','r2'])    
        
scoring = {'accuracy':'accuracy','recall':'recall','precision':'precision','fpr':FPR_scorer,'fnr':FNR_scorer,'f1':'f1' ,'roc_auc':'roc_auc','pr':'average_precision','gmean':Gmean_scorer,'r2':'r2'}    
param_grid = {'n_estimators': [200], 
             'max_depth': [80,90],
              'min_samples_leaf': [2,3, 4],
            'min_samples_split': [2,5,12],
            'criterion': [ 'gini'],
             'class_weight' : [class_weights], 'n_jobs' : [-1]} 
clf = GridSearchCV(RandomForestClassifier(class_weight=class_weights), param_grid, cv=kfold,scoring=scoring,refit=refit)#Fit the model
bestmodel = clf.fit(X,Y)
     
cross_val_rst = cross_val_rst.append(get_CrossValResults2(model='Random Forrest',bestIndx=bestmodel.best_index_,cv_rst=bestmodel.cv_results_),ignore_index=True)
2个回答

哦,我想我终于明白了。这只是一个平均问题:对于您的 k 折交叉验证中的每一折,您都会得到完美的 auROC,但在默认阈值 0.5 时,您的硬分类器(对于每一折)有时会FR=0R<1, 但其他时候FR>0R=1. 然后平均你可以得到两者意思是(FR)>0意思是(R)<1.

要检查,请查看cv_results_表格,尤其是每个测试折叠分数 ( split<i>_test_<xyz>),而不仅仅是mean_test_<xyz>分数。

我认为召回和 FPR 是在 scikit-learn 中使用 0.5 的阈值计算的。另一方面,ROC AUC 对模型阈值是透明的。我鼓励你在 scikit-lego中探索thresholder来检查这个方向。

AUC = 1 但 FPR 不好的一个例子是,如果您使用 0.5 作为阈值,您的模型会完美地分割您的样本,但正样本的分数在 0.2 到 0.4 之间,而负样本的分数在 0 到 0.2 之间。