天天看點

ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式

評估方法

  • 線性回歸算法評估方式
    • MSE/RMSE/MAE/R Squared
    • scikit-learn中的MSE/MAE/R Squared
  • 分類算法評估方式
    • 準确率(accuracy)
    • 混淆矩陣
      • 查準率(precision)
      • 查全率(recall/TPR)
      • F1 Score
      • scikit-learn中的API
      • 畫混淆矩陣
    • 查全率和查準率的平衡(PR曲線)
    • ROC曲線及其面積AUC
    • PR曲線及ROC曲線總結

線性回歸算法評估方式

  • MSE/RMSE/MAE/R Squared

  1. 均方誤差MSE(mean squared error): m s e = ∑ i = 1 m ( y ^ i − y i ) 2 m mse = \frac{\sum_{i=1}^m(\hat y_{i} - y_{i})^2}{m} mse=m∑i=1m​(y^​i​−yi​)2​

    (mse的标量是真實标量的平方,線性回歸損失函數也用此公式)

  2. 均方根誤差RMSE(root mean squared error): r m s e = ∑ i = 1 m ( y ^ i − y i ) m rmse = \sqrt \frac{\sum_{i=1}^m(\hat y_{i} - y_{i})}{m} rmse=m∑i=1m​(y^​i​−yi​)​

    (預測值與真實值誤差為 ± r m s e \pm rmse ±rmse)

  3. 均方絕對誤差MAE(mean absolute error): m a e = ∑ i = 1 m ∣ y ^ i − y i ∣ m mae = \frac{\sum_{i=1}^m|\hat y_{i} - y_{i}|}{m} mae=m∑i=1m​∣y^​i​−yi​∣​

    (預測值與真實值誤差為 ± m a e \pm mae ±mae)

  4. R Squared:
    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
  • 公式中:分式---->分子即為模型預測産生誤差用MSE計算,分母為模型的基準誤差(方差也就是最大誤差)。預測産生的誤差與最大誤差的比。
  • 因為1減去分式,是以 R 2 < = 1 R^2<=1 R2<=1, R 2 R^2 R2越大越好,為1時表示分式為0,我們模型不犯任何錯誤。為0時表示預測誤差等于基準誤差。<0時表示還不如基準模型,很可能我們的資料不存在任何線性關系。
  • scikit-learn線性回歸方法中score計算準确率,封裝評估方式就是 R 2 R^2 R2 。
  • scikit-learn中的MSE/MAE/R Squared

from sklearn.metrics import mean_squared_error
from sklearn.metrics import mean_absolute_error
from sklearn.metrics import r2_score

mean_squared_error(y_test, y_predict)
mean_absolute_error(y_test, y_predict)
r2_score(y_test,y_predict)
           

分類算法評估方式

  • 準确率(accuracy)

    1. 公式: a c c u r a c y = 分 類 正 确 樣 本 數 / 樣 本 總 數 accuracy = 分類正确樣本數 / 樣本總數 accuracy=分類正确樣本數/樣本總數
    2. 是最基本的評估方式,但是對于分布極度偏斜的資料,隻是用準确度評估是不夠的,就會出現問題。

      eg:有100人,其中90個健康,10個患病。假設100人經過模型預測,全部認定為健康。模型一個患病的都沒有預測成功,但是模型準确率卻有90%,是以将需要有更多的評估方式來評估模型的性能好壞。

  • 混淆矩陣

    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
    1. 最左邊一列代表樣本真實标記值,最上面一行代表樣本預測值。
    2. 通常定标記0代表負樣本,1代表正樣本(即我們關注的類别)。

      eg:醫療中判斷是否患病1類作為患病類,金融中判斷是否有風險1類作為風險類。

    3. 矩陣中按順序:

      TN(真負樣本),預測為0類且真值也為0類的樣本。FN(假負樣本),預測為1類但真值為0類的樣本。

      FP(假正樣本),預測為0類但真值為1類的樣本。TP(真正樣本),預測為1類且真值也為1類的樣本。

    4. 樣本總數 = TN+FN+FP+TP

    查準率(precision)

    1. 模型判定為正樣本中,正确的數量。
    2. p r e c i s i o n = T P F P + T P precision = \frac{TP}{FP+TP} precision=FP+TPTP​

    查全率(recall/TPR)

    1. 對資料集中正樣本,模型預測對了多少。
    2. r e c a l l = T P F N + T P recall = \frac{TP}{FN+TP} recall=FN+TPTP​

    F1 Score

    1. 有時候我們注重查準率,例如預測股票是升還是跌,查全率就顯得不那麼總要,我們不需要查出所有升的股票,我們隻要保證我們預測出的升的股票準确率是高的。
    2. 有時候我們注重查全率,例如醫療領域,最好的就是把所有有病的患者都查出來,相對對于準确率的要求就沒有那麼高,就算沒病判斷成有病可再進一步檢查,确診。
    3. 當然有些情況下,不是完全偏向于某一方,是希望查全率和查準率均衡,兼顧二者。新的衡量标準 F1 Score:

      使用了查全率和查準率的調和平均值:

      1 F 1 = 1 2 ( 1 p r e c i s i o n + 1 r e c a l l l ) \frac{1}{F1} = \frac{1}{2}(\frac{1}{precision}+\frac{1}{recalll}) F11​=21​(precision1​+recalll1​)

      F 1 = 2 ⋅ p r e c i s i o n ⋅ r e c a l l l p r e c i s i o n + r e c a l l F1 = \frac{2\cdot precision\cdot recalll}{precision+recall} F1=precision+recall2⋅precision⋅recalll​

      F1的範圍[ 0 , 1 ]。隻有在二者同時很高的情況下,F1的值才會很高,任何一方值是低的都會拉低F1評估值。

    scikit-learn中的API

#混淆矩陣
from sklearn.metrics import confusion_matrix
confusion_matrix(y_test, y_predict)
#查準率(percision)
from sklearn.metrics import precision_score
precision_score(y_test, y_predict,average=‘binary’)
#查全率(recall)
from sklearn.metrics import recall_score
recall_score(y_test, y_predict, average=‘binary’)
#F1 Score
from sklearn.metrics import f1_score
f1_score(y_test, y_predict)

'''
其中precision_score和recall_score有參數average,預設binary适用于二分類。
當為多分類任務需調整,主要有'macro'和'weigthed'。
以precision_score為例:'macro':不考慮各類别的樣本數量,結果為:各類别p的均值。
'weigthed':考慮各類别的樣本數量,結果為:各類别p乘各類别樣本數量,求和,再除總樣本數 。
若測試的各類别樣本數量明顯不均衡應采用weigthed。
'''
           

畫混淆矩陣

from sklearn.metrics import confusion_matrix
import seaborn as sn
#多分類(3類)
cfm = confusion_matrix(y_test, y_predict)
>>> array(預測   0    1	   2
	  真實 0  [[147,   6,   0],
     	   1   [  7, 123,   0],
    	   2   [  1,   0, 134]])

#每行樣本數
row_sums = np.sum(cfm, axis=1)
#新矩陣:每格占樣本數的比
err_matrix = cfm / row_sums
#将新矩陣對角線都填成0,因為我們不關心正确的個數,剩下的每個格子都是預測錯誤的占比。
np.fill_diagonal(err_matrix, 0)
ax1 = sn.heatmap(err_matrix, annot= True ,linewidths = 0.05, xticklabels=['put on',"take off","scratch"],
yticklabels=['put on',"take off","scratch"])
ax1.set_title("Confusion Matrix")
ax1.set_ylabel("True label")
ax1.set_xlabel("Predict label")
           
ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
  • 查全率和查準率的平衡(PR曲線)

  1. 查全率和查準率是互斥的,通常一個升高另一個便會下降,有時候我們需要查全率高,有時候我們又需要查準率高。
  2. 接下來要讨論的是一個很厲害的東西,通過決策邊界(Threshold)來調整一個訓練好的模型的查全率和查準率。
  3. 那什麼是決策邊界(Threshold)呢?以LogisticRegression為例:

      LogisticRegression是對線性回歸模型計算的結果( y = X b ⋅ θ y = X_{b}\cdot \theta y=Xb​⋅θ),再用一個函數(sigmoid)進行轉化得到[0,1]間的機率,定義以機率0.5為分界線,大于0.5歸為1類,小于0.5的歸為0類。根據sigmoid函數的性質,機率為0.5時, X b ⋅ θ X_{b}\cdot \theta Xb​⋅θ值是為0,是以也就變成 X b ⋅ θ > 0 X_{b}\cdot \theta>0 Xb​⋅θ>0 時歸為1類, X b ⋅ θ < 0 X_{b}\cdot \theta<0 Xb​⋅θ<0 時歸為0類。不清楚LogisticRegression算法的可以看我另一篇部落格:[LogisticRegression詳解]。

      是以, X b ⋅ θ = 0 X_{b}\cdot \theta = 0 Xb​⋅θ=0 就稱為決策邊界,0即可替換為任意值的Threshold,當 X b ⋅ θ > T h r e s h o l d X_{b}\cdot \theta > Threshold Xb​⋅θ>Threshold 時分為1類,當 X b ⋅ θ < T h r e s h o l d X_{b}\cdot \theta < Threshold Xb​⋅θ<Threshold 時分為0類。

  4. 舉個例子:

    一共有12個樣本,五角星代表我們關注的對象為1類。

    當Threshold = 0 ,右邊為大于0的部分分為1類, p r e c i s i o n = 0.8 , r e c a l l = 0.67 precision = 0.8, recall = 0.67 precision=0.8,recall=0.67

    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
    當Threshold = 2 ,右邊為大于2的部分分為1類, p r e c i s i o n = 1.0 , r e c a l l = 0.33 precision = 1.0, recall = 0.33 precision=1.0,recall=0.33
    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
    當Threshold = -3 ,右邊為大于-3的部分分為1類, p r e c i s i o n = 0.75 , r e c a l l = 1.0 precision = 0.75, recall = 1.0 precision=0.75,recall=1.0
    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
    在同一模型下,調整閥值,recall上升(下降)時,presicion是下降(上升)的,按不同閥值畫出曲線即PR曲線。
  5. 那應該如何修改Threshold調整預測結果呢?請看下面。

    首先要明确一點,是對已經訓練好的模型,在predict時調整決策邊界(threshold),改變預測分類結果。

    在scikit-learn中LogsticRegression預設的predict就是以 X b ⋅ θ = 0 X_{b}\cdot \theta = 0 Xb​⋅θ=0 為分界線,即sigmoid( X b ⋅ θ ) X_{b}\cdot \theta) Xb​⋅θ)大于0.5 為1,小于0.5為0。

from sklearn.linear_model import LogisticRegression
from sklearn.metrics import precision_score
from sklearn.metrics import recall_score

log_reg = LogisticRegression()
log_reg.fit(X_train, y_train)
#預設predict,threshold為0的預測結果
y_predict = log_reg.predict(X_test)
precision_score(y_test, y_predict)
>>> 0.9473549684225426
recall_score(y_test, y_predict)
>>> 0.8000000000000004

'''調整threshold的方式'''
#1.通過API:decision_function,獲得未經過sigmoid函數的預測值,即 Xb⋅ θ 的值。
decision_scores = log_reg.decision_function(X_test)
>>> [-22.0315,-33.1241,-0.9412,4.1312,15.2345,......]
#2.不使用sigmoid,通過直接給Threshold值來生成預測結果。decision_scores中大于-5的分為1類,小于-5的分為0類。
y_predict_2 = np.array(decision_scores >= -5, dtype='int')
#3.看查全率和查準率的變化
precision_score(y_test, y_predict_2)
>>> 0.72727272727272729
recall_score(y_test, y_predict_2)
>>> 0.88888888888888884

           
  1. 那該如何決定最佳的threshold呢?PR曲線誕生。
'''scikit-learn 中的precision_recall_curve
   輸入參數:測試集真值(y_test)和未經過sigmoid函數的預測值(由API:decision_function擷取)
   傳回值:查準率數組,記錄了每一個threshold對應的precision,數組最後一個值是1,且沒有對應的threshold。
   		  查全率數組,記錄了每一個threshold對應的recall,數組最後一個值是0,且沒有對應的threshold。
   		  threshold數組,記錄了每一個threshold,這些threshold是skl自動規劃間距得出有意義的threshold。
   		  threshold數組是比查準率數組和查全率數組少一個元素的。
'''
from sklearn.metrics import precision_recall_curve
precisions,recalls,thresholds = precision_recall_curve(y_test, decision_scores)

# 橫坐标為threshold,縱坐标為對應的precison(藍色)和recall(橘色)
# 因為precision數組和recall數組最後一個元素是沒有對應的threshold,是以去掉。
plt.plot(thresholds, precisions[:-1])
plt.plot(thresholds, recalls[:-1])
plt.show()
           

交彙處即為查準率和查全率最平衡的閥值。

ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
# PR曲線
plt.plot(precisions, recalls)
plt.show()
           

拐點處即為查準率和查全率最平衡的閥值。

ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式

  7.PR曲線除了可以用來權衡查全率和查準率,還可用于評價不同模型之間的性能。precision相同時,recall越高越好,反之亦然。

ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式

   通常一條PR曲線能夠包住另一條曲線,表示此曲線效能優于另一條曲線。

ROC曲線及其面積AUC

  • Receiver Operation Characteristic Curve 描述TPR和FPR之間的關系。
  • TPR (查全率/真正率),對資料集中的正樣本,模型預測對了多少。
    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
  • FPR (假正率) ,對資料集中的負樣本,模型預測錯了多少。
    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
  • TPR和FPR關系:
    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式

    在同一模型下,調整閥值,TPR升高(下降)時,.FPR也同升高(下降)。

    按不同閥值畫出的曲線即為ROC曲線: FPR相同TPR越高越好,TPR相同時,FPR越小越好。

    ML(6)-Evaluate模型評估方法線性回歸算法評估方式分類算法評估方式
    ROC通常用來比較兩個模型孰優孰劣,ROC 曲線下,面積AUC更大的模型,效能通常更好。
  • 注意TPR用到的TP和FN同屬正樣本集,FPR用到的FP和TN同屬負樣本集,分别是對不同樣本集求得的比例,是以即使資料集中正或負樣本的數量及其不均衡,也不會影響到另一類。也就是說,ROC曲線值不受類别樣本個數的影響。某種程度上這是ROC曲線的優點,即具有魯棒性,在類别分布發生明顯改變的情況下依然能客觀地識别出較好的分類器。
  • 但上面優點也同樣是ROC中不足,即ROC若用在類别極度不平均的資料集中,評估值的變化就會非常的小,難以評估模型性能的變化。

    eg: 一個資料集有正例100,負例10000。第一次模型有20個負樣本判斷錯誤,60個正樣本判斷正确,這樣 F P R = 20 10000 = 0.002 FPR = \frac{20}{10000} = 0.002 FPR=1000020​=0.002, T P R ( r e c a l l ) = 60 100 = 0.6 TPR(recall) = \frac{60}{100} = 0.6 TPR(recall)=10060​=0.6,第二次模型有40個負樣本判斷錯誤,60個正樣本判斷正确,這樣 F P R = 40 10000 = 0.004 FPR = \frac{40}{10000} = 0.004 FPR=1000040​=0.004, T P R ( r e c a l l ) = 60 100 = 0.6 TPR(recall) = \frac{60}{100} = 0.6 TPR(recall)=10060​=0.6。兩次FPR的變化在ROC曲線上微弱到難以觀察。但與FPR相比,此時 p r e c i s i o n precision precision 卻從0.75 降到了0.6 ,在PR曲線上會出現明顯的變化。

  • scikit-learn中的ROC
'同precision_recall_curve使用方式一緻'
from sklearn.metrics import roc_curve
fprs, tprs, thresholds = roc_curve(y_test, decision_scores)
plt.plot(fprs, tprs)
plt.show()

'''計算ROC曲線下方的面積AUC'''
from sklearn.metrics import roc_auc_score
roc_auc_score(y_test, decision_scores)
           

PR曲線及ROC曲線總結

  • PR曲線及F1-score僅關注對資料集中正樣本的預測情況,ROC曲線同時關注對資料集中正樣本和負樣本的預測情況。PR曲線會受資料集中類别樣本個數變化影響,而ROC曲線不會受資料集中類别樣本個數變化影響。
  • 對于類别數量不平衡問題中,訓練集驗證集類别數量分布都是不均衡的,當模型變化時,ROC曲線評估值變化是微弱的有時難以比較,是以大部分時候使用PR曲線更好。
  • 但如果對于驗證集中類别數量分布是多變時(有時不均衡、有時均衡),那ROC曲線是不受類别數量的影響,而PR曲線卻會變化巨大,是以此時使用ROC評估模型更好。

繼續閱讀