精准率和召回率是兩個不同的評價指標,很多時候它們之間存在着差異,具體在使用的時候如何解讀精准率和召回率,應該視具體使用場景而定
有些場景,人們可能更注重精准率,如股票預測系統,我們定義股票升為1,股票降為0,我們更關心的是未來升的股票的比例,而在另外一些場景中,人們更加注重召回率,如癌症預測系統,定義健康為1,患病為0,我們更關心癌症患者檢查的遺漏情況。
F1 Score
F1 Score 兼顧精准率和召回率,它是兩者的調和平均值
定義F1 Score
def f1_score(precision,recall):
try:
return 2*precision*recall/(precision+recall)
except:
return 0
由上看出,F1 Score更偏向於分數小的那個指標
Precision-Pecall的平衡
精准率和召回率是兩個互相矛盾的目標,提高一個指標,另一個指標就會不可避免的下降。如何達到兩者之間的一個平衡呢?
回憶邏輯回歸算法的原理:將一個結果發生的概率大於0.5,就把它分類為1,發生的概率小於0.5,就把它分類為0,決策邊界為:\(\theta ^T \cdot X_b = 0\)
這條直線或曲線決定了分類的結果,平移決策邊界,使\(\theta ^T \cdot X_b\)不等於0而是一個閾值:\(\theta ^T \cdot X_b = threshold\)
圓形代表分類結果為0,五角星代表分類結果為1,由上圖可以看出,精准率和召回率是兩個互相矛盾的指標,隨着閾值的逐漸增大,召回率逐漸降低,精准率逐漸增大。
編程實現不同閥值下的預測結果及混淆矩陣
from sklearn.linear_model import LogisticRegression
# 數據使用前一節處理后的手寫識別數據集
log_reg = LogisticRegression()
log_reg.fit(x_train,y_train)
求每個測試數據在邏輯回歸算法中的score值:
decision_score = log_reg.decision_function(x_test)
不同閥值下預測的結果
y_predict_1 = numpy.array(decision_score>=-5,dtype='int')
y_predict_2 = numpy.array(decision_score>=0,dtype='int')
y_predict_3 = numpy.array(decision_score>=5,dtype='int')
查看不同閾值下的混淆矩陣:
精准率-召回率曲線
求出0.1步長下,閾值在[min,max]區間下的精准率和召回率,查看其曲線特征:
threshold_scores = numpy.arange(numpy.min(decision_score),numpy.max(decision_score),0.1)
precision_scores = []
recall_scores = []
# 求出每個分類閾值下的預測值、精准率和召回率
for score in threshold_scores:
y_predict = numpy.array(decision_score>=score,dtype='int')
precision_scores.append(precision_score(y_test,y_predict))
recall_scores.append(recall_score(y_test,y_predict))
畫出精准率和召回率隨閾值變化的曲線
plt.plot(threshold_scores,precision_scores)
plt.plot(threshold_scores,recall_scores)
plt.show()
畫出精准率-召回率曲線
plt.plot(precision_scores,recall_scores)
plt.show()
sklearn中的精准率-召回率曲線
from sklearn.metrics import precision_recall_curve
precisions,recalls,thresholds = precision_recall_curve(y_test,decision_score)
# sklearn中最后一個精准率為1,召回率為0,沒有對應的threshold
plt.plot(thresholds,precisions[:-1])
plt.plot(thresholds,recalls[:-1])
plt.show()