1. 程式人生 > >機器學習模型評估混淆矩陣、ROC曲線和AUC以及PR曲線

機器學習模型評估混淆矩陣、ROC曲線和AUC以及PR曲線

       在機器學習中,當我們基於某個業務建立模型並訓練後,接下來我們需要評判模型好壞的時候需要基於混淆矩陣,ROC和AUC等來進行輔助判斷。

混淆矩陣也叫精度矩陣,是用來表示精度評價,為N *N的矩陣,用來判別分類好壞的指標。

混淆矩陣中有以下幾個概念:

TP(True Positive): 被判定為正樣本,實際也為正樣本

FN(False Negative):偽陰性 ,被判定為負樣本,實際為正樣本

FP(False Positive):偽陽性,被判斷為正樣本,實際為負樣本

TN(True Negative):被判斷為負樣本,實際為負樣本

另外模型的評判的時候大家會談到如下幾個指標概念:

精確率(Precision):也稱之為查準率,代指實際為正樣本你預測也為正樣本佔整體你預測為正樣本的比重

precision=\frac{TP}{TP+FP}

召回率(Recall):也稱為查全率,代指實際為正樣本你預測也為正樣本佔整體實際為正樣本的比重 。換句話說可以認為,實際為正樣本中你在預測中也正確預測為正樣本的佔比有多大。

Recall=\frac{TP}{TP+FN}

這些概念很繞,建議多讀幾遍,多思考幾次,慢慢的就有了一個印象。

       所以在模型評判的時候我們需要把握最終看重的結果,比如在流失模型中,流失使用者佔比始終是小部分,那麼我們要儘可能全的把這部分小樣本資料找到,那麼會更看重查全率,也就是Recall.

利用Python來定義混淆矩陣如下:

通過sklearn匯入混淆矩陣

from sklearn.metrics import confusion_matrix,roc_curve,auc,precision_recall_curve,average_precision_score
from sklearn.model_selection import learning_curve
import matplotlib.pyplot as plt
def confusion_metrix(y,y_p):
    Confusion_matrix=confusion_matrix(y,y_p) #y代表真實值,y_p 代表預測值
    plt.matshow(Confusion_matrix)
    plt.title("混淆矩陣")
    plt.colorbar()
    plt.ylabel("實際型別")
    plt.xlabel("預測型別")

通過呼叫sklearn的confusion_matrix我們就可以得到混淆矩陣,通過畫圖來畫出對應的圖形

ROC(Receiver Operating Characteristic): 是一條曲線,由FPR和TPR的點連成。橫軸是FPR,縱軸是TPR  

TPR=\frac{TP}{TP+FN}             

FPR=\frac{FP}{FP+TN}

AUC(Area Under the Curve):ROC的曲線面積就是AUC值。AUC主要用於衡量二分類問題中機器學習演算法效能或者泛化能力。

下面截圖ROC曲線

ROC曲線重點了解下這幾個節點

(0,1)點:代表FPR=0,TPR=1; 最好的情況,所有正樣本都被正確的預測了,並且沒有負樣本被人為是正樣本。

(1,0)點:代表FPR=1,TPR=0;最壞的情況,表明所有的正樣本都被錯誤的認為是負樣本

(0,0)點:代表FPR=0,TPR=0;分類器將所有的樣本都判定為負樣本

(1,1)點:代表FPR=1,TPR=1;分類器將所有的樣本都判定為正樣本

      如上圖,有一條紅色的虛線,y=x ,這條曲線的面積為0.5 ,這裡是代表的如果是隨機猜測的話,AUC=0.5.如果我們得到的ROC曲線在y=x下面,AUC<0.5,則表明分類器不合格,還不如亂猜測。

在實際中由於側重的點不同,所以我們需要明白側重在哪,如果在實際中結果重在覆蓋,我們應該更加註重True Positive高,如果是重在準確,我們則應該更加註重False Positive低

那麼怎麼通過ROC曲線來判斷True Positive和False Positive呢? 這裡我們如果看到曲線越往左上凸越好,這樣得到的True Positive 就越高,對應的False Positive越低,

上圖來自於我做的邏輯迴歸分類,最終得到的模型AUC=0.99。

PR曲線: 是由精確率和召回率的點連成的線,橫軸為Recall ,縱軸為Precision,

在PR曲線中越右上凸越好,PR想要Precision 和Recall同時高

如果樣本表現的極不均衡的時候,哪個曲線更好呢?通過ROC曲線和PR曲線的含義,我們事先假設正樣本非常少,負樣本非常多,這樣TN會非常大,將FPR拉低,最後的曲線會表現的非常好,但是我們再反過來看PR曲線,我們會發現曲線反而表現的沒那麼好。所以我們在判斷的時候不能由單一指標來下決定。

實現程式碼如下:

def plot_PR(model,x_test,y_test):#繪製PR曲線
    y_pro=model.predict_proba(x_test)
    precision,recall,thresholds=precision_recall_curve(y_test,y_pro[:,1])
    average_precision = average_precision_score(y_test, y_pro[:, 1])
    ax2 = plt.subplot(224)
    ax2.set_title("Precision_Recall Curve AP=%0.2f"%average_precision,verticalalignment='center')
    plt.step(precision, recall,where='post',alpha=0.2,color='r')
    plt.fill_between(recall,precision,step='post',alpha=0.2,color='b')
    plt.xlim([0.0, 1.0])
    plt.ylim([0.0, 1.05])
    plt.ylabel('Precision')
    plt.xlabel('Recall')

def plot_ROC(model,x_test,y_test):#繪製ROC和AUC,來判斷模型的好壞
    y_pro=model.predict_proba(x_test)
    false_positive_rate,recall,thresholds=roc_curve(y_test,y_pro[:,1])
    roc_auc=auc(false_positive_rate,recall)
    ax3=plt.subplot(223)
    ax3.set_title("Receiver Operating Characteristic",verticalalignment='center')
    plt.plot(false_positive_rate,recall,'b',label='AUC=%0.2f'%roc_auc)
    plt.legend(loc='lower right')
    plt.plot([0,1],[0,1],'r--')
    plt.xlim([0.0,1.0])
    plt.ylim([0.0,1.0])
    plt.ylabel('Recall')
    plt.xlabel('false_positive_rate')

學習曲線:主要用來提高學習演算法效能,通過對學習中的過程進行判斷,來進一步調整學習引數。來判斷模型是否過擬合。

我們通過繪製可以發現效果如下:

對應實現程式碼如下:

def plot_learning_cruve(model,x,y,train_sizes,n_jobs):#繪製學習曲線來判斷模型的學習情況
    #構建學習曲線評估器,train_size:控制用於生成學習曲線的樣本的絕對或相對數量
    cv=10  #ShuffleSplit(4,n_iter=3,test_size=0.2,random_state=0)
    train_sizes,train_scores,test_scores=learning_curve(estimator=model,X=x,y=y,train_sizes=train_sizes,cv=cv,n_jobs=n_jobs)
    #統計結果
    train_score_mean=np.mean(train_scores,axis=1)
    train_score_std=np.std(train_scores,axis=1)
    test_score_mean=np.mean(test_scores,axis=1)
    test_score_std=np.std(test_scores,axis=1)
    #繪製效果圖
    ax1=plt.subplot(211)
    ax1.set_title('learning curve')
    plt.fill_between(train_sizes,train_score_mean-train_score_std,train_score_mean+train_score_std,alpha=0.1,color='r')
    plt.fill_between(train_sizes,test_score_mean+test_score_std,test_score_mean-test_score_std,alpha=0.15,color='green')
    plt.plot(train_sizes, train_score_mean, color='blue', marker='o', markersize=5, label='training score')
    plt.plot(train_sizes,test_score_mean,'o-',color='g',label='Cross_validation score')
    plt.grid()
    plt.xlabel('training samples')
    plt.ylabel('Accuracy')
    plt.legend(loc='lower right')
    plt.ylim([0.2,1.01])

最後作圖如下: