簡體   English   中英

sklearn.model_selection.cross_val_score 與對混淆矩陣進行手動計算的結果不同

[英]sklearn.model_selection.cross_val_score has different results from a manual calculation done on a confusion matrix

TL;DR 當我通過 CV cross_val_score()計算精度、召回率和 f1 時,它給我的結果與通過混淆矩陣計算時不同。 為什么它給出不同的精度、召回率和 f1 分數?

我正在學習機器學習中的 SVM,我想比較cross_val_score返回的結果和我從混淆矩陣中手動計算指標得到的結果。 但是,我有不同的結果。

首先,我使用cross_val_score編寫了下面的代碼。

clf = svm.SVC()
kfold = KFold(n_splits = 10)

accuracy = metrics.make_scorer(metrics.accuracy_score)
precision = metrics.make_scorer(metrics.precision_score, average = 'macro')
recall = metrics.make_scorer(metrics.recall_score, average = 'macro')
f1 = metrics.make_scorer(metrics.f1_score, average = 'macro')

accuracy_score = cross_val_score(clf, X, y, scoring = accuracy, cv = kfold)
precision_score = cross_val_score(clf, X, y, scoring = precision, cv = kfold)
recall_score = cross_val_score(clf, X, y, scoring = recall, cv = kfold)
f1_score = cross_val_score(clf, X, y, scoring = f1, cv = kfold)

print("accuracy score:", accuracy_score.mean())
print("precision score:", precision_score.mean())
print("recall score:",recall_score.mean())
print("f1 score:", f1_score.mean())

每個指標的結果如下所示:

accuracy score: 0.97
precision score: 0.96
recall score: 0.97
f1 score: 0.96

此外,我創建了一個混淆矩陣,以便我可以根據矩陣上的值手動計算准確率、精度、召回率和 f1 分數。 我手動創建了混淆矩陣,因為我使用的是 K 折交叉驗證。 為此,我必須為交叉驗證的每次迭代獲取實際類和預測類,因此我有以下代碼:

def cross_val_predict(model, kfold : KFold, X : np.array, y : np.array) -> Tuple[np.array, np.array]:
    
    model_ = cp.deepcopy(model)
    
    # gets the number of classes in the column/attribute
    no_of_classes = len(np.unique(y))
    
    # initializing empty numpy arrays to be returned
    actual_classes = np.empty([0], dtype = int)
    predicted_classes = np.empty([0], dtype = int)

    for train_index, test_index in kfold.split(X):

        X_train, X_test = X[train_index], X[test_index]
        y_train, y_test = y[train_index], y[test_index]
        
        # append the actual classes for this iteration
        actual_classes = np.append(actual_classes, y_test)
        
        # fit the model
        model_.fit(X_train, y_train)
        
        # predict
        predicted_classes = np.append(predicted_classes, model_.predict(X_test))
        
    return actual_classes, predicted_classes

之后,我在調用上述函數后創建了我的混淆矩陣。

actual_classes, predicted_classes = cross_val_predict(clf, kfold, X, y)
cm = metrics.confusion_matrix(y_true = actual_classes, y_pred = predicted_classes)
cm_display = metrics.ConfusionMatrixDisplay(confusion_matrix = cm, display_labels = [2,4])
cm_display.plot()

現在,我的混淆矩陣如下所示:

where: col is the predicted label, and row is the true label.

    |------|------|
 2  | 431  |  13  |
    |------|------|
 4  |  9   | 230  |
    |------|------|
       2      4

如果我從該矩陣手動計算准確率、精度、召回率和 f1 分數,我有 ff:

confusion matrix accuracy: 0.97
confusion matrix precision: 0.95
confusion matrix recall: 0.96
confusion matrix f1 score: 0.95

我的問題是,為什么我從混淆矩陣中手動計算指標得到不同的結果,而在指定要使用哪個記分器時調用cross_val_score得到不同的結果,即 [accuracy,precision,recall,fscore]。

我希望你們能幫助我理解為什么。 非常感謝您的回復!

使用cross_val_score ,您可以獲取在每個折疊上計算的指標的平均值,但是當您手動執行此操作時,您會在計算分數之前連接預測。 因此,修改了 F1 分數、精度,而准確率和召回率不受影響。

准確性

如果 n 是您擁有的樣本數,而 k 是折疊數,那么您可以編寫: 准確性

從這個等式可以看出,在每個折疊大小相同的情況下,對准確率求平均值就相當於計算全局平均值。 但是,如果某些折疊具有不同的大小,則情況並非如此。 但是由於差異僅是一個參與者的最大值,並且與數據集大小相比,一個參與者通常很小,所以折疊平均值和整個預測精度的計算值之間的差異是不同的。

精確

現在讓我們考慮精度(但對於從兩個精度計算的 f1 分數或 ROC AUC 也是如此); 這是真陽性/陽性預測的比率

假設你有 3 折:

  • 折疊 1 :4 個正預測,1 個真正:精度 = 1/4

  • 折疊 2 :2 個正預測,2 個真正:精度 = 1

  • 折疊 3 :3 個正預測,1 個真正:精度 = 1/3

現在,如果您取平均值,您將獲得19/36=0.527的精度。 但是,如果您得到一些正面預測和真實正面的數量,您會得到4/9=0.44 ,這是完全不同的。

不同之處在於分母,即你的積極預測的數量,在折疊上不是恆定的。 取平均值時,極值的影響更大。

記起

召回率是True positive/Positive samples的比率。 在您對 k 折進行分層的情況下,平均值應與您的級聯指標相同。

使用哪個?

這是一個我還沒有找到明確答案的問題。 大多數框架或定義都使用分數的平均值,但我沒有發現任何與計算所有預測的指標的比較,所以這里有一些個人觀察:

  • 計算每個折疊的度量似乎是最常用的方法。 優點是您可以獲得平均值,還可以獲得指標的標准/四分位數。 有了這個,你可以真正評估學習過程的表現,前提是你有足夠的數據。
  • 對於較小的樣本量,評估折疊可能非常短(樣本很少)。 在這種情況下,指標不太穩定(更容易達到極值),我發現平均值仍然對極值敏感。 在那里,我建議您連接預測/目標以計算分數,但這只是個人觀察和意見

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM