1. 程式人生 > >模型的性能評估(二) 用sklearn進行模型評估

模型的性能評估(二) 用sklearn進行模型評估

ant body 指定 cross 學習 median 技術分享 依賴 是把

在sklearn當中,可以在三個地方進行模型的評估

1:各個模型的均有提供的score方法來進行評估。 這種方法對於每一種學習器來說都是根據學習器本身的特點定制的,不可改變,這種方法比較簡單。這種方法受模型的影響,

2:用交叉驗證cross_val_score,或者參數調試GridSearchCV,它們都依賴scoring參數傳入一個性能度量函數。這種方法就是我們下面討論的使用scoring進行模型的性能評估

3:Metric方法,Metric有為各種問題提供的評估方法。這些問題包括分類、聚類、回歸等。這是我們下面的使用metrics進行模型評估

總之,在進行模型評估的時候,我們總是使用上面的三種方法。第一種方法由於比較固定,而且容易使用,所以這裏並不介紹。下面介紹第二種方法和第三種。

使用scoring進行模型的性能評估

在進行模型選擇和評估的時候我們要使用一些策略,這些策略幫助我們更好的進行模型評估,在使用這些策略的時候需要傳入一個scoring參數。比如上面的cross_val_score(使用sklearn進行交叉驗證中有介紹)是用交叉驗證的方法來對模型評分。 還有GridSearchCV和RandomizedSearchCV是用來進行參數選擇的,也需要傳入一個scoring參數,這個參數決定了我們使用什麽樣的方法來進行評分。當需要傳入scoring參數的時候,我們可以有以下幾種做法:

直接指定評分函數的名稱來進行評分

評分函數的選擇是很多的,如我們熟知的f1, recall ,precision等。在用scoring進行模型性能評估的時候直接指定這些就可以完成評分任務。

輸出結果如下:

from sklearn import svm, datasets
from sklearn.model_selection import cross_val_score
iris = datasets.load_iris()

X, y = iris.data, iris.target
clf = svm.SVC(probability=True, random_state=0)
#這裏傳入的為neg_log_loss
# 觀察y值,可以發現y有三個取值的範圍,也就是說這是一個多分類問題,所以當scoring選precision,f1值的時候是不#可以的。
但是可以傳入它們對於多分類問題的變形 如f1_micro, precison_macro等,更多詳見官網 print(cross_val_score(clf, X, y, scoring=neg_log_loss)) model = svm.SVC() #一旦模型傳入一個錯誤的評分函數,會報錯,並且系統會提示出哪些正確的評分函數可以選擇 cross_val_score(model, X, y, scoring=wrong_choice)
[-0.0757138  -0.16816241 -0.07091847]、

ValueError: wrong_choice is not a valid scoring value. Valid options are [accuracy, adjusted_mutual_info_score, adjusted_rand_score, average_precision, completeness_score, explained_variance, f1, f1_macro, f1_micro, f1_samples, f1_weighted, fowlkes_mallows_score, homogeneity_score, mutual_info_score, neg_log_loss, neg_mean_absolute_error, neg_mean_squared_error, neg_mean_squared_log_error, neg_median_absolute_error, normalized_mutual_info_score, precision, precision_macro, precision_micro, precision_samples, precision_weighted, r2, recall, recall_macro, recall_micro, recall_samples, recall_weighted, roc_auc, v_measure_score]

使用metric函數來進行評分

sklearn.metrics裏面提供了一些函數來幫助我們進行評分。其中裏面以_score結尾的函數的返回值越大,模型的性能越好。而以_error或_loss結尾的函數,返回值越小,表示模型性能越好。從命名上來看,這一點不難理解。

metrics裏面的很多函數名不直接傳入scoring後面,因為有一些函數需要傳入特定的參數才能夠使用。比如在使用fbeta_score的時候需要傳入bata參數等。 在這個時候,我們的做法是把函數名和參數封裝一下,封裝成為一個新的函數,然後傳入scoring後面。封裝的方法是使用metrics的make_scorer方法。

下面是一個小例子:

from sklearn.metrics import make_scorer, fbeta_score
#我們用make_scorer封裝了fbeta_score,它需要傳入一個參數
ftwo_score = make_scorer(fbeta_score, beta=2)
from sklearn.model_selection import GridSearchCV
from sklearn.svm import LinearSVC
grid = GridSearchCV(LinearSVC(), param_grid={C:[1, 10]}, scoring=ftwo_score)

使用metrics的make_score方法,我們可以制定出我們自己的方法,這個方法需要滿足下面一些條件:

  • 需要傳入一個我們自定義的函數的名稱
  • 需說明greater_is_better的值是True還是False。 當值為正的時候,返回的是score的值,值越高性能越好。當為False的時候,返回的為score的負值,值越低越好。
  • 是否是針對分類問題的。 傳入needs_threshold=True來說明是針對分類問題的,默認情況為False。
  • 其余的參數。如在f1_score中的bata,labels。

我們來看一段代碼:

import numpy as np
from sklearn.metrics import make_scorer

def my_custom_loss_func(ground_truth, predictions):
    diff = np.abs(ground_truth - predictions).max()
    return np.log(1 + diff)

loss  = make_scorer(my_custom_loss_func, greater_is_better=False)
score = make_scorer(my_custom_loss_func, greater_is_better=True)
ground_truth = [[1], [1]]
predictions  = [0, 1]
from sklearn.dummy import DummyClassifier
clf = DummyClassifier(strategy=most_frequent, random_state=0)
clf = clf.fit(ground_truth, predictions)
#這段代碼的原理是這樣的,我們的clf使用ground_truth 和predictions進行訓練
#使用clf.predict(ground_truth) 進行預測以後的結果為[0,0],
#my_custom_loss_func(np.array([0,0], np.array[0,1]) 最後得到log(2) = 0.69314
print(score(clf, ground_truth, predictions))
print(loss(clf, ground_truth, predictions))

輸出結果如下:

0.6931471805599453
-0.6931471805599453

我們用make_score封裝了我們自己的函數my_custom_loss_func 來進行模型的評分。 score和loss的結果輸出相反。

我們還可以實現我們自己的評分對象

為了實現更高的自由度,我們可以不使用上述的make_scorer方法,完全定制出來我們自己的評分對象,這需要遵循兩點

  • 能夠調用(estimater, X, y)參數,estimater是我們的模型,X為數據集, y為X數據集的真實結果。
  • 需要返回一個分數作為評分的結果。該分數能夠從某個方面反映出我們模型的好壞。

傳入多個評分方法

在GridSearchCV, RandomizedSearchCV 和 cross_validate 的scoring參數當中還可以傳入多個評分方法,來從不同的角度來進行評分。有兩種方法,一種是傳入一個列表,另外一個是傳入一個字典。

傳入列表:

scoring = [accuracy, precision]

傳入字典:

from sklearn.metrics import accuracy_score
from sklearn.metrics import make_scorer
scoring = {accuracy : make_scorer(accuracy_score), prec:precision}

傳入字典中的方法既可以是一個字符串,也可以是一個封裝的方法,這些方法需要返回一個值,返回多個值是是不允許的。

from sklearn.svm import LinearSVC
from sklearn import datasets
from sklearn.metrics import accuracy_score
from sklearn.metrics import make_scorer
from sklearn.metrics import confusion_matrix

X, y = datasets.make_classification(n_classes=2, random_state=0)
‘‘‘
從混淆矩陣當中定義出tn,fp,fn,tp的值,混淆矩陣的值如下,(官網當中的例子疑似錯誤):
TN FP
FN TP
‘‘‘
def tp(y_true, y_pred): return confusion_matrix(y_true, y_pred)[1, 1]
def tn(y_true, y_pred): return confusion_matrix(y_true, y_pred)[0, 0]
def fp(y_true, y_pred): return confusion_matrix(y_true, y_pred)[0, 1]
def fn(y_true, y_pred): return confusion_matrix(y_true, y_pred)[1, 0]
scoring = {tp : make_scorer(tp), tn : make_scorer(tn),
                      fp : make_scorer(fp), fn : make_scorer(fn)}

svm = LinearSVC(random_state=0)
from sklearn.model_selection import cross_validate
#我們傳入了一個字典來看這個模型的各種評分情況
cv_result = cross_validate(svm.fit( X,y), X, y, scoring=scoring)
print(cv_result[test_tp])  #test後面跟scoring的可以,就可以打得到測試的結果
print(cv_result[test_fp])

輸出結果如下:

[16 14  9]
[5 4 1]

使用metrics進行模型評估

在模型的性能評估 - 理論篇這篇文章中,我們介紹了accuracy、precision、混淆矩陣、F1參數、$F_{\beta}$參數、ROC和AUC,均方誤差。下面我們用metrics中的方法來實現一些這些。

Accuracy score

metrics中的accuracy_score方法可以幫助我們計算accuracy(準確率),也就是$\frac{分類正確的樣本個數}{所有的樣本個數}$。 這個方法對於二分類問題、多分類問題、多標簽分類問題都適合。例子如下:

import numpy as np
from sklearn.metrics import accuracy_score

y_pred = [0, 2, 1, 3]
y_true = [0, 2, 2, 3]
print(accuracy_score(y_pred, y_true))

結果為: 0.75

Confusion matrix

confusion_matrix是計算出混淆矩陣,矩陣中的第i行,第j列的值為:實際上是第i類,但是卻預測為第j類的樣本的個數。

from sklearn.metrics import confusion_matrix
y_true = [2, 0, 2, 2, 0, 1]
y_pred = [0, 0, 2, 2, 0, 2]
print(confusion_matrix(y_true, y_pred))

結果如下:

[[2 0 0]
 [0 0 1]
 [1 0 2]]

對於二分類問題,混淆矩陣變為了

tn,fp

fn, tp

from sklearn.metrics import confusion_matrix
y_true = [0, 0, 0, 1, 1, 1, 1, 1]
y_pred = [0, 1, 0, 1, 0, 1, 0, 1]
tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()
print(tn, fp, fn, tp)

輸出結果為 : 2 1 2 3

Precision,Recall 和F-matures

對於二分類問題,我們直接使用metrics裏面的方法進行計算

from sklearn import metrics
y_pred = [0, 1, 0, 0]
y_true = [0, 1, 0, 1]

print( metrics.precision_score(y_true, y_pred) )
print( metrics.recall_score(y_true, y_pred) )
print( metrics.f1_score(y_true, y_pred) )
print( metrics.fbeta_score(y_true, y_pred, beta=0.5) )
print( metrics.fbeta_score(y_true, y_pred, beta=1) )
print( metrics.fbeta_score(y_true, y_pred, beta=2) )

輸出的結果如下:

1.0
0.5
0.6666666666666666
0.8333333333333334
0.6666666666666666
0.5555555555555556

這些函數用起來很簡單,名稱後面加上_score就可以了。

還有一個方法,precision_recall_fscore_support 直接把precision、recall、fscore和support的值都顯示出來,其中support是每個標簽在y_true中出現的次數。 這裏的標簽是y的取值情況,在二分類問題中,標簽為0和1兩種情況。

print( metrics.precision_recall_fscore_support(y_true, y_pred, beta=0.5)  )

輸出如下:第一列是0作為標簽時候的四個值,第二列是1作為標簽時候的四個值。

(array([0.66666667, 1.        ]), array([1. , 0.5]), array([0.71428571, 0.83333333]), array([2, 2], dtype=int64))

P-R曲線

可以使用precision_recall_curve來計算出來在不同的閾值下P和R的值,

import numpy as np
from sklearn.metrics import precision_recall_curve
from sklearn.metrics import average_precision_score

y_true = np.array([0, 0, 1, 1])
y_scores = np.array([0.1, 0.4, 0.34, 0.8])
precision, recall , threshold = precision_recall_curve(y_true, y_scores)
print(precision)
print(recall)
print(threshold)

print(average_precision_score(y_true, y_scores))

輸出結果如下:

[0.66666667 0.5        1.         1.        ]
[1.  0.5 0.5 0. ]
[0.34 0.4  0.8 ]
0.8333333333333333

當然,可以根據這個結果畫出圖形,

import matplotlib.pyplot as plt
plt.scatter(recall, precision)
plt.ylim([0, 1.1])
plt.show()

技術分享圖片

P-R圖形

ROC和AUC

受試者工作特征曲線,可以使用roc_curve來實現

import numpy as np
from sklearn.metrics import roc_curve
y = np.array([1, 1, 2, 2])
scores = np.array([0.1, 0.4, 0.35, 0.8])
fpr, tpr, thresholds = roc_curve(y, scores, pos_label=2)

print(fpr)
print(tpr)
print(thresholds)

輸入結果如下:

[0.  0.5 0.5 1. ]
[0.5 0.5 1.  1. ]
[0.8  0.4  0.35 0.1 ]

同樣,也可以畫一張圖

import matplotlib.pyplot as plt
plt.scatter(fpr, tpr)
plt.ylim([0,1.1])
plt.show()

技術分享圖片

ROC圖形

使用roc_auc_score可以計算AUC的值

import numpy as np
from sklearn.metrics import roc_auc_score
y_true = np.array([0, 0, 1, 1])
y_scores = np.array([0.1, 0.4, 0.35, 0.8])
print(roc_auc_score(y_true, y_scores))

計算得到的結果為: 0.75

mean square error

這是評估回歸問題所使用的方法:

from sklearn.metrics import mean_squared_error
y_true = [3, -0.5, 2, 7]
y_pred = [2.5, 0.0, 2, 8]
print(mean_squared_error(y_true, y_pred))

結果是0.375

總結

sklearn有三個地方可以實現模型性能度量,我們介紹了兩個。一個是交叉驗證策略和參數選擇策略中的scoring方法,傳入我們的方法即可。另外一個是metrics裏面的方法,我們需要的方法都可以在這裏面找到。

參考:

Model evaluation: quantifying the quality of predictions

模型的性能評估(二) 用sklearn進行模型評估