一、概述
分類模型是機器學習中一種最常見的問題模型,在許多問題場景中有著廣泛的運用,是模式識別問題中一種主要的實現手段。分類問題概況起來就是,對一堆高度抽象了的樣本,由經驗標定了每個樣本所屬的實際類別,由特定演算法訓練得到一個分類器,輸入樣本屬性即自動計算出其所屬類別,從而完成特定的識別任務。依實現原理的不同,分類演算法有很多種,常見的如支援向量機、決策樹、k近鄰、樸素貝葉斯......,以及設計了的各種人工神經網路等。在特定問題中,演算法效能的評價是一個重要的方面,它一般由學習器在測試資料中的效能表現來直接衡定,常見的評價指標有準確率、精準度(查準率)、召回率(查全率)、F1值、ROC-AUC值、Kappa係數等。
二、評價指標——二分類情形
二分類模型是較常見和較一般化的情形,它預測的混淆矩陣可表示為
其中,
TP(True Positive,真正例)為被正確劃分為正例的樣本數;
FP(False Positive,假正例)為被錯誤劃分為正例的樣本數;
TN(True Negative,真負例)為被正確劃分為負例的樣本數;
FN(False Negative,假負例)為被錯誤劃分為負例的樣本數。
1.準確率(accuracy)
準確率是被預測正確的樣本數與樣本總數\(N\)的比值,比較直觀地反映了學習器的效能。表示式為
2. 精準度(precision)
精準度是TP(真正例)佔預測為正例樣本數的百分比,它表徵了預測的正例中有多少有效成分,也叫做查準率。表示式為
3. 召回率(recall)
召回率是TP(真正例)與真實正樣本數的比值,它表徵了所有的有效內容有多少被檢測了出來,也叫做查全率、靈敏度(sensitive)。表示式為
4. F度量(F-Measure, F-Score)
我們希望學習器的查準率和查全率都高,而查準率和查全率往往是一對矛盾的度量,查準率高時,查全率往往偏低;查全率高時,查準率往往偏低。此時可以用F度量來綜合評估精準度(查準率)和召回率(查全率),數值越高學習器越理想。它的一般形式記作\(F_\beta\),表示式為
式中的\(\beta\) 值能夠表達出對查準率/查全率的不同偏好,如F1分數認為召回率和精準度同等重要,F2分數認為召回率的重要程度是精準度的兩倍,而F0.5分數認為召回率的重要程度是精準度的一半。其中,F1度量是最常用的一種,表示式為
注:
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,假正率)表示式為
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值估算的表示式為
6.Kappa係數
Kappa係數是統計分析中一種進行一致性檢驗的常見方法,能夠較大程度上反映出分類演算法的效能表現。它的計算同樣基於混淆矩陣,反映的是預測結果與實際結果的一致性,其取值範圍為[-1,1],值越大說明一致性越高,效能越好;反之效能越差。假設樣本總數為N,Kappa係數定義為
其中,\(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的比值
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,則
宏計算的指標值表示為
微計算的指標值表示為 $$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}\),有
其中,\(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下載