天天看點

聊聊機器學習分類問題常用的評價名額

作者:新語資料故事彙

一、 混淆矩陣

在機器學習領域,混淆矩陣(Confusion Matrix),又稱為「可能性矩陣」或「錯誤矩陣」。混淆矩陣是可視化工具,特别用于監督學習,在無監督學習一般叫做比對矩陣。在圖像精度評價中,主要用于比較分類結果和實際測得值,可以把分類結果的精度顯示在一個混淆矩陣裡面。

混淆矩陣的結構一般如下圖表示

聊聊機器學習分類問題常用的評價名額

混淆矩陣表達的含義:

TP(True Positive) :将正類預測為正類數,真實為0,預測為0

FN(False Negative):将正類預測為負類數,真實為0,預測為1

FP(False Positive) :将負類預測為正類數,真實為1,預測為0

TN(True Negative) :将負類預測為負類數,真實為1,預測為1

聊聊機器學習分類問題常用的評價名額

該矩陣常用于易于了解的二分類問題,但通過向混淆矩陣添加更多行和列,也可輕松應用于多分類問題。

舉例:如有150個樣本資料,預測為類I,類II,類III 各為50個。分類結束後得到的混淆矩陣為:

聊聊機器學習分類問題常用的評價名額

每一行之和表示該類别的真實樣本數量,每一列之和表示被預測為該類别的樣本數量。

第1行第1列中的43表示有43個實際歸屬第一類的執行個體被預測為第一類,同理,第1行第2列的2表示有2個實際歸屬為第一類的執行個體被錯誤預測為第二類。

混淆矩陣是對分類問題預測結果的總結。使用計數值彙總正确和不正确預測的數量,并按每個類進行細分,這是混淆矩陣的關鍵所在。

混淆矩陣顯示了分類模型的在進行預測時會對哪一部分産生混淆。它不僅可以讓您了解分類模型所犯的錯誤,更重要的是可以了解哪些錯誤類型正在發生。正是這種對結果的分解克服了僅使用分類準确率所帶來的局限性。

二、分類名額

從混淆矩陣當中,可以得到更進階的分類名額:Accuracy(精确率),Precision(正确率或者準确率),Recall(召回率),Specificity(特異性),Sensitivity(靈敏度)。

2.1 精确率(Accuracy)

精确率是最常用的分類性能名額。可以用來表示模型的精度,即模型識别正确的個數/樣本的總個數。一般情況下,模型的精度越高,說明模型的效果越好。

Accuracy = (TP+TN)/(TP+FN+FP+TN)

2.2 正确率或者準确率(Precision)

又稱為查準率,表示在模型識别為正類的樣本中,真正為正類的樣本所占的比例。一般情況下,查準率越高,說明模型的效果越好。

Precision = TP/(TP+FP)

2.3 召回率(Recall)

召回率又稱為查全率,召回率表現出在實際正樣本中,分類器能預測出多少。

Recall(召回率)= Sensitivity(敏感名額,True Positive Rate,TPR)= 查全率

表示的是,模型正确識别出為正類的樣本的數量占總的正類樣本數量的比值。一般情況下,Recall越高,說明有更多的正類樣本被模型預測正确,模型的效果越好。

Recall = TP/(TP+FN)

查準率和查全率是一對沖突的名額。一般來說,查準率高時,查全率往往偏低;當查全率高時,查準率往往偏低。

2.4 精确率(Accuracy)和正确率(Precision)的差別

精确率(Accuracy),不管是哪個類别,隻要預測正确,其數量都放在分子上,而分母是全部資料量,說明這個精确率是對全部資料的判斷。

而正确率(Precision)在分類中對應的是某個類别,分子是預測該類别正确的數量,分母是預測為該類别的全部數量。

即:Accuracy是對分類器整體上的精确率的評價,而Precision是分類器預測為某一個類别的精确評價。

2.5 Specificity(特異性)

特異性名額,表示的是模型識别為負類的樣本的數量,占總的負類樣本數量的比值。負正類率(False Positive Rate, FPR),計算公式為:

FPR=FP/(TN+FP)

計算的是模型錯識别為正類的負類樣本占所有負類樣本的比例,一般越低越好。

Specificity = 1 - FPR

2.6 Fβ_Score

Fβ的實體意義就是将正确率和召回率的一種權重平均,在合并的過程中,召回率的權重是正确率的β倍。

F1分數認為召回率和正确率同等重要,F2分數認為召回率的重要程度是正确率的2倍,而F0.5分數認為召回率的重要程度是正确率的一半。比較常用的是F1分數(F1 Score),是統計學中用來衡量二分類模型精确度的一種名額。

F1_Score:數學定義為 F1分數,又稱為平衡F分數(Balanced Score),它被定義為正确率和召回率的調和平均數。在 β=1 的情況,F1-Score的值是從0到1的,1是最好,0是最差。

是以我們知道,計算Precision,Recall,Specificity等隻是計算某一分類的特性,而Accuracy和F1-Score是判斷分類模型總體的标準。

三、ROC 曲線

聊聊機器學習分類問題常用的評價名額

橫坐标 :1-Specificity,僞正類率(False positive rate,FPR),預測為正但實際為負的樣本占所有負例樣本的比例。

縱坐标:Sensitivity,真正類率(True positive rate,TPR),預測為正且實際為正的樣本占所有正例樣本 的比例。

在一個二分類模型中,假設采用邏輯回歸分類器,其給出針對每個執行個體為正類的機率,那麼通過設定一個門檻值如0.6,機率大于等于0.6的為正類,小于0.6的為負類。對應的就可以算出一組(FPR,TPR),在平面中得到對應坐标點。随着門檻值的逐漸減小,越來越多的執行個體被劃分為正類,但是這些正類中同樣也摻雜着真正的負執行個體,即TPR和FPR會同時增大。門檻值最大時,對應坐标點為(0,0),門檻值最小時,對應坐标點(1,1)。

如下面這幅圖,(a)圖中實線為ROC曲線,線上每個點對應一個門檻值。

聊聊機器學習分類問題常用的評價名額

① 理想情況下,TPR應該接近1,FPR應該接近0。ROC曲線上的每一個點對應于一個threshold,對于一個分類器,每個threshold下會有一個TPR和FPR。比如Threshold最大時,TP=FP=0,對應于原點;Threshold最小時,TN=FN=0,對應于右上角的點(1,1)。

② P和N得分不作為特征間距離d的一個函數,随着門檻值theta增加,TP和FP都增加。

聊聊機器學習分類問題常用的評價名額

3.1 如何畫ROC曲線

對于一個特定的分類器和測試資料集,顯然隻能得到一個分類結果,即一組FPR和TPR結果,而要得到一個曲線,我們實際上需要一系列FPR和TPR的值,這又是如何得到的呢?我們先來看一下Wikipedia上對ROC曲線的定義:

In signal detection theory, a receiver operating characteristic (ROC), or simply ROC curve, is a graphical plot which illustrates the performance of a binary classifier system as its discrimination threshold is varied.

問題在于"as its discrimination threashold is varied"。如何了解這裡的"discrimination threashold"呢?我們忽略了分類器的一個重要功能"機率輸出",即表示分類器認為某個樣本具有多大的機率屬于正樣本(或負樣本)。通過更深入地了解各個分類器的内部機理,我們總能想辦法得到一種機率輸出。通常來說,是将一個實數範圍通過某個變換映射到(0,1)區間。

假如我們已經得到了所有樣本的機率輸出(屬于正樣本的機率),現在的問題是如何改變"discrimination threashold"?我們根據每個測試樣本屬于正樣本的機率值從大到小排序。下圖是一個示例,圖中共有20個測試樣本,"Class"一欄表示每個測試樣本真正的标簽(p表示正樣本,n表示負樣本),"Score"表示每個測試樣本屬于正樣本的機率。

聊聊機器學習分類問題常用的評價名額

接下來,我們從高到低,依次将"Score"值作為門檻值threshold,當測試樣本屬于正樣本的機率大于或等于這個threshold時,我們認為它為正樣本,否則為負樣本。舉例來說,對于圖中的第4個樣本,其"Score"值為0.6,那麼樣本1,2,3,4都被認為是正樣本,因為它們的"Score"值都大于等于0.6,而其他樣本則都認為是負樣本。每次選取一個不同的threshold,我們就可以得到一組FPR和TPR,即ROC曲線上的一點。這樣一來,我們一共得到了20組FPR和TPR的值,将它們畫在ROC曲線的結果如下圖:

聊聊機器學習分類問題常用的評價名額

當我們将threshold設定為1和0時,分别可以得到ROC曲線上的(0,0)和(1,1)兩個點。将這些(FPR,TPR)對連接配接起來,就得到了ROC曲線。當threshold取值越多,ROC曲線越平滑。

其實,我們并不一定要得到每個測試樣本是正樣本的機率值,隻要得到這個分類器對該測試樣本的"評分值"即可(評分值并不一定在(0,1)區間)。評分越高,表示分類器越肯定地認為這個測試樣本是正樣本,而且同時使用各個評分值作為threshold。我認為将評分值轉化為機率更易于了解一些。

四、AUC

4.1 AUC 值的計算

AUC (Area Under Curve) 被定義為ROC曲線下的面積,顯然這個面積的數值不會大于1。又由于ROC曲線一般都處于y=x這條直線的上方,是以AUC的取值範圍一般在0.5和1之間。使用AUC值作為評價标準是因為很多時候ROC曲線并不能清晰的說明哪個分類器的效果更好,而作為一個數值,對應AUC更大的分類器效果更好。

AUC的計算有兩種方式,梯形法和ROC AUCH法,都是以逼近法求近似值,具體見wikipedia。

4.2 AUC 意味着什麼

那麼AUC值的含義是什麼呢?根據(Fawcett, 2006),AUC的值的含義是:

The AUC value is equivalent to the probability that a randomly chosen positive example is ranked higher than a randomly chosen negative example.

這句話有些繞,我嘗試解釋一下:首先AUC值是一個機率值,當你随機挑選一個正樣本以及一個負樣本,目前的分類算法根據計算得到的Score值将這個正樣本排在負樣本前面的機率就是AUC值。當然,AUC值越大,目前的分類算法越有可能将正樣本排在負樣本前面,即能夠更好的分類。

從AUC判斷分類器(預測模型)優劣的标準:

AUC = 1,是完美分類器,采用這個預測模型時,存在至少一個門檻值能得出完美預測。絕大多數預測的場合,不存在完美分類器。

0.5< AUC <1,優于随機猜測。這個分類器(模型)妥善設定門檻值的話,能有預測價值。

AUC = 0.5,跟随機猜測一樣(例:丢銅闆),模型沒有預測價值。

AUC <0.5,比随機猜測還差;但隻要總是反預測而行,就優于随機猜測。

簡單說:AUC值越大的分類器,正确率越高。

三種 AUC 值示例:

聊聊機器學習分類問題常用的評價名額

五、為什麼使用 ROC 曲線

既然已經這麼多評價标準,為什麼還要使用ROC和AUC呢?因為ROC曲線有個很好的特性:當測試集中的正負樣本的分布變化的時候,ROC曲線能夠保持不變。在實際的資料集中經常會出現類不平衡(class imbalance)現象,即負樣本比正樣本多很多(或者相反),而且測試資料中的正負樣本的分布也可能随着時間變化。下圖是ROC曲線和Precision-Recall曲線的對比:

聊聊機器學習分類問題常用的評價名額

為什麼還要使用ROC和AUC呢?因為ROC曲線有個很好的特性:當測試集中的正負樣本的分布變化的時候,ROC曲線能夠保持不變。在實際的資料集中經常會出現類不平衡(class imbalance)現象,即負樣本比正樣本多很多(或者相反),而且測試資料中的正負樣本的分布也可能随着時間變化。ROC和Precision-Recall

在上圖中,(a)和(c)為ROC曲線,(b)和(d)為Precision-Recall曲線。(a)和(b)展示的是分類其在原始測試集(正負樣本分布平衡)的結果,(c)和(d)是将測試集中負樣本的數量增加到原來的10倍後,分類器的結果。可以明顯的看出,ROC曲線基本保持原貌,而Precision-Recall曲線則變化較大。

六、 動手實驗

依然用我們最熟悉的Iris資料集,分析探索工具依然用我們的資料科學/分析利器SmartNoteBook。

Iris資料集是常用的分類實驗資料集,由Fisher, 1936收集整理。Iris也稱鸢尾花卉資料集,是一類多重變量分析的資料集。

資料集包含150個資料樣本,分為3類,每類50個資料,每個資料包含4個屬性。可通過花萼長度,花萼寬度,花瓣長度,花瓣寬度4個屬性預測鸢尾花卉屬于(Setosa,Versicolour,Virginica)三個種類中的哪一類。

資料導入和準備:

# 導入需要的包
import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle
from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from sklearn.metrics import accuracy_score,precision_score,recall_score,f1_score
from numpy import interp
%matplotlib inline


# 擷取資料集,這裡我們友善起見隻導入兩種分類
iris = datasets.load_iris()
X = iris.data[50:150]
y = iris.target[50:150]


# 增加樣本記錄的數量(将數量翻6翻)
for i in range(6):
    X=np.append(X,X,axis=0)
    y=np.append(y,y,axis=0)           

為資料集增加一些噪音:

random_state = np.random.RandomState(2022)
n_samples, n_features = X.shape
X = np.c_[X, random_state.randn(n_samples, 32 )]
for i in range(4):
    X[:,i]=X[:,i]+ random_state.randn(1,n_samples )[0]           

檢視資料集的形狀:

X.shape           

(25600, 36)

标簽二值化:

y = label_binarize(y, classes=[0, 1])
n_classes = y.shape[1]           

訓練模型并預測:

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.3,random_state=0)
classifier = OneVsRestClassifier(svm.SVC(kernel='linear', probability=True))
y_score = classifier.fit(X_train, y_train).decision_function(X_test)
y_pred = classifier.predict(X_test)           

計算準确率、精确率、召回率、f1_score:

print ('accuracy is %s'% accuracy_score(y_test, y_pred))
print('precision is %s'% classifier.score(X_train, y_train))
print ('recall is %s'% recall_score(y_test, y_pred, average='macro'))
print ('f1-score is %s'% f1_score(y_test, y_pred, average='macro') )           

accuracy is 0.7516927083333333

precision is 0.7500558035714285

recall is 0.7516944913982669

f1-score is 0.7516926704446416

計算并展示混淆矩陣:

# 計算混淆矩陣
from sklearn import metrics
iris_confusion_matrix = metrics.confusion_matrix(y_test,y_pred)
iris_confusion_matrix           
# 直覺展示混淆矩陣
from pyecharts import options as opts
from pyecharts.charts import HeatMap


x=['versicolor','virginica']
y=['virginica','versicolor']
i=0
value=[]
for m in iris_confusion_matrix:
    j=0
    for v in m:
       value.append([i,1-j,int(v)])
       j=j+1
    i=i+1
value


c = (
    HeatMap()
    .add_xaxis(x)
    .add_yaxis(
        "",
        y,
        value,
        label_opts=opts.LabelOpts(is_show=True, position="inside"),
    )
    .set_global_opts(
        xaxis_opts=opts.AxisOpts(position='top',name="預測值",name_gap = 35,name_location = 'center'),
        yaxis_opts=opts.AxisOpts(name="真實值",name_gap = 35,name_location = 'center',axislabel_opts=opts.LabelOpts(rotate=90)),
        title_opts=opts.TitleOpts(title="混淆矩陣"),
        visualmap_opts=opts.VisualMapOpts(is_show=False,
                min_ = 0,
                max_ = 5000,
                range_color = ['#0d243b','#053b70'],
                )
    )
)
c.render_notebook()           
聊聊機器學習分類問題常用的評價名額

繪制ROC曲線:

fpr = dict()
tpr = dict()
roc_auc = dict()


fpr, tpr, _ = roc_curve(y_test, y_score)
roc_auc = auc(fpr, tpr)


plt.figure(dpi=100,figsize=(8,6))


plt.plot(fpr, tpr, color=color, lw=1.2) 
plt.plot([0, 1], [0, 1], 'k--', lw=1.2)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.legend(loc="lower right")
plt.show()           
聊聊機器學習分類問題常用的評價名額

《新語資料故事彙,數說新語》 科普資料科學、講述資料故事,深層次挖掘資料價值。歡迎各位朋友投稿!

微信号|SnbDataStory

《新語資料故事彙,數說新語》

繼續閱讀