【火爐煉AI】機器學(xué)習(xí)011-分類模型的評估:準(zhǔn)確率绕辖,精確率,召回率擂红,F(xiàn)1值
(本文所使用的Python庫和版本號: Python 3.5, Numpy 1.14, scikit-learn 0.19, matplotlib 2.2 )
在前面的(【火爐煉AI】機器學(xué)習(xí)004-嶺回歸器的構(gòu)建和模型評估)中,講解了回歸模型的評估方法,主要有均方誤差MSE弟头, 解釋方差分,R方得分等指標(biāo)。
同樣的肚医,對于分類模型,也有很多評估指標(biāo)來判斷該分類模型是否達到我們的要求搁痛,這幾個評估指標(biāo)主要是指:準(zhǔn)確率(accuracy)病苗,精確率(precision),召回率(recall)瞒斩,F(xiàn)1值(F1 measure)。
1. 指標(biāo)的基本概念和計算方法
1.1 準(zhǔn)確率(Accuracy)
準(zhǔn)確率的定義是:對于給定的測試集涮总,分類模型正確分類的樣本數(shù)與總樣本數(shù)之比胸囱。舉個例子來講,有一個簡單的二分類模型(暫時叫做Classifier_A)瀑梗,專門用于分類蘋果和梨烹笔,在某個測試集中,有30個蘋果+70個梨抛丽,這個二分類模型在對這個測試集進行分類的時候谤职,得出該數(shù)據(jù)集有40個蘋果(包括正確分類的25個蘋果和錯誤分類的15個梨)和60個梨(包括正確分類的55個梨和錯誤分類的5個蘋果)。畫成矩陣圖為:
從圖中可以看出亿鲜,行表示該測試集中實際的類別允蜈,比如蘋果類一共有25+5=30個,梨類有15+55=70個蒿柳。其中被分類模型正確分類的是該表格的對角線所在的數(shù)字陷寝。在sklearn中,這樣一個表格被命名為混淆矩陣(Confusion Matrix)其馏,所以凤跑,按照準(zhǔn)確率的定義,可以計算出該分類模型在測試集上的準(zhǔn)確率為:
即叛复,該分類模型在測試集上的準(zhǔn)確率為80%仔引。
但是,準(zhǔn)確率指標(biāo)并不總是能夠評估一個模型的好壞褐奥,比如對于下面的情況咖耘,假如有一個數(shù)據(jù)集,含有98個蘋果撬码,2個梨儿倒,而分類器(暫時叫做Classifier_B)是一個很差勁的分類器,它把數(shù)據(jù)集的所有樣本都劃分為蘋果呜笑,也就是不管輸入什么樣的樣本夫否,該模型都認(rèn)為該樣本是蘋果。那么這個表格會是什么樣的了叫胁?
則該模型的準(zhǔn)確率為98%凰慈,因為它正確地識別出來了測試集中的98個蘋果,只是錯誤的把2個梨也當(dāng)做蘋果驼鹅,所以按照準(zhǔn)確率的計算公式微谓,該模型有高達98%的準(zhǔn)確率森篷。
可是,這樣的模型有意義嗎豺型?一個把所有樣本都預(yù)測為蘋果的模型仲智,反而得到了非常高的準(zhǔn)確率,那么問題出在哪兒了姻氨?只能說準(zhǔn)確率不可信坎藐。特別是對于這種樣品數(shù)量偏差比較大的問題,準(zhǔn)確率的“準(zhǔn)確度”會極大的下降哼绑。所以,這時就需要引入其他評估指標(biāo)評價模型的好壞了碉咆。
1.2 精確率(Precision)
精確率的定義是:對于給定測試集的某一個類別抖韩,分類模型預(yù)測正確的比例,或者說:分類模型預(yù)測的正樣本中有多少是真正的正樣本疫铜,其計算公式是:
所以茂浮,根據(jù)定義,精確率要區(qū)分不同的類別壳咕,比如上面我們討論有兩個類別席揽,所以要分類來計算各自的精確率。對于上面提到的Classifier_A和Classifier_B分類模型谓厘,我們可以分別計算出其精確率:
在很多文章中幌羞,都講到把某一個類別當(dāng)做正類(Positive),把其他類別當(dāng)做負(fù)類(Negative)竟稳,然后只關(guān)注正類的精確率属桦。但是,有的時候我們不知道哪一個類作為正類更合適他爸,比如此處的二分類問題聂宾,我們可以把蘋果當(dāng)做正類,也可以把梨當(dāng)做正類诊笤,兩者計算出來的精確率明顯是不一樣的系谐。
1.3 召回率(Recall)
召回率的定義為:對于給定測試集的某一個類別,樣本中的正類有多少被分類模型預(yù)測正確讨跟,其計算公式為:
同樣的纪他,召回率也要考慮某一個類別,比如晾匠,下面我們將蘋果作為正類止喷,在Classifier_A模型下得到的表格為:
如果我們將梨作為正類,在Classifier_A模型下得到的表格為:
同樣的混聊,可以計算出上面兩個模型對給定測試集的召回率弹谁,如下表所示:
1.4 F1值(F1-Measure)
在理想情況下乾巧,我們希望模型的精確率越高越好,同時召回率也越高越高预愤,但是沟于,現(xiàn)實情況往往事與愿違,在現(xiàn)實情況下植康,精確率和召回率像是坐在蹺蹺板上一樣旷太,往往出現(xiàn)一個值升高,另一個值降低销睁,那么供璧,有沒有一個指標(biāo)來綜合考慮精確率和召回率了,這個指標(biāo)就是F值冻记。F值的計算公式為:
式中:P: Precision睡毒, R: Recall, a:權(quán)重因子。
當(dāng)a=1時冗栗,F(xiàn)值便是F1值演顾,代表精確率和召回率的權(quán)重是一樣的,是最常用的一種評價指標(biāo)隅居。F1的計算公式為:
所以根據(jù)上面的精確率和召回率钠至,可以輕松的計算出這兩個模型的F1值:
2. 用sklearn計算精確率,召回率胎源,F(xiàn)1值
上面第一部分棉钧,我們都是手動計算出每種分類模型的各種評價指標(biāo),但是上帝告訴我們涕蚤,他已經(jīng)幫我們造好了輪子掰盘,我們只需要直接調(diào)用即可。廢話少說赞季,直接把計算這些評價指標(biāo)的代碼貼過來:
2.1 用sklearn計算分類結(jié)果的混淆矩陣
# 假如有一個模型在測試集上得到的預(yù)測結(jié)果為:
y_true = [1, 0, 0, 2, 1, 0, 3, 3, 3] # 實際的類別
y_pred = [1, 1, 0, 2, 1, 0, 1, 3, 3] # 模型預(yù)測的類別
# 使用sklearn 模塊計算混淆矩陣
from sklearn.metrics import confusion_matrix
confusion_mat = confusion_matrix(y_true, y_pred)
print(confusion_mat) #看看混淆矩陣長啥樣
-------------------------------------輸---------出--------------------------------
[[2 1 0 0]
[0 2 0 0]
[0 0 1 0]
[0 1 0 2]]
--------------------------------------------完-------------------------------------
其實這個矩陣的產(chǎn)生過程很簡單愧捕,比如實際類別是3(y_true=3)一共有三個樣本,其中兩個預(yù)測正確申钩,一個預(yù)測錯誤成1次绘,結(jié)果如表格所示:
2.2 混淆矩陣可視化
上面雖然把混淆矩陣打印出來了,但是結(jié)果很難直接觀察對比撒遣,下面將混淆矩陣可視化為圖表邮偎,便于觀察。
def plot_confusion_matrix(confusion_mat):
'''將混淆矩陣畫圖并顯示出來'''
plt.imshow(confusion_mat, interpolation='nearest', cmap=plt.cm.gray)
plt.title('Confusion matrix')
plt.colorbar()
tick_marks = np.arange(confusion_mat.shape[0])
plt.xticks(tick_marks, tick_marks)
plt.yticks(tick_marks, tick_marks)
plt.ylabel('True label')
plt.xlabel('Predicted label')
plt.show()
plot_confusion_matrix(confusion_mat)
2.3 打印模型的性能報告
Sklearn模塊中已經(jīng)有成熟的對于模型評估的性能報告义黎,里面已經(jīng)集成了分類模型的精確率禾进,召回率和F1值信息,可以說廉涕,是我們分析模型的必備良器泻云。
# 打印該模型的性能報告
# 直接使用sklearn打印精度艇拍,召回率和F1值
from sklearn.metrics import classification_report
target_names = ['Class-0', 'Class-1', 'Class-2', 'Class-3']
print(classification_report(y_true, y_pred, target_names=target_names))
-------------------------------------輸---------出--------------------------------
precision recall f1-score support
Class-0 1.00 0.67 0.80 3
Class-1 0.50 1.00 0.67 2
Class-2 1.00 1.00 1.00 1
Class-3 1.00 0.67 0.80 3
avg / total 0.89 0.78 0.79 9
--------------------------------------------完-------------------------------------
這個性能報告表中的評估指標(biāo)的計算方法如前面第一節(jié)講述的,比如對于Precision,對于Class_1, Precision=TP/(TP+FP)=2/(2+1+0+1)=0.50宠纯,而對于Class_2: Precision=1/(1+0+0+0)=1.0.
對于Recall的計算方法卸夕,比如,對于Class_0=TP/(TP+FN)=2/(2+1+0+0)=0.67.所以可以看出婆瓜,Precision的算法是在混淆矩陣的縱向上運算快集,而Recall的算法是在混淆矩陣的橫向上運算。
F1-score的計算便是直接套用公式即可廉白。后面的support是真實的各個類別的樣本數(shù)量个初。
########################小**********結(jié)###############################
1,sklearn中已經(jīng)有成熟的方法可以直接計算混淆矩陣和打印性能報告猴蹂,這些函數(shù)對于模型的評估非常有幫助院溺。
2,精確率晕讲,召回率,F(xiàn)1值的計算其實很簡單马澈,只要弄明白各自對應(yīng)的公式瓢省,弄明白公式所代表的具體含義即可。
#################################################################
3. 評估樸素貝葉斯多分類模型
在文章【火爐煉AI】機器學(xué)習(xí)010-用樸素貝葉斯分類器解決多分類問題中我們使用了高斯樸素貝葉斯分類器構(gòu)建了一個多分類模型痊班,將該數(shù)據(jù)集成功分成了四個類別勤婚,貌似結(jié)果很不錯,可是該文章沒有提高用可以量化的性能指標(biāo)來評估該分類模型的好壞涤伐。此處我們可以用上面講到的各種評價指標(biāo)來評估該分類模型馒胆。
3.1 用交叉驗證檢驗?zāi)P偷臏?zhǔn)確性
先加載數(shù)據(jù)集,然后劃分為train set 和testset凝果。構(gòu)建樸素貝葉斯分類模型祝迂,用trainset進行訓(xùn)練,然后用sklearn中的cross_val_score來輸出該分類模型在test set上的整體表現(xiàn)器净,代碼如下:
# 評估樸素貝葉斯多分類模型
# 1型雳, 準(zhǔn)備數(shù)據(jù)集
data_path='D:\PyProjects\DataSet/NaiveBayers/data_multivar.txt'
df=pd.read_csv(data_path,header=None)
dataset_X,dataset_y=df.iloc[:,:-1],df.iloc[:,-1]
dataset_X=dataset_X.values
dataset_y=dataset_y.values
# 將整個數(shù)據(jù)集劃分為train set和test set
from sklearn.cross_validation import train_test_split
train_X, test_X, train_y, test_y=train_test_split(dataset_X,dataset_y,test_size=0.25,random_state=42)
# 構(gòu)建樸素貝葉斯分類模型
from sklearn.naive_bayes import GaussianNB
gaussianNB_new=GaussianNB()
gaussianNB_new.fit(train_X,train_y)
# 2 用交叉驗證來檢驗?zāi)P偷臏?zhǔn)確性,只是在test set上驗證準(zhǔn)確性
from sklearn.cross_validation import cross_val_score
num_validations=5
accuracy=cross_val_score(gaussianNB_new,test_X,test_y,
scoring='accuracy',cv=num_validations)
print('準(zhǔn)確率:{:.2f}%'.format(accuracy.mean()*100))
precision=cross_val_score(gaussianNB_new,test_X,test_y,
scoring='precision_weighted',cv=num_validations)
print('精確度:{:.2f}%'.format(precision.mean()*100))
recall=cross_val_score(gaussianNB_new,test_X,test_y,
scoring='recall_weighted',cv=num_validations)
print('召回率:{:.2f}%'.format(recall.mean()*100))
f1=cross_val_score(gaussianNB_new,test_X,test_y,
scoring='f1_weighted',cv=num_validations)
print('F1 值:{:.2f}%'.format(f1.mean()*100))
-------------------------------------輸---------出--------------------------------
準(zhǔn)確率:99.00%
精確度:99.17%
召回率:99.00%
F1 值:98.97%
--------------------------------------------完-------------------------------------
3.2 查看該模型在測試集上的混淆矩陣和性能報告
直接上代碼山害,沒什么好講的纠俭。
# 使用sklearn 模塊計算混淆矩陣
y_pred=gaussianNB_new.predict(test_X)
confusion_mat = confusion_matrix(test_y, y_pred)
print(confusion_mat) #看看混淆矩陣長啥樣
print('*'*50)
# 打印該模型的性能報告
# 直接使用sklearn打印精度,召回率和F1值
target_names = ['Class-0', 'Class-1', 'Class-2', 'Class-3']
print(classification_report(test_y, y_pred, target_names=target_names))
-------------------------------------輸---------出--------------------------------
[[27 0 0 0]
[ 0 18 0 0]
[ 0 0 33 0]
[ 0 0 0 22]]
precision recall f1-score support
Class-0 1.00 1.00 1.00 27
Class-1 1.00 1.00 1.00 18
Class-2 1.00 1.00 1.00 33
Class-3 1.00 1.00 1.00 22
avg / total 1.00 1.00 1.00 100
--------------------------------------------完-------------------------------------
########################小**********結(jié)###############################
1浪慌,對于樸素貝葉斯解決這里的多分類問題冤荆,從模型檢測結(jié)果可以看出,該分類器可以很好地將這個數(shù)據(jù)集的四個類別區(qū)分開來权纤,得到的準(zhǔn)確率钓简,精確率乌妒,召回率,F(xiàn)1值等都比較好涌庭。
2芥被,該分類器在測試集上的混淆矩陣都只有TP,沒有FP或FN坐榆,表明該分類器可以100%的將這測試集中的四個類別區(qū)分開來拴魄。
3,在交叉驗證時席镀,得到的結(jié)果并不是100%匹中,而是99%以上,原因很有可能是交叉驗證是采用多步驗證來計算這些指標(biāo)豪诲,評估得到的結(jié)果可能更可靠一些顶捷。
#################################################################
注:本部分代碼已經(jīng)全部上傳到(我的github)上,歡迎下載屎篱。
參考資料:
1, Python機器學(xué)習(xí)經(jīng)典實例服赎,Prateek Joshi著,陶俊杰交播,陳小莉譯