機器學習之分類效果評估

對於迴歸問題,一般有 MSE、MAE、RMSE、R^2 四種方法來評判模型的效果。對於分類問題,最簡單的辦法是採用準確率來評估模型的效果。好比 sklearn 中對於分類問題默認的 score 都是根據準確率來統計的。python

使用準確率來評估理解很是簡單,可是對於極度偏斜的數據的預測會有很大問題。好比對於癌症預測問題,健康 vs 患病的比例多是 10000:1。對於這種極度偏斜的數據,咱們能夠作一個最簡單的模型,直接預測全部樣本都屬於健康類,這樣模型準確率均可以達到 99.99%。git

對於這類型數據,分類算法模型的 score 能夠藉助混淆矩陣來評估。算法

混淆矩陣

下面爲了方便解釋混淆矩陣以及準確率和召回率等名詞術語,先以二分類問題爲例來分析。app

真實/預測 0 1
0 TN FP
1 FN TP
  1. 上述表格中,行表明實際值,列表明預測值。
  2. 0 表明 negative,1 表明 postive。
  3. TN (True Negative) 表示實際值爲 negative,預測值爲 negative,預測 negative 正確。
  4. FP (False Positive) 表示實際值爲 negative,預測值爲 positive,預測 positive 錯誤。
  5. FN (False Negative) 表示實際值爲 positive,預測值爲 negative,預測 negative 錯誤。
  6. TP (True Positive) 表示實際值爲 positive,預測值爲 positive,預測 positive 錯誤。

上面說的有些抽象,下面舉一個具體的例子。dom

真實/預測 0 1
0 9980 10
1 3 7
  1. 9980 我的自己沒有患癌症,同時算法也預測他們沒有患癌症。
  2. 10 我的沒有患癌症,可是算法預測他們患有癌症。
  3. 3 我的患有癌症,可是算法預測他們沒有患癌症。
  4. 7 我的患有癌症,算法預測他們患有癌症。

精準率

對於精準率的定義是:預測關注事件的結果中(總共 17 次)預測正確的機率,7 次正確,10 次錯誤。post

精準率 = TP / (TP + FP) = 7 / (10+7),也就是說沒作 17 次患病預測的時候,平均有 7 次正確的。spa

召回率

召回率的定義是:對所關注的類型(也就是 10 個患者),將其預測出的機率(預測出 7 個)。code

召回率 = TP / (TP + FN) = 7 / (7 + 3) = 70%,也就是說每當有 100 個患者,算法平均可以成功找出 70 個,會漏掉 30 個。cdn

F1-Score

對於有些場景,選擇精準率更合適,好比股票預測場景,要預測股票是漲仍是降,業務需求是更精準的找到可以上升的股票。而對於疾病預測場景,要預測就診人員是否患病,這個時候的業務需求是找出全部患病的病人不要漏掉任何一個患者,能夠說將健康者診斷爲患者可能沒太多關係,只要不將患者診斷爲健康者。blog

可是在有些場景,須要同時綜合精準率和召回率,這個時候怎麼辦呢?可使用 f1-score 來解決,f1 是精準率和召回率的調和平均值:

F 1=\frac{2 \cdot \text { precision} \cdot \text {recall} }{\text { precision }+\text { recall }}

實例

爲了演示上面提到的三個概念,首先咱們先構建一個極度偏斜的數據,咱們選擇 sklearn 提供手寫識別數據集,自己在這個數據集中,0-9 十個數字都分佈比較均勻,咱們將這個十分類數據轉換成二分類數據,一類等於 9,另一類不等於 9 來製造數據偏斜。

import numpy as np
from sklearn import datasets

digits = datasets.load_digits()
X = digits.data
y = digits.target.copy()

y[digits.target==9] = 1
y[digits.target!=9] = 0
複製代碼

使用邏輯迴歸來進行預測:

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

from sklearn.linear_model import LogisticRegression

log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)

log_reg.score(X_test, y_test)
複製代碼

因爲數據是極度偏斜的,即便預測全部樣本的類型都是 0,準確度都能達到 90% 左右。準確度只能說明模型對每個樣本預測的準確度,並不能真正準確找出類型爲 1 的樣本,也就是說準確度並不能反映模型是否精準找出了類型爲 1 的樣本。sklearn metrics 包中直接提供了對於混淆矩陣、精準率、召回率的支持。

from sklearn.metrics import confusion_matrix

confusion_matrix(y_test, y_log_predict)

from sklearn.metrics import precision_score

precision_score(y_test, y_log_predict)

from sklearn.metrics import recall_score

recall_score(y_test, y_log_predict)

from sklearn.metrics import f1_score

f1_score(y_test, y_log_predict)
複製代碼

PR 曲線

對於二分類問題,咱們能夠調節分類邊界值來調節精準率和召回率的比重。score > threshold 時分類爲 1,score < threshold 時分類爲 0。閾值增大,精準率提升,召回率下降;閾值減少,精準率下降,召回率提升。精準率和召回率是相互牽制,互相矛盾的兩個變量,不能同時增高。

import numpy as np
import matplotlib.pyplot as plt
from sklearn import datasets

digits = datasets.load_digits()
X = digits.data
y = digits.target.copy()
y[digits.target==9] = 1
y[digits.target!=9] = 0

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
decision_scores = log_reg.decision_function(X_test)


from sklearn.metrics import precision_score
from sklearn.metrics import recall_score

precisions = []
recalls = []
thresholds = np.arange(np.min(decision_scores), np.max(decision_scores), 0.1)

for threshold in thresholds:
    y_predict = np.array(decision_scores >= threshold, dtype='int')
    precisions.append(precision_score(y_test, y_predict))
    recalls.append(recall_score(y_test, y_predict))
複製代碼
plt.plot(precisions, recalls)
plt.show()
複製代碼

ROC 曲線

ROC(Receiver Operation Characteristic Curve)用來描述 TPR 和 FPR 之間的關係,其中:

  1. TPR(True Positive Rate) 表示真正率,被預測爲正的正樣本結果數 / 正樣本實際數:TPR = TP /(TP + FN)
  2. TNR(True Negative Rate) 表示真負率;被預測爲負的負樣本結果數 / 負樣本實際數:TNR = TN /(TN + FP)
  3. FPR(False Positive Rate) 表示假正率;被預測爲正的負樣本結果數 /負樣本實際數:FPR = FP /(TN + FP)
  4. FNR(False Negative Rate) 表示假負率;被預測爲負的正樣本結果數 / 正樣本實際數:FNR = FN /(TP + FN)
F P R=\frac{F P}{T N+F P}
T P R=\frac{T P}{T P+F N}

實例

import numpy as np
from sklearn import datasets

digits = datasets.load_digits()
X = digits.data
y = digits.target.copy()
y[digits.target==9] = 1
y[digits.target!=9] = 0

from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=666)

from sklearn.linear_model import LogisticRegression
log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
decision_scores = log_reg.decision_function(X_test)

from sklearn.metrics import roc_curve

fprs, tprs, thresholds = roc_curve(y_test, decision_scores)

import matplotlib.pyplot as plt
plt.plot(fprs, tprs)
plt.show()
複製代碼

ROC-曲線

ROC 曲線與圖形邊界圍成的面積,做爲衡量模型優劣的標準,面積越大,模型越優。

相關文章
相關標籤/搜索