分類模型的演算法效能評價

归去_来兮發表於2024-07-09

一、概述

  分類模型是機器學習中一種最常見的問題模型,在許多問題場景中有著廣泛的運用,是模式識別問題中一種主要的實現手段。分類問題概況起來就是,對一堆高度抽象了的樣本,由經驗標定了每個樣本所屬的實際類別,由特定演算法訓練得到一個分類器,輸入樣本屬性即自動計算出其所屬類別,從而完成特定的識別任務。依實現原理的不同,分類演算法有很多種,常見的如支援向量機、決策樹、k近鄰、樸素貝葉斯......,以及設計了的各種人工神經網路等。在特定問題中,演算法效能的評價是一個重要的方面,它一般由學習器在測試資料中的效能表現來直接衡定,常見的評價指標有準確率、精準度(查準率)、召回率(查全率)、F1值、ROC-AUC值、Kappa係數等。

二、評價指標——二分類情形

  二分類模型是較常見和較一般化的情形,它預測的混淆矩陣可表示為

其中,
  TP(True Positive,真正例)為被正確劃分為正例的樣本數;
  FP(False Positive,假正例)為被錯誤劃分為正例的樣本數;
  TN(True Negative,真負例)為被正確劃分為負例的樣本數;
  FN(False Negative,假負例)為被錯誤劃分為負例的樣本數。

1.準確率(accuracy)

  準確率是被預測正確的樣本數與樣本總數\(N\)的比值,比較直觀地反映了學習器的效能。表示式為

\[Accuracy=\frac{TP+TN}{N} \]

2. 精準度(precision)

   精準度是TP(真正例)佔預測為正例樣本數的百分比,它表徵了預測的正例中有多少有效成分,也叫做查準率。表示式為

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

3. 召回率(recall)

  召回率是TP(真正例)與真實正樣本數的比值,它表徵了所有的有效內容有多少被檢測了出來,也叫做查全率、靈敏度(sensitive)。表示式為

\[recall=\frac{TP}{TP+FN} \]

4. F度量(F-Measure, F-Score)

  我們希望學習器的查準率和查全率都高,而查準率和查全率往往是一對矛盾的度量,查準率高時,查全率往往偏低;查全率高時,查準率往往偏低。此時可以用F度量來綜合評估精準度(查準率)和召回率(查全率),數值越高學習器越理想。它的一般形式記作\(F_\beta\),表示式為

\[F_\beta=\frac{(1+\beta^2)\cdot precision\cdot recall}{\beta^2\cdot precision + recall} \]

  式中的\(\beta\) 值能夠表達出對查準率/查全率的不同偏好,如F1分數認為召回率和精準度同等重要,F2分數認為召回率的重要程度是精準度的兩倍,而F0.5分數認為召回率的重要程度是精準度的一半。其中,F1度量是最常用的一種,表示式為

\[F_1=\frac{2\cdot precision\cdot recall}{precision+recall} \]

注:
F1由調和平均進行定義: $$\frac{1}{F_1}=\frac{1}{2}\left(
\frac{1}{precision}+\frac{1}{recall} \right)$$ \(F_\beta\)由加權調和平均進行定義:

\[\frac{1}{F_\beta}=\frac{1}{1+\beta^2 }\left( \frac{1}{precision}+\frac{\beta^2}{recall} \right)\]

5.ROC曲線與AUC值

  ROC(Receiver Operating Characteristic,受試者工作特徵)曲線是以真正率(TPR)為縱軸、假正率(FPR)為橫軸繪製的曲線,AUC(Area Under ROC Curve)是ROC曲線下的面積,它們能夠在一定程度上衡量分類器的效能,示意圖如圖所示。

  TPR(true positive rate,真正率)、FPR(false positive rate,假正率)表示式為

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

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


  ROC與AUC的度量,對二分類問題來說是更直觀的,它直接地關注於正例樣本,透過正例樣本的整體表現來衡量學習器的效能。而這個正例類的指定,則由實際問題情形而確定。
  ROC曲線的繪製過程為,對測試樣本集中的樣本,將待考察的類別規定為正例類,學習器計算得到每個樣本歸屬於正例類的機率,對所有樣本依機率進行排序,起始時將劃分閾值設為最大,即將所有樣本劃為負樣本,此時TPR和FPR均為0,座標軸上在(0,0)處標定了一個點。然後調整劃分閾值,依次將每個樣本劃為正樣本,TPR、FPR值隨之增大,連線過程中標定的座標點即得到ROC曲線。易知,若一個學習器的ROC曲線被另一個學習器的曲線完全包住,則後者的效能優於前者;若兩個學習器的曲線發生交叉,則可比較ROC曲線下的面積,即AUC(Area Under ROC Curve),面積越大,效能越好。
  假定ROC曲線由座標點{(x1,y1),(x2,y2),…,(xn,yn)}按序連線而成,則AUC值估算的表示式為

\[AUC=\frac{1}{2}\sum_{i=1}^{n-1}{\left( x_{i+1}-x_i \right)\cdot\left( y_i+y_{i+1} \right)} \]

6.Kappa係數

  Kappa係數是統計分析中一種進行一致性檢驗的常見方法,能夠較大程度上反映出分類演算法的效能表現。它的計算同樣基於混淆矩陣,反映的是預測結果與實際結果的一致性,其取值範圍為[-1,1],值越大說明一致性越高,效能越好;反之效能越差。假設樣本總數為N,Kappa係數定義為

\[kappa=\frac{p_o-p_e}{1-p_e} \]

  其中,\(p_o=\frac{1}{N}\left( TP+TN \right)\)是整體準確率,
     \(p_e=\frac{1}{N^2}\left[ \left( TP+FN \right)\cdot \left( TP+FP \right)+\left( FP+TN \right)\cdot \left( FN+TN \right) \right]\)表偶然一致性。

三、評價指標——多分類情形

  多分類情形下的混淆矩陣表示為

  多分類問題往往能夠轉化為多個二分類問題,對它們效能的評價可透過宏計算或微計算的方式進行。

1.準確率(accuracy)

  準確率即混淆矩陣主對角線上的值之和與樣本總數N的比值

\[Accuracy=\frac{1}{N}\sum_{i=1}^{K}{x_{ii}} \]

2.精準度、召回率、F1值

  對於多分類任務,各個類別兩兩之間即對應了一個混淆矩陣,計算查準率、查全率、F1值的方式有兩種,一種是對各混淆矩陣計算得到的指標值對應求平均,得到宏查準率(macro-P)、宏查全率(macro-R)和宏F1值(macro-F1);另一種是將各混淆矩陣對應位置處的值求平均,記為\(\bar{TP}\)\(\bar{FP}\)\(\bar{TN}\)\(\bar{FN}\),由這些平均的值計算得到微查準率(micro-P)、微查全率(micro-R)和微F1值(micro-F1)。假設共有K個類別,那麼混淆矩陣數量為\(C_{K}^{2}=\frac{K\cdot(K-1)}{2}\),記為n,則
  宏計算的指標值表示為

\[macro_{-}P=\frac{1}{n}\sum_{i=1}^{n}{precision_i} \]

\[macro_{-}R=\frac{1}{n}\sum_{i=1}^{n}{recall_i} \]

\[macrox_{-}F1=\frac{2\ast macro_{-}P\ast macro_{-}R}{macro_{-}P+macro_{-}R} \]


  微計算的指標值表示為 $$micro_{-}P=\frac{\bar{TP}}{\bar{TP}+\bar{FP}}$$ $$micro_{-}R=\frac{\bar{TP}}{\bar{TP}+\bar{FN}}$$ $$micro_{-}F1=\frac{2\ast micro_{-}P \ast micro_{-}R}{micro_{-}P+micro_{-}R}$$

3. ROC曲線與AUC值

  多分類情形下的ROC與AUC同樣可以以“宏”或“微”的形式進行計算。
方式一:
  對於K(K>2)類分類問題,分別將每一個類別視作正例,其餘各類別視作負例,在機率預測矩陣中,按當前類別列下的機率值進行排序,隨之調整劃分閾值,可得到一條ROC曲線,如此,共可得到K條ROC曲線,對各曲線的座標點求平均,即繪製出一條“宏計算(macro)”的ROC曲線,並可計算出它對應的AUC值。簡單地說就是,機率預測矩陣的每一列值排序後都形成一條ROC曲線,再得到平均後的曲線。

方式二:
  對於K(K>2)類分類問題,首先將樣本標籤one-hot化,得到一個K列的0和1標識的矩陣,將機率預測矩陣和該矩陣分別按行或按列將各自拼接為一維向量,按此機率向量進行排序,隨之調整劃分閾值,可得到一條“微計算(micro)”的ROC曲線,並可計算出它對應的AUC值。簡單地說就是,機率預測矩陣的所有值排序後直接地形成一條ROC曲線。

4.Kappa係數

  Kappa的計算與二分類是一致的,假設樣本類別數為K,總樣本數為N,實際為i預測為j的樣本數為\(a_{ij}\),有

\[kappa=\frac{p_o-p_e}{1-p_e} \]

  其中,\(p_o=\frac{1}{N}\sum_{i=1}^{K}{a_{ii}}\)是整體準確率,\(p_e=\frac{1}{N^2}\sum_{i=1}^{K}{a_{i+}\cdot a_{+i}}\) 表偶然一致性。

例如,在某分類問題中,樣本真實類別和預測類別分別是
   y_true=['A','A','C','B','B','A','C','B'];
   y_pred=['C','A','C','B','B','A','B','B'],
其對應的混淆矩陣為

  則\(p_o=\frac{2+3+1}{8}=0.75\)\(p_e=\frac{3\times 2+3\times 4+2\times 2}{8\times 8}=0.3438\)
  所以\(kappa=\frac{0.75-0.3438}{1-0.3438}=0.619\)

四、Python實現

二分類情形

import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn import metrics
import matplotlib
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
from sklearn.metrics import cohen_kappa_score

## 1.定義資料集

# 訓練資料
train_x = [
    [4.8,3,1.4,0.3],
    [5.1,3.8,1.6,0.2],
    [4.6,3.2,1.4,0.2],
    [5.3,3.7,1.5,0.2],
    [5,3.3,1.4,0.2],
    [7,3.2,4.7,1.4],
    [6.4,3.2,4.5,1.5],
    [6.9,3.1,4.9,1.5],
    [5.5,2.3,4,1.3],
    [6.5,2.8,4.6,1.5]
]

# 訓練資料標籤
train_y = [
    'A',
    'A',
    'A',
    'A',
    'A',
    'B',
    'B',
    'B',
    'B',
    'B'
]


# 測試資料
test_x = [
    [3.1,3.5,1.4,0.2],
    [4.9,3,1.4,0.2],
    [5.1,2.5,3,1.1],
    [6.2,3.6,3.4,1.3]
]

# 測試資料標籤
test_y = [
    'A',
    'A',
    'B',
    'B'
]

train_x = np.array(train_x)
train_y = np.array(train_y)
test_x = np.array(test_x)
test_y = np.array(test_y)

## 2.訓練分類器
clf_dt = DecisionTreeClassifier(max_depth=None, min_samples_split=2)  # 定義決策樹學習器
rclf_dt = clf_dt.fit(train_x,train_y)  # 訓練

## 3.資料計算
pre_y = rclf_dt.predict(test_x)
pre_y_proba = rclf_dt.predict_proba(test_x)[:,0] # 預測為類'A'的機率

## 4.效能評價
# (1) 準確率
accuracy = metrics.accuracy_score(test_y,pre_y)

# (2) 精確度(查準率)
precision = metrics.precision_score(test_y,pre_y,pos_label='A') # pos_label指定正例類

# (3) 召回率(查全率)
recall = metrics.recall_score(test_y,pre_y,pos_label='A')

# (4) F1度量
F1 = metrics.f1_score(test_y,pre_y,pos_label='A')

# (5) ROC-AUC值
fpr,tpr,threshold = metrics.roc_curve(test_y,pre_y_proba,pos_label='A')
AUC = metrics.auc(fpr,tpr)

# (6) Kappa係數
kappa = cohen_kappa_score(test_y, pre_y)

## 5.結果輸出
print('\naccuracy:', accuracy)
print('\nprecision:', precision)
print('recall:', recall)
print('F1:', F1)
print('\nAUC:', AUC)
print('\nkappa:', kappa)

# ROC曲線繪圖
plt.figure()
plt.plot(fpr, tpr, label='ROC curve (area = %0.2f)' % AUC)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Binary Classify ROC')
plt.legend(loc="lower right")
plt.show()


多分類情形

import numpy as np
from sklearn.tree import DecisionTreeClassifier
from sklearn import metrics
from sklearn.preprocessing import OneHotEncoder
from sklearn.metrics import cohen_kappa_score

## 1.定義資料集

# 訓練資料
train_x = [
    [4.8,3,1.4,0.3],
    [5.1,3.8,1.6,0.2],
    [4.6,3.2,1.4,0.2],
    [5.3,3.7,1.5,0.2],
    [5,3.3,1.4,0.2],
    [7,3.2,4.7,1.4],
    [6.4,3.2,4.5,1.5],
    [6.9,3.1,4.9,1.5],
    [5.5,2.3,4,1.3],
    [6.5,2.8,4.6,1.5],
    [6.3,3.3,6,2.5],
    [5.8,2.7,5.1,1.9],
    [7.1,3,5.9,2.1],
    [6.3,2.9,5.6,1.8],
    [6.5,3,5.8,2.2]
]

# 訓練資料標籤
train_y = [
    'A',
    'A',
    'A',
    'A',
    'A',
    'B',
    'B',
    'B',
    'B',
    'B',
    'C',
    'C',
    'C',
    'C',
    'C'
]


# 測試資料
test_x = [
    [5.1,3.5,1.4,0.2],
    [4.9,3,1.4,0.2],
    [5.1,2.5,3,1.1],
    [5.7,2.8,4.1,1.3],
    [6.2,3.4,5.4,2.3],
    [5.9,3,5.1,1.8]
]

# 測試資料標籤
test_y = [
    'A',
    'A',
    'C',
    'B',
    'C',
    'C'
]

train_x = np.array(train_x)
train_y = np.array(train_y)
test_x = np.array(test_x)
test_y = np.array(test_y)

## 2.訓練分類器
clf_dt = DecisionTreeClassifier(max_depth=None, min_samples_split=2)  # 定義決策樹學習器
rclf_dt = clf_dt.fit(train_x,train_y)  # 訓練

## 3.資料計算
pre_y = rclf_dt.predict(test_x)
pre_y_proba = rclf_dt.predict_proba(test_x)

## 4.效能評價
# (1) 準確率
accuracy = metrics.accuracy_score(test_y,pre_y)

# (2) P-R度量
precision_macro = metrics.precision_score(test_y,pre_y,average='macro')  #宏精確度(查準率)
recall_macro = metrics.recall_score(test_y,pre_y,average='macro')  #宏召回率(查全率)
F1_macro = metrics.f1_score(test_y,pre_y,average='macro')  #宏F1度量

precision_micro = metrics.precision_score(test_y,pre_y,average='micro')  #微精確度(查準率)
recall_micro = metrics.recall_score(test_y,pre_y,average='micro')  #微召回率(查全率)
F1_micro = metrics.f1_score(test_y,pre_y,average='micro')  #微F1度量

# (3)ROC-AUC值
encoder = OneHotEncoder(sparse_output=False)  # 建立一個OneHotEncoder物件
onehot_test_y = encoder.fit_transform(test_y.reshape(-1, 1)) # 對整數陣列進行one-hot編碼
AUC_macro = metrics.roc_auc_score(onehot_test_y,pre_y_proba, average='macro', sample_weight=None)
AUC_micro = metrics.roc_auc_score(onehot_test_y,pre_y_proba, average='micro', sample_weight=None)

# (4) Kappa係數
kappa = cohen_kappa_score(test_y, pre_y)

## 5.結果輸出
print('\naccuracy: ', accuracy)
print('\nprecision_macro: ',precision_macro)
print('recall_macro:',recall_macro)
print('F1_macro:',F1_macro)
print('\nprecision_micro:',precision_micro)
print('recall_micro:',recall_micro)
print('F1_micro:',F1_micro)
print('\nAUC_macro: ',AUC_macro)
print('AUC_micro:',AUC_micro)
print('\nKappa: ',kappa)


End.


參考:
  周志華. 機器學習. 清華大學出版社.


全文pdf下載

相關文章