3.4. 指標與評分:量化預測品質#

3.4.1. 我應該使用哪個評分函數?#

在我們更仔細地研究許多分數和評估指標的細節之前,我們想根據統計決策理論,為監督式學習評分函數的選擇提供一些指導,請參閱[Gneiting2009]

  • 我應該使用哪個評分函數?

  • 哪個評分函數對我的任務來說是好的?

簡而言之,如果評分函數是給定的,例如在 kaggle 比賽或業務背景中,請使用該函數。如果您可以自由選擇,則首先要考慮預測的最終目標和應用。區分兩個步驟很有用:

  • 預測

  • 決策制定

預測: 通常,反應變數 \(Y\) 是一個隨機變數,因為特徵 \(X\) *沒有確定性* 函數 \(Y = g(X)\)。相反,\(Y\) 有一個機率分佈 \(F\)。人們可以旨在預測整個分佈,稱為機率預測,或者—更關注 scikit-learn 的—透過選擇該分佈 \(F\) 的屬性或函數來發出點預測(或點預報)。典型的例子是反應變數 \(Y\) 的平均值(期望值)、中位數或分位數(以 \(X\) 為條件)。

一旦確定了這一點,請針對該(目標)函數使用嚴格一致的評分函數,請參閱 [Gneiting2009]。這表示使用與測量預測 y_pred 和使用 \(Y\) 的觀察值(即 y_true)的真實目標函數之間的距離一致的評分函數。對於分類,請參閱 Wikipedia 的評分規則條目[Gneiting2007]嚴格適當的評分規則與嚴格一致的評分函數一致。下表提供了範例。可以說一致的評分函數充當真理血清,因為它們保證「在期望中,說真話 […] 是一種最佳策略」[Gneiting2014]

一旦選擇了嚴格一致的評分函數,最好將其同時用於:作為模型訓練的損失函數,以及作為模型評估和模型比較的指標/分數。

請注意,對於迴歸器,預測是使用 predict 完成的,而對於分類器,則通常是 predict_proba

決策制定: 最常見的決策是在二元分類任務上完成的,其中 predict_proba 的結果會轉為單一結果,例如,從預測的降雨機率中,做出如何行動的決定(是否採取像雨傘這樣的減輕措施)。對於分類器,這是 predict 返回的內容。另請參閱調整類別預測的決策閾值。有許多評分函數可以衡量此類決策的不同方面,其中大多數都包含在或衍生自metrics.confusion_matrix

嚴格一致評分函數列表:在這裡,我們列出了一些最相關的統計函數以及用於實務中任務的相應嚴格一致評分函數。請注意,此列表並不完整,並且還有更多。有關如何選擇特定函數的更多標準,請參閱[Fissler2022]

函數

評分或損失函數

回應 y

預測

分類

平均值

Brier 分數 1

多類別

predict_proba

平均值

對數損失

多類別

predict_proba

眾數

零一損失 2

多類別

predict,類別

迴歸

平均值

平方誤差 3

所有實數

predict,所有實數

平均值

泊松偏差

非負數

predict,嚴格正數

平均值

伽瑪偏差

嚴格正數

predict,嚴格正數

平均值

Tweedie 偏差

取決於 power

predict,取決於 power

中位數

絕對誤差

所有實數

predict,所有實數

分位數

釘球損失

所有實數

predict,所有實數

眾數

不存在一致的函數

實數

1 在分類的情況下,Brier 分數只是平方誤差的另一個名稱。

2 零一損失僅適用於眾數,但並非嚴格一致。零一損失等同於一減去準確度分數,這表示它會給出不同的分數值,但排名相同。

3 R² 給出的排名與平方誤差相同。

虛構範例: 讓我們讓上述論點更具體。考慮網路可靠性工程中的設定,例如維護穩定的網際網路或 Wi-Fi 連線。作為網路的供應商,您可以存取包含隨時間推移的網路負載和許多有趣功能的網路連線記錄條目的資料集。您的目標是提高連線的可靠性。事實上,您向客戶承諾,在至少 99% 的日子裡,不會出現大於 1 分鐘的連線中斷。因此,您有興趣預測 99% 的分位數(每天最長連線中斷時間),以便提前知道何時增加頻寬,從而滿足您的客戶。因此,目標函數是 99% 的分位數。從上表中,您選擇釘球損失作為評分函數(公平地說,沒有太多選擇),用於模型訓練(例如 HistGradientBoostingRegressor(loss="quantile", quantile=0.99))以及模型評估(mean_pinball_loss(..., alpha=0.99) - 我們為不同的參數名稱 quantilealpha 表示歉意),無論是在網格搜尋中尋找超參數,還是在與其他模型(如 QuantileRegressor(quantile=0.99))進行比較時。

參考文獻

[Gneiting2007]

T. Gneiting 和 A. E. Raftery. 嚴格的評分規則、預測和估計 在: 美國統計協會期刊 102 (2007), pp. 359– 378. pdf 連結

[Gneiting2009] (1,2)

T. Gneiting. 制定和評估點預測 美國統計協會期刊 106 (2009): 746 - 762.

[Gneiting2014]

T. Gneiting 和 M. Katzfuss. 機率預測. 在: 統計及其應用年度評論 1.1 (2014), pp. 125–151.

3.4.2. 評分 API 概述#

有 3 種不同的 API 可用於評估模型預測的品質

最後,虛擬估算器對於獲取隨機預測的這些度量的基準值很有用。

另請參閱

對於 樣本 之間而不是估算器或預測之間的「成對」度量,請參閱成對度量、親和性和核心部分。

3.4.3. scoring 參數:定義模型評估規則#

內部使用交叉驗證的模型選擇和評估工具(例如model_selection.GridSearchCVmodel_selection.validation_curvelinear_model.LogisticRegressionCV)採用 scoring 參數,該參數控制它們將哪個度量應用於評估的估算器。

它們可以用幾種方式指定

  • None:使用估算器的預設評估標準(即,估算器的 score 方法中使用的度量)。

  • 字串名稱:可以通過字串名稱傳遞常見的度量。

  • 可呼叫對象:可以通過自訂度量可呼叫對象(例如,函數)傳遞更複雜的度量。

某些工具也接受多個度量評估。有關詳細資訊,請參閱使用多個度量評估

3.4.3.1. 字串名稱評分器#

對於最常見的使用案例,您可以使用字串名稱透過 scoring 參數指定評分器物件;下表顯示所有可能的值。所有評分器物件都遵循一個慣例,即較高的返回值優於較低的返回值。因此,衡量模型與資料之間距離的度量(如metrics.mean_squared_error)可用作 'neg_mean_squared_error',它返回度量的負值。

評分字串名稱

函數

註解

分類

‘accuracy’

metrics.accuracy_score

‘balanced_accuracy’

metrics.balanced_accuracy_score

‘top_k_accuracy’

metrics.top_k_accuracy_score

‘average_precision’

metrics.average_precision_score

‘neg_brier_score’

metrics.brier_score_loss

‘f1’

metrics.f1_score

用於二元目標

‘f1_micro’

metrics.f1_score

微平均

‘f1_macro’

metrics.f1_score

巨平均

‘f1_weighted’

metrics.f1_score

加權平均

‘f1_samples’

metrics.f1_score

按多標籤樣本

‘neg_log_loss’

metrics.log_loss

需要 predict_proba 支援

‘precision’ 等。

metrics.precision_score

後綴與 'f1' 相同

‘recall’ 等。

metrics.recall_score

後綴與 'f1' 相同

‘jaccard’ 等。

metrics.jaccard_score

後綴與 'f1' 相同

‘roc_auc’

metrics.roc_auc_score

‘roc_auc_ovr’

metrics.roc_auc_score

‘roc_auc_ovo’

metrics.roc_auc_score

‘roc_auc_ovr_weighted’

metrics.roc_auc_score

‘roc_auc_ovo_weighted’

metrics.roc_auc_score

‘d2_log_loss_score’

metrics.d2_log_loss_score

分群

‘adjusted_mutual_info_score’

metrics.adjusted_mutual_info_score

‘adjusted_rand_score’

metrics.adjusted_rand_score

‘completeness_score’

metrics.completeness_score

‘fowlkes_mallows_score’

metrics.fowlkes_mallows_score

‘homogeneity_score’

metrics.homogeneity_score

‘mutual_info_score’

metrics.mutual_info_score

‘normalized_mutual_info_score’

metrics.normalized_mutual_info_score

‘rand_score’

metrics.rand_score

‘v_measure_score’

metrics.v_measure_score

迴歸

‘explained_variance’

metrics.explained_variance_score

‘neg_max_error’

metrics.max_error

‘neg_mean_absolute_error’

metrics.mean_absolute_error

‘neg_mean_squared_error’

metrics.mean_squared_error

‘neg_root_mean_squared_error’

metrics.root_mean_squared_error

‘neg_mean_squared_log_error’

metrics.mean_squared_log_error

‘neg_root_mean_squared_log_error’

metrics.root_mean_squared_log_error

‘neg_median_absolute_error’

metrics.median_absolute_error

‘r2’

metrics.r2_score

‘neg_mean_poisson_deviance’

metrics.mean_poisson_deviance

‘neg_mean_gamma_deviance’

metrics.mean_gamma_deviance

‘neg_mean_absolute_percentage_error’

metrics.mean_absolute_percentage_error

‘d2_absolute_error_score’

metrics.d2_absolute_error_score

使用範例

>>> from sklearn import svm, datasets
>>> from sklearn.model_selection import cross_val_score
>>> X, y = datasets.load_iris(return_X_y=True)
>>> clf = svm.SVC(random_state=0)
>>> cross_val_score(clf, X, y, cv=5, scoring='recall_macro')
array([0.96..., 0.96..., 0.96..., 0.93..., 1.        ])

注意

如果傳遞了錯誤的評分名稱,則會引發 InvalidParameterError。您可以通過呼叫get_scorer_names 來檢索所有可用評分器的名稱。

3.4.3.2. 可呼叫的評分器#

對於更複雜的使用案例和更高的靈活性,您可以將可呼叫對象傳遞給 scoring 參數。這可以通過以下方式完成

3.4.3.2.1. 通過 make_scorer 改編預定義的度量#

以下度量函數未實作為命名評分器,有時是因為它們需要額外的參數,例如fbeta_score。它們不能傳遞給 scoring 參數;相反,它們的可呼叫對象需要與使用者可設定參數的值一起傳遞給make_scorer

函數

參數

使用範例

分類

metrics.fbeta_score

beta

make_scorer(fbeta_score, beta=2)

迴歸

metrics.mean_tweedie_deviance

power

make_scorer(mean_tweedie_deviance, power=1.5)

metrics.mean_pinball_loss

alpha

make_scorer(mean_pinball_loss, alpha=0.95)

metrics.d2_tweedie_score

power

make_scorer(d2_tweedie_score, power=1.5)

metrics.d2_pinball_score

alpha

make_scorer(d2_pinball_score, alpha=0.95)

一個典型的使用案例是使用其參數的非預設值包裝來自庫的現有度量函數,例如fbeta_score函數的 beta 參數

>>> from sklearn.metrics import fbeta_score, make_scorer
>>> ftwo_scorer = 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_scorer, cv=5)

sklearn.metrics 模組還公開了一組簡單的函數,用於測量給定真實值和預測值的預測誤差

  • _score 結尾的函數返回要最大化的值,越高越好。

  • _error_loss_deviance 結尾的函數返回要最小化的值,越低越好。在使用 make_scorer 轉換為評分器物件時,請將 greater_is_better 參數設定為 False(預設為 True;請參閱下面的參數說明)。

3.4.3.2.2. 建立自訂評分器物件#

您可以使用 make_scorer 建立您自己的自訂評分器物件,或者為了獲得最大的彈性,從頭開始建立。請參閱以下詳細資訊。

使用 make_scorer 的自訂評分器物件#

您可以使用 make_scorer 從一個簡單的 Python 函式建立完全自訂的評分器物件,該函式可以接收多個參數

  • 您想要使用的 Python 函式(在下面的範例中為 my_custom_loss_func

  • Python 函式是否返回一個分數(greater_is_better=True,預設值)或一個損失(greater_is_better=False)。如果是損失,評分器物件會將 Python 函式的輸出取反,符合交叉驗證的慣例,即評分器會為較好的模型返回較高的值。

  • 僅適用於分類指標:您提供的 Python 函式是否需要連續的決策確定性。如果評分函式僅接受機率估計(例如 metrics.log_loss),則需要設定參數 response_method="predict_proba"。有些評分函式不一定需要機率估計,而是需要非閾值的決策值(例如 metrics.roc_auc_score)。在這種情況下,可以提供一個列表(例如 response_method=["decision_function", "predict_proba"]),評分器將使用列表中給定的順序中第一個可用的方法來計算分數。

  • 評分函式的任何其他參數,例如 betalabels

以下是一個建立自訂評分器以及使用 greater_is_better 參數的範例

>>> import numpy as np
>>> def my_custom_loss_func(y_true, y_pred):
...     diff = np.abs(y_true - y_pred).max()
...     return np.log1p(diff)
...
>>> # score will negate the return value of my_custom_loss_func,
>>> # which will be np.log(2), 0.693, given the values for X
>>> # and y defined below.
>>> score = make_scorer(my_custom_loss_func, greater_is_better=False)
>>> X = [[1], [1]]
>>> y = [0, 1]
>>> from sklearn.dummy import DummyClassifier
>>> clf = DummyClassifier(strategy='most_frequent', random_state=0)
>>> clf = clf.fit(X, y)
>>> my_custom_loss_func(y, clf.predict(X))
0.69...
>>> score(clf, X, y)
-0.69...
從頭開始建立自訂評分器物件#

您可以通過從頭開始建構自己的評分物件,而無需使用 make_scorer 工廠,來產生更具彈性的模型評分器。

為了使可調用物件成為評分器,它需要符合以下兩個規則所指定的協定

  • 它可以被調用並帶有參數 (estimator, X, y),其中 estimator 是應該被評估的模型,X 是驗證資料,而 yX 的真實目標(在監督案例中)或 None (在非監督案例中)。

  • 它返回一個浮點數,該浮點數量化了 estimatorX 上的預測品質,並參考 y。同樣,按照慣例,較高的數字較好,因此如果您的評分器返回損失,則該值應取反。

  • 進階:如果它需要傳遞額外的元數據,則它應該公開一個返回所請求元數據的 get_metadata_routing 方法。使用者應能夠通過 set_score_request 方法設定所請求的元數據。請參閱 使用者指南開發人員指南 以獲取更多詳細資訊。

在 n_jobs > 1 的函式中使用自訂評分器#

雖然在調用函式旁邊定義自訂評分函式應該可以使用預設的 joblib 後端 (loky),但從另一個模組匯入它將是一個更穩健的方法,並且可以獨立於 joblib 後端工作。

例如,為了在下面的範例中使用大於 1 的 n_jobscustom_scoring_function 函式會儲存在使用者建立的模組 (custom_scorer_module.py) 中並匯入

>>> from custom_scorer_module import custom_scoring_function 
>>> cross_val_score(model,
...  X_train,
...  y_train,
...  scoring=make_scorer(custom_scoring_function, greater_is_better=False),
...  cv=5,
...  n_jobs=-1) 

3.4.3.3. 使用多個指標評估#

Scikit-learn 也允許在 GridSearchCVRandomizedSearchCVcross_validate 中評估多個指標。

有三種方法可以為 scoring 參數指定多個評分指標

  • 作為字串指標的可迭代物件

    >>> scoring = ['accuracy', 'precision']
    
  • 作為一個 dict,將評分器名稱對應到評分函式

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

    請注意,dict 值可以是評分器函式或預定義的指標字串之一。

  • 作為一個返回分數字典的可調用物件

    >>> from sklearn.model_selection import cross_validate
    >>> from sklearn.metrics import confusion_matrix
    >>> # A sample toy binary classification dataset
    >>> X, y = datasets.make_classification(n_classes=2, random_state=0)
    >>> svm = LinearSVC(random_state=0)
    >>> def confusion_matrix_scorer(clf, X, y):
    ...      y_pred = clf.predict(X)
    ...      cm = confusion_matrix(y, y_pred)
    ...      return {'tn': cm[0, 0], 'fp': cm[0, 1],
    ...              'fn': cm[1, 0], 'tp': cm[1, 1]}
    >>> cv_results = cross_validate(svm, X, y, cv=5,
    ...                             scoring=confusion_matrix_scorer)
    >>> # Getting the test set true positive scores
    >>> print(cv_results['test_tp'])
    [10  9  8  7  8]
    >>> # Getting the test set false negative scores
    >>> print(cv_results['test_fn'])
    [0 1 2 3 2]
    

3.4.4. 分類指標#

sklearn.metrics 模組實作了多個損失、分數和實用函式來測量分類效能。某些指標可能需要正類別的機率估計、置信度值或二元決策值。大多數實作都允許每個樣本通過 sample_weight 參數對總體分數做出加權貢獻。

其中一些僅限於二元分類案例

precision_recall_curve(y_true[, y_score, ...])

計算不同機率閾值的精確度-召回率對。

roc_curve(y_true, y_score, *[, pos_label, ...])

計算接收者操作特徵 (ROC)。

class_likelihood_ratios(y_true, y_pred, *[, ...])

計算二元分類正負似然比。

det_curve(y_true, y_score[, pos_label, ...])

計算不同機率閾值的錯誤率。

其他也適用於多類別案例

balanced_accuracy_score(y_true, y_pred, *[, ...])

計算平衡準確度。

cohen_kappa_score(y1, y2, *[, labels, ...])

計算科恩卡帕值:一種測量註解者之間一致性的統計量。

confusion_matrix(y_true, y_pred, *[, ...])

計算混淆矩陣以評估分類的準確性。

hinge_loss(y_true, pred_decision, *[, ...])

平均合頁損失(非正規化)。

matthews_corrcoef(y_true, y_pred, *[, ...])

計算馬修斯相關係數 (MCC)。

roc_auc_score(y_true, y_score, *[, average, ...])

從預測分數計算接收者操作特徵曲線 (ROC AUC) 下的面積。

top_k_accuracy_score(y_true, y_score, *[, ...])

Top-k 準確度分類分數。

有些也適用於多標籤案例

accuracy_score(y_true, y_pred, *[, ...])

準確度分類分數。

classification_report(y_true, y_pred, *[, ...])

建立一個顯示主要分類指標的文字報告。

f1_score(y_true, y_pred, *[, labels, ...])

計算 F1 分數,也稱為平衡 F 分數或 F 量測。

fbeta_score(y_true, y_pred, *, beta[, ...])

計算 F-beta 分數。

hamming_loss(y_true, y_pred, *[, sample_weight])

計算平均漢明損失。

jaccard_score(y_true, y_pred, *[, labels, ...])

計算 Jaccard 相似係數分數。

log_loss(y_true, y_pred, *[, normalize, ...])

計算對數損失,又稱邏輯損失或交叉熵損失。

multilabel_confusion_matrix(y_true, y_pred, *)

計算每個類別或樣本的混淆矩陣。

precision_recall_fscore_support(y_true, ...)

計算每個類別的精確度、召回率、F 量測和支持度。

precision_score(y_true, y_pred, *[, labels, ...])

計算精確度。

recall_score(y_true, y_pred, *[, labels, ...])

計算召回率。

roc_auc_score(y_true, y_score, *[, average, ...])

從預測分數計算接收者操作特徵曲線 (ROC AUC) 下的面積。

zero_one_loss(y_true, y_pred, *[, ...])

計算零一分類損失。

d2_log_loss_score(y_true, y_pred, *[, ...])

計算 \(D^2\) 分數函數,即對數損失的解釋比例。

以及一些二元和多標籤 (但不是多類別) 問題的處理

average_precision_score(y_true, y_score, *)

從預測分數計算平均精確度 (AP)。

在以下小節中,我們將描述每個函數,並先介紹一些關於常見 API 和度量定義的注意事項。

3.4.4.1. 從二元到多類別和多標籤#

某些指標本質上是為二元分類任務定義的(例如 f1_scoreroc_auc_score)。在這些情況下,預設只會評估正向標籤,預設假設正向類別的標籤為 1 (雖然可以透過 pos_label 參數進行配置)。

在將二元指標擴展到多類別或多標籤問題時,資料會被視為一組二元問題,每個類別一個問題。然後有多種方法可以將二元指標計算結果在類別集合中平均,每種方法在某些情況下都可能很有用。在可用的情況下,您應該使用 average 參數在這些方法中進行選擇。

  • "macro" 只是簡單地計算二元指標的平均值,給每個類別相同的權重。在不常見的類別仍然重要的問題中,巨觀平均可能是一種突出其效能的方法。另一方面,所有類別都同樣重要的假設通常是不成立的,因此巨觀平均會過度強調不常見類別的通常較差的效能。

  • "weighted" 通過計算二元指標的平均值來考慮類別不平衡,其中每個類別的分數都由其在真實資料樣本中的存在加權。

  • "micro" 給每個樣本-類別對整體指標相同的貢獻(除了樣本權重造成的結果)。它不是對每個類別的指標求和,而是對構成每個類別指標的被除數和除數求和,以計算整體商。在多標籤設定中,包括要忽略大多數類別的多類別分類中,可能更喜歡微觀平均。

  • "samples" 僅適用於多標籤問題。它不計算每個類別的度量,而是計算評估資料中每個樣本的真實和預測類別的度量,並傳回它們的 (sample_weight 加權) 平均值。

  • 選擇 average=None 將傳回一個包含每個類別分數的陣列。

雖然多類別資料作為類別標籤陣列提供給指標,就像二元目標一樣,但多標籤資料被指定為指示器矩陣,其中單元格 [i, j] 如果樣本 i 具有標籤 j,則值為 1,否則值為 0。

3.4.4.2. 準確度分數#

accuracy_score 函數計算 準確度,即正確預測的分數(預設值)或計數 (normalize=False)。

在多標籤分類中,該函數傳回子集準確度。如果樣本的整個預測標籤集與真實標籤集完全匹配,則子集準確度為 1.0;否則為 0.0。

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,而 \(y_i\) 是相應的真實值,則 \(n_\text{samples}\) 個樣本中正確預測的分數定義為

\[\texttt{accuracy}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} 1(\hat{y}_i = y_i)\]

其中 \(1(x)\)指示函數

>>> import numpy as np
>>> from sklearn.metrics import accuracy_score
>>> y_pred = [0, 2, 1, 3]
>>> y_true = [0, 1, 2, 3]
>>> accuracy_score(y_true, y_pred)
0.5
>>> accuracy_score(y_true, y_pred, normalize=False)
2.0

在具有二元標籤指示器的多標籤情況下

>>> accuracy_score(np.array([[0, 1], [1, 1]]), np.ones((2, 2)))
0.5

範例

3.4.4.3. 前 k 名準確度分數#

top_k_accuracy_score 函數是 accuracy_score 的推廣。不同之處在於,只要真實標籤與 k 個最高的預測分數之一相關聯,預測就被認為是正確的。accuracy_scorek = 1 的特殊情況。

該函數涵蓋二元和多類別分類情況,但不涵蓋多標籤情況。

如果 \(\hat{f}_{i,j}\) 是與第 \(j\) 個最大預測分數對應的第 \(i\) 個樣本的預測類別,而 \(y_i\) 是相應的真實值,則 \(n_\text{samples}\) 個樣本中正確預測的分數定義為

\[\texttt{top-k accuracy}(y, \hat{f}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} \sum_{j=1}^{k} 1(\hat{f}_{i,j} = y_i)\]

其中 \(k\) 是允許的猜測次數,而 \(1(x)\)指示函數

>>> import numpy as np
>>> from sklearn.metrics import top_k_accuracy_score
>>> y_true = np.array([0, 1, 2, 2])
>>> y_score = np.array([[0.5, 0.2, 0.2],
...                     [0.3, 0.4, 0.2],
...                     [0.2, 0.4, 0.3],
...                     [0.7, 0.2, 0.1]])
>>> top_k_accuracy_score(y_true, y_score, k=2)
0.75
>>> # Not normalizing gives the number of "correctly" classified samples
>>> top_k_accuracy_score(y_true, y_score, k=2, normalize=False)
3

3.4.4.4. 平衡準確度分數#

balanced_accuracy_score 函數計算平衡準確度,它可以避免在不平衡資料集上誇大效能估計。它是每個類別的召回率分數的巨觀平均值,或等效地,根據其真實類別的逆盛行率加權每個樣本的原始準確度。因此,對於平衡資料集,分數等於準確度。

在二元情況下,平衡準確度等於 靈敏度 (真正陽性率) 和 特異性 (真正陰性率) 的算術平均值,或具有二元預測而不是分數的 ROC 曲線下的面積

\[\texttt{balanced-accuracy} = \frac{1}{2}\left( \frac{TP}{TP + FN} + \frac{TN}{TN + FP}\right )\]

如果分類器在任一類別上都表現良好,則此項會簡化為傳統準確度 (即正確預測的數量除以預測總數)。

相反地,如果傳統準確度高於機會值只是因為分類器利用了不平衡的測試集,則平衡準確度將會適當地降至 \(\frac{1}{n\_classes}\)

分數範圍從 0 到 1,或者當使用 adjusted=True 時,分數會重新縮放到 \(\frac{1}{1 - n\_classes}\) 到 1 的範圍(包含邊界值),隨機表現的分數為 0。

如果 \(y_i\) 是第 \(i\) 個樣本的真實值,而 \(w_i\) 是對應的樣本權重,則我們會調整樣本權重為:

\[\hat{w}_i = \frac{w_i}{\sum_j{1(y_j = y_i) w_j}}\]

其中 \(1(x)\)指示函數。給定樣本 \(i\) 的預測值 \(\hat{y}_i\),平衡準確度定義為:

\[\texttt{balanced-accuracy}(y, \hat{y}, w) = \frac{1}{\sum{\hat{w}_i}} \sum_i 1(\hat{y}_i = y_i) \hat{w}_i\]

當使用 adjusted=True 時,平衡準確度會報告相較於 \(\texttt{balanced-accuracy}(y, \mathbf{0}, w) = \frac{1}{n\_classes}\) 的相對增長。在二元分類的情況下,這也稱為 尤登 J 統計量(Youden’s J statistic),或稱為知情度(informedness)

注意

此處的多類別定義似乎是二元分類中使用的度量標準最合理的擴展,儘管在文獻中尚未有明確的共識。

  • 我們的定義:[Mosley2013][Kelleher2015][Guyon2015],其中 [Guyon2015] 採用了調整後的版本,以確保隨機預測的分數為 \(0\),而完美預測的分數為 \(1\)

  • 如同 [Mosley2013] 中描述的類別平衡準確度:計算每個類別的精確率和召回率之間的最小值。然後將這些值在類別總數上取平均,以獲得平衡準確度。

  • 如同 [Urbanowicz2015] 中描述的平衡準確度:計算每個類別的靈敏度和特異度的平均值,然後在類別總數上取平均。

參考文獻

[Guyon2015] (1,2)

I. Guyon, K. Bennett, G. Cawley, H.J. Escalante, S. Escalera, T.K. Ho, N. Macià, B. Ray, M. Saeed, A.R. Statnikov, E. Viegas, Design of the 2015 ChaLearn AutoML Challenge, IJCNN 2015.

[Mosley2013] (1,2)

L. Mosley, A balanced approach to the multi-class imbalance problem, IJCV 2010.

3.4.4.5. 柯恩卡帕係數(Cohen’s kappa)#

函數 cohen_kappa_score 計算 柯恩卡帕(Cohen’s kappa)統計量。此度量旨在比較不同人工標註者的標記,而非分類器與真實標籤之間的比較。

卡帕係數的分數介於 -1 和 1 之間。分數高於 0.8 通常被認為是良好的一致性;零或更低的分數表示沒有一致性(實際上是隨機標籤)。

卡帕係數可以針對二元或多類別問題計算,但不適用於多標籤問題(除非手動計算每個標籤的分數)且不適用於兩個以上的標註者。

>>> from sklearn.metrics import cohen_kappa_score
>>> labeling1 = [2, 0, 2, 2, 0, 1]
>>> labeling2 = [0, 0, 2, 2, 0, 2]
>>> cohen_kappa_score(labeling1, labeling2)
0.4285714285714286

3.4.4.6. 混淆矩陣(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]
>>> confusion_matrix(y_true, y_pred)
array([[2, 0, 0],
       [0, 0, 1],
       [1, 0, 2]])

ConfusionMatrixDisplay 可用於視覺化呈現混淆矩陣,如混淆矩陣範例中所示,該範例產生以下圖形:

../_images/sphx_glr_plot_confusion_matrix_001.png

參數 normalize 允許報告比率而不是計數。混淆矩陣可以用 3 種不同的方式進行正規化:'pred''true''all',分別將計數除以每列、每行或整個矩陣的總和。

>>> y_true = [0, 0, 0, 1, 1, 1, 1, 1]
>>> y_pred = [0, 1, 0, 1, 0, 1, 0, 1]
>>> confusion_matrix(y_true, y_pred, normalize='all')
array([[0.25 , 0.125],
       [0.25 , 0.375]])

對於二元分類問題,我們可以按照以下方式取得真陰性、假陽性、假陰性和真陽性的計數:

>>> 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()
>>> tn, fp, fn, tp
(2, 1, 2, 3)

範例

3.4.4.7. 分類報告(Classification report)#

classification_report 函數會建立一個文字報告,顯示主要的分類指標。以下是一個使用自訂 target_names 和推斷標籤的小範例:

>>> from sklearn.metrics import classification_report
>>> y_true = [0, 1, 2, 2, 0]
>>> y_pred = [0, 0, 2, 1, 0]
>>> target_names = ['class 0', 'class 1', 'class 2']
>>> print(classification_report(y_true, y_pred, target_names=target_names))
              precision    recall  f1-score   support

     class 0       0.67      1.00      0.80         2
     class 1       0.00      0.00      0.00         1
     class 2       1.00      0.50      0.67         2

    accuracy                           0.60         5
   macro avg       0.56      0.50      0.49         5
weighted avg       0.67      0.60      0.59         5

範例

3.4.4.8. 漢明損失(Hamming loss)#

hamming_loss 計算兩組樣本之間的平均漢明損失或漢明距離

如果 \(\hat{y}_{i,j}\) 是給定樣本 \(i\) 的第 \(j\) 個標籤的預測值,\(y_{i,j}\) 是對應的真實值,\(n_\text{samples}\) 是樣本數,而 \(n_\text{labels}\) 是標籤數,則漢明損失 \(L_{Hamming}\) 定義為:

\[L_{Hamming}(y, \hat{y}) = \frac{1}{n_\text{samples} * n_\text{labels}} \sum_{i=0}^{n_\text{samples}-1} \sum_{j=0}^{n_\text{labels} - 1} 1(\hat{y}_{i,j} \not= y_{i,j})\]

其中 \(1(x)\)指示函數

上面的方程式在多類別分類的情況下不成立。請參閱下面的註釋以取得更多資訊。

>>> from sklearn.metrics import hamming_loss
>>> y_pred = [1, 2, 3, 4]
>>> y_true = [2, 2, 3, 4]
>>> hamming_loss(y_true, y_pred)
0.25

在具有二元標籤指示器的多標籤情況下

>>> hamming_loss(np.array([[0, 1], [1, 1]]), np.zeros((2, 2)))
0.75

注意

在多類別分類中,漢明損失對應於 y_truey_pred 之間的漢明距離,這與零一損失函數相似。然而,雖然零一損失會懲罰不完全匹配真實集合的預測集合,但漢明損失會懲罰個別標籤。因此,以零一損失為上限的漢明損失始終介於零和一之間(包括邊界值);並且預測真實標籤的適當子集或超集將使漢明損失介於零和一之間(不包含邊界值)。

3.4.4.9. 精確率、召回率和 F 度量(Precision, recall and F-measures)#

直觀地說,精確率是分類器不將負樣本標記為正樣本的能力,而召回率是分類器找出所有正樣本的能力。

\[\text{AP} = \sum_n (R_n - R_{n-1}) P_n\]

average_precision_score(y_true, y_score, *)

從預測分數計算平均精確度 (AP)。

f1_score(y_true, y_pred, *[, labels, ...])

計算 F1 分數,也稱為平衡 F 分數或 F 量測。

fbeta_score(y_true, y_pred, *, beta[, ...])

計算 F-beta 分數。

precision_recall_curve(y_true[, y_score, ...])

計算不同機率閾值的精確度-召回率對。

precision_recall_fscore_support(y_true, ...)

計算每個類別的精確度、召回率、F 量測和支持度。

precision_score(y_true, y_pred, *[, labels, ...])

計算精確度。

recall_score(y_true, y_pred, *[, labels, ...])

計算召回率。

../_images/sphx_glr_plot_precision_recall_001.png

範例

參考文獻

實際類別(觀察)

預測類別(預期)

tp (真陽性) 正確結果

fp (假陽性) 意外結果

fn (假陰性) 遺失結果

tn (真陰性) 正確地沒有結果

\[\text{精確度} = \frac{\text{tp}}{\text{tp} + \text{fp}},\]
\[\text{召回率} = \frac{\text{tp}}{\text{tp} + \text{fn}},\]

(有時召回率也稱為「敏感度」)

\[F_\beta = (1 + \beta^2) \frac{\text{精確度} \times \text{召回率}}{\beta^2 \text{精確度} + \text{召回率}}\]

\[F_\beta = \frac{(1 + \beta^2) \text{tp}}{(1 + \beta^2) \text{tp} + \text{fp} + \beta^2 \text{fn}}\]

>>> from sklearn import metrics
>>> y_pred = [0, 1, 0, 0]
>>> y_true = [0, 1, 0, 1]
>>> metrics.precision_score(y_true, y_pred)
1.0
>>> metrics.recall_score(y_true, y_pred)
0.5
>>> metrics.f1_score(y_true, y_pred)
0.66...
>>> metrics.fbeta_score(y_true, y_pred, beta=0.5)
0.83...
>>> metrics.fbeta_score(y_true, y_pred, beta=1)
0.66...
>>> metrics.fbeta_score(y_true, y_pred, beta=2)
0.55...
>>> metrics.precision_recall_fscore_support(y_true, y_pred, beta=0.5)
(array([0.66..., 1.        ]), array([1. , 0.5]), array([0.71..., 0.83...]), array([2, 2]))


>>> 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.35, 0.8])
>>> precision, recall, threshold = precision_recall_curve(y_true, y_scores)
>>> precision
array([0.5       , 0.66..., 0.5       , 1.        , 1.        ])
>>> recall
array([1. , 1. , 0.5, 0.5, 0. ])
>>> threshold
array([0.1 , 0.35, 0.4 , 0.8 ])
>>> average_precision_score(y_true, y_scores)
0.83...

  • 類似地,\(\hat{y}_s\)\(\hat{y}_l\)\(\hat{y}\) 的子集

  • 對於某些集合 \(A\)\(B\)\(P(A, B) := \frac{\left| A \cap B \right|}{\left|B\right|}\)

  • \(R(A, B) := \frac{\left| A \cap B \right|}{\left|A\right|}\) (關於如何處理 \(A = \emptyset\) 的慣例各不相同;此實作使用 \(R(A, B):=0\),對於 \(P\) 也類似。)

  • \(F_\beta(A, B) := \left(1 + \beta^2\right) \frac{P(A, B) \times R(A, B)}{\beta^2 P(A, B) + R(A, B)}\)

然後,這些指標定義如下

平均

精確度

召回率

F_beta

「微觀」

\(P(y, \hat{y})\)

\(R(y, \hat{y})\)

\(F_\beta(y, \hat{y})\)

「樣本」

\(\frac{1}{\left|S\right|} \sum_{s \in S} P(y_s, \hat{y}_s)\)

\(\frac{1}{\left|S\right|} \sum_{s \in S} R(y_s, \hat{y}_s)\)

\(\frac{1}{\left|S\right|} \sum_{s \in S} F_\beta(y_s, \hat{y}_s)\)

「巨觀」

\(\frac{1}{\left|L\right|} \sum_{l \in L} P(y_l, \hat{y}_l)\)

\(\frac{1}{\left|L\right|} \sum_{l \in L} R(y_l, \hat{y}_l)\)

\(\frac{1}{\left|L\right|} \sum_{l \in L} F_\beta(y_l, \hat{y}_l)\)

「加權」

\(\frac{1}{\sum_{l \in L} \left|y_l\right|} \sum_{l \in L} \left|y_l\right| P(y_l, \hat{y}_l)\)

\(\frac{1}{\sum_{l \in L} \left|y_l\right|} \sum_{l \in L} \left|y_l\right| R(y_l, \hat{y}_l)\)

\(\frac{1}{\sum_{l \in L} \left|y_l\right|} \sum_{l \in L} \left|y_l\right| F_\beta(y_l, \hat{y}_l)\)

\(\langle P(y_l, \hat{y}_l) | l \in L \rangle\)

\(\langle R(y_l, \hat{y}_l) | l \in L \rangle\)

\(\langle F_\beta(y_l, \hat{y}_l) | l \in L \rangle\)

>>> from sklearn import metrics
>>> y_true = [0, 1, 2, 0, 1, 2]
>>> y_pred = [0, 2, 1, 0, 0, 1]
>>> metrics.precision_score(y_true, y_pred, average='macro')
0.22...
>>> metrics.recall_score(y_true, y_pred, average='micro')
0.33...
>>> metrics.f1_score(y_true, y_pred, average='weighted')
0.26...
>>> metrics.fbeta_score(y_true, y_pred, average='macro', beta=0.5)
0.23...
>>> metrics.precision_recall_fscore_support(y_true, y_pred, beta=0.5, average=None)
(array([0.66..., 0.        , 0.        ]), array([1., 0., 0.]), array([0.71..., 0.        , 0.        ]), array([2, 2, 2]...))

對於具有「負類別」的多類別分類,可以排除某些標籤

>>> metrics.recall_score(y_true, y_pred, labels=[1, 2], average='micro')
... # excluding 0, no labels were correctly recalled
0.0

同樣地,在資料樣本中不存在的標籤可以在巨觀平均中被考慮。

>>> metrics.precision_score(y_true, y_pred, labels=[0, 1, 2, 3], average='macro')
0.166...

參考文獻

3.4.4.10. 傑卡德相似係數分數#

jaccard_score 函數計算標籤集合對之間 傑卡德相似係數(也稱為傑卡德指數)的平均值。

具有真實標籤集合 \(y\) 和預測標籤集合 \(\hat{y}\) 的傑卡德相似係數定義為

\[J(y, \hat{y}) = \frac{|y \cap \hat{y}|}{|y \cup \hat{y}|}.\]

jaccard_score (如 precision_recall_fscore_support)本身適用於二元目標。通過逐集合計算,可以使用 average 將其擴展應用於多標籤和多類別問題(請參閱上方)。

在二元情況下

>>> import numpy as np
>>> from sklearn.metrics import jaccard_score
>>> y_true = np.array([[0, 1, 1],
...                    [1, 1, 0]])
>>> y_pred = np.array([[1, 1, 1],
...                    [1, 0, 0]])
>>> jaccard_score(y_true[0], y_pred[0])
0.6666...

在 2D 比較情況下(例如,影像相似度)

>>> jaccard_score(y_true, y_pred, average="micro")
0.6

在具有二元標籤指示器的多標籤情況下

>>> jaccard_score(y_true, y_pred, average='samples')
0.5833...
>>> jaccard_score(y_true, y_pred, average='macro')
0.6666...
>>> jaccard_score(y_true, y_pred, average=None)
array([0.5, 0.5, 1. ])

多類別問題會被二元化,並視為對應的多標籤問題

>>> y_pred = [0, 2, 1, 2]
>>> y_true = [0, 1, 2, 2]
>>> jaccard_score(y_true, y_pred, average=None)
array([1. , 0. , 0.33...])
>>> jaccard_score(y_true, y_pred, average='macro')
0.44...
>>> jaccard_score(y_true, y_pred, average='micro')
0.33...

3.4.4.11. 合頁損失#

hinge_loss 函數使用 合頁損失計算模型和資料之間的平均距離,這是一個單邊指標,僅考慮預測錯誤。(合頁損失用於最大邊界分類器,例如支援向量機。)

如果二元分類任務的真實標籤 \(y_i\) 對每個樣本 \(i\) 編碼為 \(y_i=\left\{-1, +1\right\}\);並且 \(w_i\) 是對應的預測決策(形狀為 (n_samples,) 的陣列,由 decision_function 方法輸出),則合頁損失定義為

\[L_\text{Hinge}(y, w) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} \max\left\{1 - w_i y_i, 0\right\}\]

如果有多個標籤,hinge_loss 使用 Crammer & Singer 的多類別變體。這裡是描述它的論文。

在這種情況下,預測決策是形狀為 (n_samples, n_labels) 的陣列。如果 \(w_{i, y_i}\) 是第 \(i\) 個樣本的真實標籤 \(y_i\) 的預測決策;且 \(\hat{w}_{i, y_i} = \max\left\{w_{i, y_j}~|~y_j \ne y_i \right\}\) 是所有其他標籤的預測決策的最大值,則多類別合頁損失定義為

\[L_\text{Hinge}(y, w) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} \max\left\{1 + \hat{w}_{i, y_i} - w_{i, y_i}, 0\right\}\]

這是一個小的範例,示範如何在二元類別問題中使用具有 svm 分類器的 hinge_loss 函數

>>> from sklearn import svm
>>> from sklearn.metrics import hinge_loss
>>> X = [[0], [1]]
>>> y = [-1, 1]
>>> est = svm.LinearSVC(random_state=0)
>>> est.fit(X, y)
LinearSVC(random_state=0)
>>> pred_decision = est.decision_function([[-2], [3], [0.5]])
>>> pred_decision
array([-2.18...,  2.36...,  0.09...])
>>> hinge_loss([-1, 1, 1], pred_decision)
0.3...

這是一個範例,示範如何在多類別問題中使用具有 svm 分類器的 hinge_loss 函數

>>> X = np.array([[0], [1], [2], [3]])
>>> Y = np.array([0, 1, 2, 3])
>>> labels = np.array([0, 1, 2, 3])
>>> est = svm.LinearSVC()
>>> est.fit(X, Y)
LinearSVC()
>>> pred_decision = est.decision_function([[-1], [2], [3]])
>>> y_true = [0, 2, 3]
>>> hinge_loss(y_true, pred_decision, labels=labels)
0.56...

3.4.4.12. 對數損失#

對數損失,也稱為邏輯迴歸損失或交叉熵損失,定義於機率估計值。它通常用於(多項式)邏輯迴歸和神經網路,以及期望最大化的一些變體中,並且可用於評估分類器的機率輸出 (predict_proba) 而不是其離散預測。

對於真實標籤 \(y \in \{0,1\}\) 和機率估計 \(p = \operatorname{Pr}(y = 1)\) 的二元分類,每個樣本的對數損失是給定真實標籤下分類器的負對數似然

\[L_{\log}(y, p) = -\log \operatorname{Pr}(y|p) = -(y \log (p) + (1 - y) \log (1 - p))\]

這擴展到多類別情況如下。讓一組樣本的真實標籤編碼為 1-of-K 二元指示矩陣 \(Y\),即,如果樣本 \(i\) 具有從 \(K\) 個標籤集合中取出的標籤 \(k\),則 \(y_{i,k} = 1\)。讓 \(P\) 為機率估計值的矩陣,其中 \(p_{i,k} = \operatorname{Pr}(y_{i,k} = 1)\)。然後,整組的對數損失為

\[L_{\log}(Y, P) = -\log \operatorname{Pr}(Y|P) = - \frac{1}{N} \sum_{i=0}^{N-1} \sum_{k=0}^{K-1} y_{i,k} \log p_{i,k}\]

要了解這如何概括上述二元對數損失,請注意,在二元情況下,\(p_{i,0} = 1 - p_{i,1}\)\(y_{i,0} = 1 - y_{i,1}\),因此展開 \(y_{i,k} \in \{0,1\}\) 的內和會得到二元對數損失。

log_loss 函數計算給定真實標籤列表和機率矩陣的對數損失,該矩陣由估計器的 predict_proba 方法傳回。

>>> from sklearn.metrics import log_loss
>>> y_true = [0, 0, 1, 1]
>>> y_pred = [[.9, .1], [.8, .2], [.3, .7], [.01, .99]]
>>> log_loss(y_true, y_pred)
0.1738...

y_pred 中的第一個 [.9, .1] 表示第一個樣本有 90% 的機率具有標籤 0。對數損失為非負值。

3.4.4.13. 馬修斯相關係數#

matthews_corrcoef 函數計算二元類別的 馬修斯相關係數 (MCC)。引用維基百科

「馬修斯相關係數在機器學習中用作衡量二元(雙類別)分類品質的指標。它會考量真陽性、偽陽性和偽陰性,並且通常被認為是一種平衡的衡量標準,即使類別大小差異很大也可以使用。MCC 本質上是介於 -1 和 +1 之間的相關係數值。係數 +1 代表完美的預測,0 代表平均隨機預測,-1 代表反向預測。該統計值也稱為 phi 係數。」

在二元(雙類別)情況下,\(tp\)\(tn\)\(fp\)\(fn\) 分別是真陽性、真陰性、偽陽性和偽陰性的數量,MCC 定義為

\[MCC = \frac{tp \times tn - fp \times fn}{\sqrt{(tp + fp)(tp + fn)(tn + fp)(tn + fn)}}.\]

在多類別情況下,馬修斯相關係數可以根據 \(K\) 個類別的 confusion_matrix \(C\)定義。為了簡化定義,請考慮以下中間變數

  • \(t_k=\sum_{i}^{K} C_{ik}\),類別 \(k\) 真實發生的次數,

  • \(p_k=\sum_{i}^{K} C_{ki}\),類別 \(k\) 被預測的次數,

  • \(c=\sum_{k}^{K} C_{kk}\),正確預測的樣本總數,

  • \(s=\sum_{i}^{K} \sum_{j}^{K} C_{ij}\),樣本總數。

然後,多類別 MCC 定義為

\[MCC = \frac{ c \times s - \sum_{k}^{K} p_k \times t_k }{\sqrt{ (s^2 - \sum_{k}^{K} p_k^2) \times (s^2 - \sum_{k}^{K} t_k^2) }}\]

當標籤多於兩個時,MCC 的值將不再介於 -1 和 +1 之間。相反,最小值將介於 -1 和 0 之間的某個值,具體取決於真實標籤的數量和分佈。最大值始終為 +1。如需其他資訊,請參閱 [WikipediaMCC2021]

這是一個小的範例,說明 matthews_corrcoef 函數的用法

>>> from sklearn.metrics import matthews_corrcoef
>>> y_true = [+1, +1, +1, -1]
>>> y_pred = [+1, -1, +1, +1]
>>> matthews_corrcoef(y_true, y_pred)
-0.33...

參考文獻

[WikipediaMCC2021]

維基百科貢獻者。Phi 係數。維基百科,自由百科全書。2021 年 4 月 21 日,12:21 CEST。可在以下網址取得:https://en.wikipedia.org/wiki/Phi_coefficient 於 2021 年 4 月 21 日存取。

3.4.4.14. 多標籤混淆矩陣#

multilabel_confusion_matrix 函數會計算類別式 (預設) 或樣本式 (samplewise=True) 的多標籤混淆矩陣,以評估分類的準確性。multilabel_confusion_matrix 也會將多類別資料視為多標籤資料,因為這是常被應用於使用二元分類指標(如精確度、召回率等)來評估多類別問題的轉換方式。

當計算類別式多標籤混淆矩陣 \(C\) 時,類別 \(i\) 的真陰性計數為 \(C_{i,0,0}\),假陰性為 \(C_{i,1,0}\),真陽性為 \(C_{i,1,1}\),假陽性為 \(C_{i,0,1}\)

以下範例展示如何使用 multilabel_confusion_matrix 函數,並使用 多標籤指示矩陣 作為輸入。

>>> import numpy as np
>>> from sklearn.metrics import multilabel_confusion_matrix
>>> y_true = np.array([[1, 0, 1],
...                    [0, 1, 0]])
>>> y_pred = np.array([[1, 0, 0],
...                    [0, 1, 1]])
>>> multilabel_confusion_matrix(y_true, y_pred)
array([[[1, 0],
        [0, 1]],

       [[1, 0],
        [0, 1]],

       [[0, 1],
        [1, 0]]])

或者,可以為每個樣本的標籤建構一個混淆矩陣。

>>> multilabel_confusion_matrix(y_true, y_pred, samplewise=True)
array([[[1, 0],
        [1, 1]],

       [[1, 1],
        [0, 1]]])

以下範例展示如何使用 multilabel_confusion_matrix 函數,並使用 多類別 作為輸入。

>>> y_true = ["cat", "ant", "cat", "cat", "ant", "bird"]
>>> y_pred = ["ant", "ant", "cat", "cat", "ant", "cat"]
>>> multilabel_confusion_matrix(y_true, y_pred,
...                             labels=["ant", "bird", "cat"])
array([[[3, 1],
        [0, 2]],

       [[5, 0],
        [1, 0]],

       [[2, 1],
        [1, 2]]])

以下是一些範例,展示如何使用 multilabel_confusion_matrix 函數來計算多標籤指示矩陣輸入問題中每個類別的召回率(或靈敏度)、特異性、偽陽性率和漏失率。

計算每個類別的召回率(也稱為真陽性率或靈敏度)

>>> y_true = np.array([[0, 0, 1],
...                    [0, 1, 0],
...                    [1, 1, 0]])
>>> y_pred = np.array([[0, 1, 0],
...                    [0, 0, 1],
...                    [1, 1, 0]])
>>> mcm = multilabel_confusion_matrix(y_true, y_pred)
>>> tn = mcm[:, 0, 0]
>>> tp = mcm[:, 1, 1]
>>> fn = mcm[:, 1, 0]
>>> fp = mcm[:, 0, 1]
>>> tp / (tp + fn)
array([1. , 0.5, 0. ])

計算每個類別的特異性(也稱為真陰性率)

>>> tn / (tn + fp)
array([1. , 0. , 0.5])

計算每個類別的偽陽性率(也稱為假陽性率)

>>> fp / (fp + tn)
array([0. , 1. , 0.5])

計算每個類別的漏失率(也稱為假陰性率)

>>> fn / (fn + tp)
array([0. , 0.5, 1. ])

3.4.4.15. 接收者操作特徵 (ROC)#

roc_curve 函數計算接收者操作特徵曲線,或 ROC 曲線。引用維基百科的說明:

「接收者操作特徵 (ROC),或簡稱 ROC 曲線,是一個圖形化的繪圖,說明二元分類系統的效能,因為其判別閾值會有所變化。它是藉由繪製真陽性(TPR = 真陽性率)佔所有陽性的比例與假陽性(FPR = 假陽性率)佔所有陰性的比例(在各種閾值設定下)所建立的。TPR 也稱為靈敏度,而 FPR 是 1 減去特異性或真陰性率。」

此函數需要真實的二元值和目標分數,這些分數可以是陽性類別的機率估計、信賴值或二元決策。以下是一個如何使用 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)
>>> fpr
array([0. , 0. , 0.5, 0.5, 1. ])
>>> tpr
array([0. , 0.5, 0.5, 1. , 1. ])
>>> thresholds
array([ inf, 0.8 , 0.4 , 0.35, 0.1 ])

與子集準確性、漢明損失或 F1 分數等指標相比,ROC 不需要為每個標籤優化閾值。

roc_auc_score 函數,以 ROC-AUC 或 AUROC 表示,計算 ROC 曲線下的面積。這樣做可將曲線資訊匯總為一個數字。

下圖顯示了一個分類器的 ROC 曲線和 ROC-AUC 分數,該分類器的目的是將鳶尾花資料集中的維吉尼亞鳶尾花與其餘物種區分開來。

../_images/sphx_glr_plot_roc_001.png

如需更多資訊,請參閱關於 AUC 的維基百科文章

3.4.4.15.1. 二元情況#

二元情況下,您可以使用 classifier.predict_proba() 方法提供機率估計,或使用 classifier.decision_function() 方法給出未經閾值處理的決策值。在提供機率估計的情況下,應提供「較大標籤」類別的機率。「較大標籤」對應於 classifier.classes_[1],因此為 classifier.predict_proba(X)[:, 1]。因此,y_score 參數的大小為 (n_samples,)。

>>> from sklearn.datasets import load_breast_cancer
>>> from sklearn.linear_model import LogisticRegression
>>> from sklearn.metrics import roc_auc_score
>>> X, y = load_breast_cancer(return_X_y=True)
>>> clf = LogisticRegression(solver="liblinear").fit(X, y)
>>> clf.classes_
array([0, 1])

我們可以使用對應於 clf.classes_[1] 的機率估計。

>>> y_score = clf.predict_proba(X)[:, 1]
>>> roc_auc_score(y, y_score)
0.99...

否則,我們可以使用未經閾值處理的決策值。

>>> roc_auc_score(y, clf.decision_function(X))
0.99...

3.4.4.15.2. 多類別情況#

roc_auc_score 函數也可以用於多類別分類。目前支援兩種平均策略:一對一演算法計算成對 ROC AUC 分數的平均值,而一對多演算法計算每個類別相對於所有其他類別的 ROC AUC 分數的平均值。在這兩種情況下,預測的標籤都以從 0 到 n_classes 的值的陣列提供,而分數對應於樣本屬於特定類別的機率估計。OvO 和 OvR 演算法支援均勻加權 (average='macro') 以及依流行度加權 (average='weighted')。

一對一演算法#

計算所有可能的類別成對組合的平均 AUC。[HT2001] 定義了一個均勻加權的多類別 AUC 指標

\[\frac{1}{c(c-1)}\sum_{j=1}^{c}\sum_{k > j}^c (\text{AUC}(j | k) + \text{AUC}(k | j))\]

其中 \(c\) 是類別數,而 \(\text{AUC}(j | k)\) 是以類別 \(j\) 作為陽性類別,以類別 \(k\) 作為陰性類別的 AUC。一般而言,在多類別情況下,\(\text{AUC}(j | k) \neq \text{AUC}(k | j))\)。此演算法透過將關鍵字引數 multiclass 設定為 'ovo' 並將 average 設定為 'macro' 來使用。

[HT2001] 多類別 AUC 指標可以擴展為依流行度加權

\[\frac{1}{c(c-1)}\sum_{j=1}^{c}\sum_{k > j}^c p(j \cup k)( \text{AUC}(j | k) + \text{AUC}(k | j))\]

其中 \(c\) 是類別數。此演算法透過將關鍵字引數 multiclass 設定為 'ovo' 並將 average 設定為 'weighted' 來使用。'weighted' 選項會傳回 [FC2009] 中所述的流行度加權平均值。

一對多演算法#

計算每個類別相對於其餘類別的 AUC [PD2000]。此演算法在功能上與多標籤情況相同。若要啟用此演算法,請將關鍵字引數 multiclass 設定為 'ovr'。此外,除了 'macro' [F2006]'weighted' [F2001] 平均值之外,OvR 還支援 'micro' 平均值。

在無法容忍高偽陽性率的應用中,可以使用 roc_auc_scoremax_fpr 參數,以總結 ROC 曲線至給定限制。

下圖顯示了針對一個分類器的微平均 ROC 曲線及其對應的 ROC-AUC 分數,該分類器的目的是區分鳶尾花資料集中不同的物種。

../_images/sphx_glr_plot_roc_002.png

3.4.4.15.3. 多標籤情況#

多標籤分類中,roc_auc_score 函數會透過在標籤上取平均值的方式來擴展,如上方所述。在此情況下,您應提供形狀為 (n_samples, n_classes)y_score。因此,當使用機率估計時,需要為每個輸出選取具有較大標籤的類別的機率。

>>> from sklearn.datasets import make_multilabel_classification
>>> from sklearn.multioutput import MultiOutputClassifier
>>> X, y = make_multilabel_classification(random_state=0)
>>> inner_clf = LogisticRegression(solver="liblinear", random_state=0)
>>> clf = MultiOutputClassifier(inner_clf).fit(X, y)
>>> y_score = np.transpose([y_pred[:, 1] for y_pred in clf.predict_proba(X)])
>>> roc_auc_score(y, y_score, average=None)
array([0.82..., 0.86..., 0.94..., 0.85... , 0.94...])

而決策值不需要進行此類處理。

>>> from sklearn.linear_model import RidgeClassifierCV
>>> clf = RidgeClassifierCV().fit(X, y)
>>> y_score = clf.decision_function(X)
>>> roc_auc_score(y, y_score, average=None)
array([0.81..., 0.84... , 0.93..., 0.87..., 0.94...])

範例

參考文獻

[HT2001] (1,2)

Hand, D.J. 和 Till, R.J., (2001). 多類別分類問題中 ROC 曲線下面積的簡單推廣。機器學習,45(2),頁 171-186。

[FC2009]

Ferri, Cèsar & Hernandez-Orallo, Jose & Modroiu, R. (2009). 分類效能度量之實驗比較。模式識別快報。30. 27-38。

[PD2000]

Provost, F., Domingos, P. (2000). 訓練良好的 PET:改進機率估計樹 (第 6.2 節),CeDER 工作論文 #IS-00-04,紐約大學斯特恩商學院。

[F2006]

Fawcett, T., 2006. ROC 分析簡介。模式識別快報,27(8),頁 861-874。

[F2001]

Fawcett, T., 2001. 使用規則集最大化 ROC 效能 於 2001 年資料探勘 IEEE 國際會議論文集,頁 131-138。

3.4.4.16. 偵測錯誤權衡 (DET)#

函式 det_curve 計算偵測錯誤權衡曲線 (DET) [WikipediaDET2017]。引述維基百科

「偵測錯誤權衡 (DET) 圖是二元分類系統錯誤率的圖形繪圖,繪製偽拒絕率與偽接受率。x 軸和 y 軸透過其標準常態偏差 (或僅透過對數轉換) 以非線性方式縮放,產生比 ROC 曲線更線性的權衡曲線,並使用大部分影像區域來突顯關鍵操作區域中重要的差異。」

DET 曲線是接收者操作特徵 (ROC) 曲線的變體,其中偽陰性率繪製在 y 軸上,而不是真正陽性率。DET 曲線通常透過 \(\phi^{-1}\) (其中 \(\phi\) 為累積分配函式) 轉換以常態偏差刻度繪製。產生的效能曲線明確地視覺化給定分類演算法的錯誤類型權衡。請參閱 [Martin1997] 以取得範例和進一步的動機。

此圖比較了在相同分類任務上兩個範例分類器的 ROC 和 DET 曲線

../_images/sphx_glr_plot_det_001.png
屬性#
  • 如果偵測分數呈常態分佈 (或接近常態分佈),則 DET 曲線會以常態偏差刻度形成線性曲線。 [Navratil2007] 顯示,反之則不一定成立,甚至更一般的分配也能產生線性 DET 曲線。

  • 常態偏差刻度轉換會分散點,使得佔用相對較大的繪圖空間。因此,在 DET 圖上,分類效能相似的曲線可能更容易區分。

  • 由於偽陰性率與真正陽性率「相反」,因此 DET 曲線的完美點是原點 (與 ROC 曲線的左上角相反)。

應用和限制#

DET 曲線易於閱讀,因此可以快速視覺評估分類器的效能。此外,DET 曲線可用於閾值分析和操作點選擇。如果需要比較錯誤類型,這特別有用。

另一方面,DET 曲線不會將其度量值以單一數字的形式提供。因此,對於自動評估或與其他分類任務的比較,像是 ROC 曲線下導出面積的度量值可能更適合。

範例

參考文獻

[WikipediaDET2017]

維基百科貢獻者。偵測錯誤權衡。維基百科,自由百科全書。2017 年 9 月 4 日,23:33 UTC。可於以下網址取得: https://en.wikipedia.org/w/index.php?title=Detection_error_tradeoff&oldid=798982054。存取於 2018 年 2 月 19 日。

[Martin1997]

A. Martin, G. Doddington, T. Kamm, M. Ordowski 和 M. Przybocki, 偵測任務效能評估中的 DET 曲線,NIST 1997。

3.4.4.17. 零一損失#

zero_one_loss 函式計算 \(n_{\text{samples}}\) 上 0-1 分類損失 (\(L_{0-1}\)) 的總和或平均值。預設情況下,函式會在樣本上正規化。若要取得 \(L_{0-1}\) 的總和,請將 normalize 設定為 False

在多標籤分類中,如果子集的標籤與預測完全相符,zero_one_loss 會將子集評分為一,如果存在任何錯誤,則評分為零。依預設,函式會傳回預測不完美的子集百分比。若要取得此類子集的計數,請將 normalize 設定為 False

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,且 \(y_i\) 是對應的真實值,則 0-1 損失 \(L_{0-1}\) 定義為

\[L_{0-1}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples}-1} 1(\hat{y}_i \not= y_i)\]

其中 \(1(x)\)指示函數。零一損失也可以計算為 \(zero-one loss = 1 - accuracy\)

>>> from sklearn.metrics import zero_one_loss
>>> y_pred = [1, 2, 3, 4]
>>> y_true = [2, 2, 3, 4]
>>> zero_one_loss(y_true, y_pred)
0.25
>>> zero_one_loss(y_true, y_pred, normalize=False)
1.0

在使用二元標籤指示器的多標籤案例中,其中第一個標籤集 [0,1] 存在錯誤

>>> zero_one_loss(np.array([[0, 1], [1, 1]]), np.ones((2, 2)))
0.5

>>> zero_one_loss(np.array([[0, 1], [1, 1]]), np.ones((2, 2)),  normalize=False)
1.0

範例

3.4.4.18. 布萊爾分數損失#

brier_score_loss 函式計算二元類別的 布萊爾分數 [Brier1950]。引述維基百科

「布萊爾分數是測量機率預測準確性的適當分數函式。它適用於必須將機率分配給一組互斥離散結果的任務。」

此函式會傳回實際結果 \(y \in \{0,1\}\) 的均方誤差和預測機率估計 \(p = \operatorname{Pr}(y = 1)\) (由 predict_proba) 輸出

\[BS = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}} - 1}(y_i - p_i)^2\]

布萊爾分數損失也在 0 到 1 之間,且值越低 (均方差越小),表示預測越準確。

以下是此函式的簡單使用範例

>>> import numpy as np
>>> from sklearn.metrics import brier_score_loss
>>> y_true = np.array([0, 1, 1, 0])
>>> y_true_categorical = np.array(["spam", "ham", "ham", "spam"])
>>> y_prob = np.array([0.1, 0.9, 0.8, 0.4])
>>> y_pred = np.array([0, 1, 1, 0])
>>> brier_score_loss(y_true, y_prob)
0.055
>>> brier_score_loss(y_true, 1 - y_prob, pos_label=0)
0.055
>>> brier_score_loss(y_true_categorical, y_prob, pos_label="ham")
0.055
>>> brier_score_loss(y_true, y_prob > 0.5)
0.0

布萊爾分數可用於評估分類器的校準程度。但是,較低的布萊爾分數損失並不總是意味著更好的校準。這是因為,與均方誤差的偏差變異數分解類似,布萊爾分數損失可以分解為校準損失和精化損失的總和 [Bella2012]。校準損失定義為從 ROC 線段斜率導出的經驗機率的均方偏差。精化損失可以定義為最佳成本曲線下面積測量的預期最佳損失。精化損失可以獨立於校準損失變化,因此較低的布萊爾分數損失並不一定意味著更好的校準。「只有當精化損失保持不變時,較低的布萊爾分數損失才始終意味著更好的校準」[Bella2012], [Flach2008]

範例

參考文獻

[Brier1950]

G. Brier, 以機率表示的預測驗證,《每月天氣評論》78.1 (1950)

[Bella2012] (1,2)

Bella, Ferri, Hernández-Orallo 和 Ramírez-Quintana 《機器學習模型的校準》 在 Khosrow-Pour, M. 的「機器學習:概念、方法、工具和應用」。賓夕法尼亞州赫爾希:資訊科學參考文獻 (2012)。

[Flach2008]

Flach, Peter 和 Edson Matsubara。 「關於分類、排序和機率估計。」 達格斯圖爾研討會論文集。Schloss Dagstuhl-Leibniz-Zentrum fr Informatik (2008)。

3.4.4.19. 類別可能性比率#

class_likelihood_ratios 函式計算二元分類的陽性與陰性概似比 \(LR_\pm\),如下所述,其可被解釋為檢測後勝算與檢測前勝算的比率。因此,這個指標對於類別盛行率(正類別的樣本數除以總樣本數)是不變的,並且可以在不同族群之間外推,而無需考慮任何可能的類別不平衡。

因此,\(LR_\pm\) 指標在用於訓練與評估分類器的資料是類別近乎平衡的研究族群(例如病例對照研究),但目標應用(即一般族群)的盛行率非常低的情況下非常有用。

陽性概似比 \(LR_+\) 是分類器正確預測樣本屬於正類別的機率,除以屬於負類別的樣本被預測為正類別的機率

\[LR_+ = \frac{\text{PR}(P+|T+)}{\text{PR}(P+|T-)}.\]

此處的符號表示預測的 (\(P\)) 或真實的 (\(T\)) 標籤,而符號 \(+\)\(-\) 分別表示正類別和負類別,例如 \(P+\) 表示「預測為正」。

類似地,陰性概似比 \(LR_-\) 是正類別樣本被分類為屬於負類別的機率,除以負類別樣本被正確分類的機率

\[LR_- = \frac{\text{PR}(P-|T+)}{\text{PR}(P-|T-)}.\]

對於表現優於隨機的分類器,\(LR_+\) 大於 1,越高越好,而 \(LR_-\) 的範圍從 0 到 1,且越低越好\(LR_\pm\approx 1\) 的值對應於隨機水準。

請注意,機率與計數不同,例如 \(\operatorname{PR}(P+|T+)\) 不等於真正正例計數 tp(實際公式請參閱維基百科頁面)。

範例

跨不同盛行率的解釋#

兩個類別概似比都可以用勝算比(檢測前和檢測後)來解釋

\[\text{檢測後勝算} = \text{概似比} \times \text{檢測前勝算}.\]

一般而言,勝算透過以下方式與機率相關

\[\text{勝算} = \frac{\text{機率}}{1 - \text{機率}},\]

或等效地

\[\text{機率} = \frac{\text{勝算}}{1 + \text{勝算}}.\]

在給定族群中,檢測前機率由盛行率給出。透過將勝算轉換為機率,概似比可以轉換為分類器預測前後,真正屬於任一類別的機率

\[\text{檢測後勝算} = \text{概似比} \times \frac{\text{檢測前機率}}{1 - \text{檢測前機率}},\]
\[\text{檢測後機率} = \frac{\text{檢測後勝算}}{1 + \text{檢測後勝算}}.\]
數學上的發散#

\(fp = 0\) 時,陽性概似比是未定義的,這可以解釋為分類器完美識別正例的情況。如果 \(fp = 0\) 並且 \(tp = 0\),則會導致零除以零的情況。舉例來說,當使用始終預測負類別的 DummyClassifier 時就會發生這種情況,因此完美分類器的解釋會失效。

\(tn = 0\) 時,陰性概似比是未定義的。這種發散是無效的,因為 \(LR_- > 1\) 表示樣本在被分類為負類別後,屬於正類別的勝算會增加,就好像分類的行為導致了正向條件。這包括始終預測正類別的 DummyClassifier 的情況(即當 \(tn=fn=0\) 時)。

\(tp=fn=0\) 時,兩個類別概似比都是未定義的,這表示測試集中沒有正類別的樣本。在交叉驗證高度不平衡的資料時,也可能發生這種情況。

在所有先前的狀況下,class_likelihood_ratios 函式預設會發出適當的警告訊息,並返回 nan,以避免在對交叉驗證折疊取平均值時造成污染。

如需 class_likelihood_ratios 函式的運作示範,請參閱以下範例。

參考資料#

3.4.4.20. 用於分類的 D² 分數#

D² 分數計算解釋的偏差比例。它是 R² 的一般化,其中平方誤差被廣義化,並由選擇的分類偏差 \(\text{dev}(y, \hat{y})\)(例如,對數損失)取代。D² 是 技能分數 的一種形式。其計算方式為

\[D^2(y, \hat{y}) = 1 - \frac{\text{dev}(y, \hat{y})}{\text{dev}(y, y_{\text{null}})} \,.\]

其中 \(y_{\text{null}}\) 是僅截距模型(例如,對數損失情況下 y_true 的每個類別比例)的最佳預測。

與 R² 類似,最佳分數為 1.0,而且可以是負值(因為模型可能會任意差)。始終預測 \(y_{\text{null}}\),而忽略輸入特徵的常數模型,會得到 0.0 的 D² 分數。

D2 對數損失分數#

d2_log_loss_score 函式實作了 D² 使用對數損失的特殊情況,請參閱對數損失,即

\[\text{dev}(y, \hat{y}) = \text{log_loss}(y, \hat{y}).\]

以下是一些 d2_log_loss_score 函式的使用範例

>>> from sklearn.metrics import d2_log_loss_score
>>> y_true = [1, 1, 2, 3]
>>> y_pred = [
...    [0.5, 0.25, 0.25],
...    [0.5, 0.25, 0.25],
...    [0.5, 0.25, 0.25],
...    [0.5, 0.25, 0.25],
... ]
>>> d2_log_loss_score(y_true, y_pred)
0.0
>>> y_true = [1, 2, 3]
>>> y_pred = [
...     [0.98, 0.01, 0.01],
...     [0.01, 0.98, 0.01],
...     [0.01, 0.01, 0.98],
... ]
>>> d2_log_loss_score(y_true, y_pred)
0.981...
>>> y_true = [1, 2, 3]
>>> y_pred = [
...     [0.1, 0.6, 0.3],
...     [0.1, 0.6, 0.3],
...     [0.4, 0.5, 0.1],
... ]
>>> d2_log_loss_score(y_true, y_pred)
-0.552...

3.4.5. 多標籤排名指標#

在多標籤學習中,每個樣本可以有任意數量的相關聯真實標籤。目標是給予真實標籤高分和較佳的排名。

3.4.5.1. 覆蓋率誤差#

coverage_error 函式計算最終預測中必須包含的標籤平均數量,以便預測所有真實標籤。如果您想知道平均需要預測多少個最高分的標籤,而不會遺漏任何真實標籤,這非常有用。因此,此指標的最佳值是真實標籤的平均數量。

注意

我們的實作分數比 Tsoumakas 等人於 2010 年給出的分數大 1。這使其擴展以處理一個實例具有 0 個真實標籤的退化情況。

正式而言,給定真實標籤的二元指標矩陣 \(y \in \left\{0, 1\right\}^{n_\text{samples} \times n_\text{labels}}\) 以及與每個標籤相關聯的分數 \(\hat{f} \in \mathbb{R}^{n_\text{samples} \times n_\text{labels}}\),覆蓋率定義為

\[coverage(y, \hat{f}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}} - 1} \max_{j:y_{ij} = 1} \text{rank}_{ij}\]

其中 \(\text{rank}_{ij} = \left|\left\{k: \hat{f}_{ik} \geq \hat{f}_{ij} \right\}\right|\)。給定排名的定義,y_scores 中的聯繫會透過給予將分配給所有聯繫值的最大排名來打破。

以下是此函式的簡單使用範例

>>> import numpy as np
>>> from sklearn.metrics import coverage_error
>>> y_true = np.array([[1, 0, 0], [0, 0, 1]])
>>> y_score = np.array([[0.75, 0.5, 1], [1, 0.2, 0.1]])
>>> coverage_error(y_true, y_score)
2.5

3.4.5.2. 標籤排名平均精準率#

label_ranking_average_precision_score 函式實作了標籤排名平均精準率 (LRAP)。此指標與 average_precision_score 函式相關聯,但基於標籤排名的概念,而不是精準率和召回率。

標籤排名平均精準率 (LRAP) 會對樣本求平均值,以回答以下問題:對於每個真實標籤,較高排名的標籤中有多少比例是真實標籤?如果您可以為與每個樣本相關聯的標籤提供更好的排名,則此效能衡量指標將會較高。獲得的分數始終嚴格大於 0,最佳值為 1。如果每個樣本恰好有一個相關標籤,則標籤排名平均精準率等同於平均倒數排名

形式上,給定真實標籤的二元指示矩陣 \(y \in \left\{0, 1\right\}^{n_\text{樣本} \times n_\text{標籤}}\) 和每個標籤的關聯分數 \(\hat{f} \in \mathbb{R}^{n_\text{樣本} \times n_\text{標籤}}\),平均精確度定義為

\[LRAP(y, \hat{f}) = \frac{1}{n_{\text{樣本}}} \sum_{i=0}^{n_{\text{樣本}} - 1} \frac{1}{||y_i||_0} \sum_{j:y_{ij} = 1} \frac{|\mathcal{L}_{ij}|}{\text{rank}_{ij}}\]

其中 \(\mathcal{L}_{ij} = \left\{k: y_{ik} = 1, \hat{f}_{ik} \geq \hat{f}_{ij} \right\}\)\(\text{rank}_{ij} = \left|\left\{k: \hat{f}_{ik} \geq \hat{f}_{ij} \right\}\right|\)\(|\cdot|\) 計算集合的基數(即集合中的元素個數),而 \(||\cdot||_0\)\(\ell_0\) 「範數」(計算向量中非零元素的個數)。

以下是此函式的簡單使用範例

>>> import numpy as np
>>> from sklearn.metrics import label_ranking_average_precision_score
>>> y_true = np.array([[1, 0, 0], [0, 0, 1]])
>>> y_score = np.array([[0.75, 0.5, 1], [1, 0.2, 0.1]])
>>> label_ranking_average_precision_score(y_true, y_score)
0.416...

3.4.5.3. 排名損失#

label_ranking_loss 函數計算排名損失,該損失會將樣本中錯誤排序的標籤對數量取平均,也就是說,真實標籤的分數低於錯誤標籤的分數,並以錯誤標籤和真實標籤的有序配對數量的倒數進行加權。最低可達到的排名損失為零。

形式上,給定真實標籤的二元指示矩陣 \(y \in \left\{0, 1\right\}^{n_\text{樣本} \times n_\text{標籤}}\) 和每個標籤的關聯分數 \(\hat{f} \in \mathbb{R}^{n_\text{樣本} \times n_\text{標籤}}\),排名損失定義為

\[ranking\_loss(y, \hat{f}) = \frac{1}{n_{\text{樣本}}} \sum_{i=0}^{n_{\text{樣本}} - 1} \frac{1}{||y_i||_0(n_\text{標籤} - ||y_i||_0)} \left|\left\{(k, l): \hat{f}_{ik} \leq \hat{f}_{il}, y_{ik} = 1, y_{il} = 0 \right\}\right|\]

其中 \(|\cdot|\) 計算集合的基數(即集合中的元素個數),而 \(||\cdot||_0\)\(\ell_0\) 「範數」(計算向量中非零元素的個數)。

以下是此函式的簡單使用範例

>>> import numpy as np
>>> from sklearn.metrics import label_ranking_loss
>>> y_true = np.array([[1, 0, 0], [0, 0, 1]])
>>> y_score = np.array([[0.75, 0.5, 1], [1, 0.2, 0.1]])
>>> label_ranking_loss(y_true, y_score)
0.75...
>>> # With the following prediction, we have perfect and minimal loss
>>> y_score = np.array([[1.0, 0.1, 0.2], [0.1, 0.2, 0.9]])
>>> label_ranking_loss(y_true, y_score)
0.0
參考文獻#
  • Tsoumakas, G., Katakis, I., & Vlahavas, I. (2010). Mining multi-label data. In Data mining and knowledge discovery handbook (pp. 667-685). Springer US.

3.4.5.4. 正規化折損累積增益#

折損累積增益 (DCG) 和正規化折損累積增益 (NDCG) 是在 dcg_scorendcg_score 中實作的排名指標;它們會將預測順序與真實分數進行比較,例如答案與查詢的相關性。

取自維基百科的折損累積增益頁面

「折損累積增益 (DCG) 是一種衡量排名品質的指標。在資訊檢索中,它通常用於衡量網頁搜尋引擎演算法或相關應用程式的有效性。使用搜尋引擎結果集中文件的分級相關性量表,DCG 會根據文件在結果列表中的位置來衡量文件的實用性或增益。增益會從結果列表的頂部累積到底部,並且每個結果的增益會在較低的排名處折損」

DCG 會依預測順序排列真實目標(例如,查詢答案的相關性),然後將它們乘以對數衰減並加總結果。加總可以在前 \(K\) 個結果後截斷,在這種情況下,我們將其稱為 DCG@K。NDCG 或 NDCG@K 是 DCG 除以完美預測所獲得的 DCG,因此它始終介於 0 和 1 之間。通常,NDCG 優於 DCG。

與排名損失相比,NDCG 可以考慮相關性分數,而不是真實排名。因此,如果真實值僅包含排序,則應優先使用排名損失;如果真實值包含實際的實用性分數(例如,不相關為 0,相關為 1,非常相關為 2),則可以使用 NDCG。

對於一個樣本,給定每個目標的連續真實值向量 \(y \in \mathbb{R}^{M}\),其中 \(M\) 是輸出的數量,以及預測 \(\hat{y}\),這會誘導排名函數 \(f\),則 DCG 分數為

\[\sum_{r=1}^{\min(K, M)}\frac{y_{f(r)}}{\log(1 + r)}\]

而 NDCG 分數是 DCG 分數除以針對 \(y\) 獲得的 DCG 分數。

參考文獻#
  • 維基百科關於折損累積增益的條目

  • Jarvelin, K., & Kekalainen, J. (2002). Cumulated gain-based evaluation of IR techniques. ACM Transactions on Information Systems (TOIS), 20(4), 422-446.

  • Wang, Y., Wang, L., Li, Y., He, D., Chen, W., & Liu, T. Y. (2013, May). A theoretical analysis of NDCG ranking measures. In Proceedings of the 26th Annual Conference on Learning Theory (COLT 2013)

  • McSherry, F., & Najork, M. (2008, March). Computing information retrieval performance measures efficiently in the presence of tied scores. In European conference on information retrieval (pp. 414-421). Springer, Berlin, Heidelberg.

3.4.6. 迴歸指標#

sklearn.metrics 模組實作了數個用於衡量迴歸效能的損失、分數和實用函數。其中一些已增強以處理多輸出案例:mean_squared_errormean_absolute_errorr2_scoreexplained_variance_scoremean_pinball_lossd2_pinball_scored2_absolute_error_score

這些函數具有 multioutput 關鍵字引數,用於指定應如何平均每個個別目標的分數或損失。預設值為 'uniform_average',它指定輸出上的均勻加權平均值。如果傳遞形狀為 (n_outputs,)ndarray,則其條目會被解釋為權重,並傳回相應的加權平均值。如果 multioutput'raw_values',則所有未經修改的個別分數或損失將以形狀為 (n_outputs,) 的陣列形式傳回。

r2_scoreexplained_variance_score 接受 multioutput 參數的額外值 'variance_weighted'。此選項會導致每個個別分數根據相應目標變數的變異數進行加權。此設定會量化整體捕獲的未縮放變異數。如果目標變數的尺度不同,則此分數會更重視解釋較高變異數的變數。

3.4.6.1. R² 分數,判定係數#

r2_score 函數計算 判定係數,通常表示為 \(R^2\)

它代表模型中獨立變數已解釋的變異數 (y) 比例。它透過已解釋的變異數比例,指示擬合的優劣程度,因此也是衡量模型預測未見樣本的可能性好壞程度的指標。

由於變異數是依據資料集而定,\(R^2\) 在不同的資料集之間可能不具有有意義的可比較性。最佳可能分數為 1.0,而且它可能是負值(因為模型可能任意更差)。一個始終預測 y 的期望(平均)值的常數模型(忽略輸入特徵)會獲得 0.0 的 \(R^2\) 分數。

注意:當預測殘差的平均值為零時,\(R^2\) 分數和已解釋變異數分數是相同的。

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,而 \(y_i\) 是對應的真實值,總共有 \(n\) 個樣本,則估計的 \(R^2\) 定義為:

\[R^2(y, \hat{y}) = 1 - \frac{\sum_{i=1}^{n} (y_i - \hat{y}_i)^2}{\sum_{i=1}^{n} (y_i - \bar{y})^2}\]

其中 \(\bar{y} = \frac{1}{n} \sum_{i=1}^{n} y_i\)\(\sum_{i=1}^{n} (y_i - \hat{y}_i)^2 = \sum_{i=1}^{n} \epsilon_i^2\)

請注意,r2_score 計算的是未調整的 \(R^2\),並未修正 y 的樣本變異數偏差。

在真實目標為常數的特殊情況下,\(R^2\) 分數不是有限值:它不是 NaN(完美預測),就是 -Inf(不完美預測)。此類非有限分數可能會妨礙正確執行模型最佳化,例如網格搜尋交叉驗證。因此,r2_score 的預設行為是將它們替換為 1.0(完美預測)或 0.0(不完美預測)。如果 force_finite 設定為 False,則此分數會回退到原始的 \(R^2\) 定義。

以下是 r2_score 函式的使用範例:

>>> from sklearn.metrics import r2_score
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> r2_score(y_true, y_pred)
0.948...
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> r2_score(y_true, y_pred, multioutput='variance_weighted')
0.938...
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> r2_score(y_true, y_pred, multioutput='uniform_average')
0.936...
>>> r2_score(y_true, y_pred, multioutput='raw_values')
array([0.965..., 0.908...])
>>> r2_score(y_true, y_pred, multioutput=[0.3, 0.7])
0.925...
>>> y_true = [-2, -2, -2]
>>> y_pred = [-2, -2, -2]
>>> r2_score(y_true, y_pred)
1.0
>>> r2_score(y_true, y_pred, force_finite=False)
nan
>>> y_true = [-2, -2, -2]
>>> y_pred = [-2, -2, -2 + 1e-8]
>>> r2_score(y_true, y_pred)
0.0
>>> r2_score(y_true, y_pred, force_finite=False)
-inf

範例

3.4.6.2. 平均絕對誤差#

mean_absolute_error 函式計算 平均絕對誤差,這是一種風險指標,對應於絕對誤差損失或 \(l1\)-範數損失的期望值。

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,而 \(y_i\) 是對應的真實值,則在 \(n_{\text{samples}}\) 上估計的平均絕對誤差 (MAE) 定義為:

\[\text{MAE}(y, \hat{y}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}}-1} \left| y_i - \hat{y}_i \right|.\]

以下是 mean_absolute_error 函式的使用範例:

>>> from sklearn.metrics import mean_absolute_error
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> mean_absolute_error(y_true, y_pred)
0.5
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> mean_absolute_error(y_true, y_pred)
0.75
>>> mean_absolute_error(y_true, y_pred, multioutput='raw_values')
array([0.5, 1. ])
>>> mean_absolute_error(y_true, y_pred, multioutput=[0.3, 0.7])
0.85...

3.4.6.3. 均方誤差#

mean_squared_error 函式計算 均方誤差,這是一種風險指標,對應於平方(二次)誤差或損失的期望值。

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,而 \(y_i\) 是對應的真實值,則在 \(n_{\text{samples}}\) 上估計的均方誤差 (MSE) 定義為:

\[\text{MSE}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples} - 1} (y_i - \hat{y}_i)^2.\]

以下是 mean_squared_error 函式的使用範例:

>>> from sklearn.metrics import mean_squared_error
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> mean_squared_error(y_true, y_pred)
0.375
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> mean_squared_error(y_true, y_pred)
0.7083...

範例

  • 請參閱 梯度提升迴歸,以了解均方誤差如何用於評估梯度提升迴歸。

MSE 的平方根,稱為均方根誤差 (RMSE),是另一個常見的指標,它提供與目標變數單位相同的量度。RSME 可透過 root_mean_squared_error 函式取得。

3.4.6.4. 平均平方對數誤差#

mean_squared_log_error 函式計算一個風險指標,對應於平方對數(二次)誤差或損失的期望值。

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,而 \(y_i\) 是對應的真實值,則在 \(n_{\text{samples}}\) 上估計的平均平方對數誤差 (MSLE) 定義為:

\[\text{MSLE}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples} - 1} (\log_e (1 + y_i) - \log_e (1 + \hat{y}_i) )^2.\]

其中 \(\log_e (x)\) 表示 \(x\) 的自然對數。當目標具有指數成長時,例如人口數、商品在幾年內的平均銷售額等,這個指標最適合使用。請注意,此指標對低估的預測估計值的懲罰大於高估的預測估計值。

以下是 mean_squared_log_error 函式的使用範例:

>>> from sklearn.metrics import mean_squared_log_error
>>> y_true = [3, 5, 2.5, 7]
>>> y_pred = [2.5, 5, 4, 8]
>>> mean_squared_log_error(y_true, y_pred)
0.039...
>>> y_true = [[0.5, 1], [1, 2], [7, 6]]
>>> y_pred = [[0.5, 2], [1, 2.5], [8, 8]]
>>> mean_squared_log_error(y_true, y_pred)
0.044...

均方根對數誤差 (RMSLE) 可透過 root_mean_squared_log_error 函式取得。

3.4.6.5. 平均絕對百分比誤差#

mean_absolute_percentage_error (MAPE),也稱為平均絕對百分比偏差 (MAPD),是迴歸問題的評估指標。此指標的目的是對相對誤差敏感。例如,它不會因目標變數的整體縮放而改變。

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,而 \(y_i\) 是對應的真實值,則在 \(n_{\text{samples}}\) 上估計的平均絕對百分比誤差 (MAPE) 定義為:

\[\text{MAPE}(y, \hat{y}) = \frac{1}{n_{\text{samples}}} \sum_{i=0}^{n_{\text{samples}}-1} \frac{{}\left| y_i - \hat{y}_i \right|}{\max(\epsilon, \left| y_i \right|)}\]

其中 \(\epsilon\) 是一個任意小但嚴格正數的數值,以避免當 y 為零時產生未定義的結果。

mean_absolute_percentage_error 函式支援多輸出。

以下是 mean_absolute_percentage_error 函式的使用範例:

>>> from sklearn.metrics import mean_absolute_percentage_error
>>> y_true = [1, 10, 1e6]
>>> y_pred = [0.9, 15, 1.2e6]
>>> mean_absolute_percentage_error(y_true, y_pred)
0.2666...

在上面的範例中,如果我們使用 mean_absolute_error,它會忽略較小的數值,而只會反映最高數值預測的誤差。但 MAPE 可以解決這個問題,因為它是根據實際輸出計算相對百分比誤差。

注意

此處的 MAPE 公式並未表示常見的「百分比」定義:範圍在 [0, 100] 的百分比會除以 100 轉換為範圍在 [0, 1] 的相對值。因此,200% 的誤差對應於 2 的相對誤差。這裡的動機是要讓數值範圍與 scikit-learn 中的其他誤差指標(例如 accuracy_score)更加一致。

若要取得符合維基百科公式的平均絕對百分比誤差,請將此處計算的 mean_absolute_percentage_error 乘以 100。

參考資料#

3.4.6.6. 中位數絕對誤差#

median_absolute_error 特別有趣,因為它對離群值具有穩健性。損失的計算方式是取目標值和預測值之間所有絕對差的中位數。

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,而 \(y_i\) 是對應的真實值,則在 \(n_{\text{samples}}\) 上估計的中位數絕對誤差 (MedAE) 定義為:

\[\text{MedAE}(y, \hat{y}) = \text{median}(\mid y_1 - \hat{y}_1 \mid, \ldots, \mid y_n - \hat{y}_n \mid).\]

median_absolute_error 不支援多輸出。

以下是 median_absolute_error 函式的使用範例:

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

3.4.6.7. 最大誤差#

max_error 函式計算最大殘差誤差,這是一種捕捉預測值和真實值之間最糟情況誤差的指標。在完美擬合的單輸出迴歸模型中,max_error 在訓練集上會是 0,雖然這在現實世界中不太可能,但這個指標顯示了模型在擬合時所產生的誤差程度。

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,而 \(y_i\) 是對應的真實值,則最大誤差定義為

\[\text{最大誤差}(y, \hat{y}) = \max(| y_i - \hat{y}_i |)\]

以下是 max_error 函數的使用範例

>>> from sklearn.metrics import max_error
>>> y_true = [3, 2, 7, 1]
>>> y_pred = [9, 2, 7, 1]
>>> max_error(y_true, y_pred)
6

max_error 不支援多輸出。

3.4.6.8. 解釋變異數分數#

explained_variance_score 計算解釋變異數回歸分數

如果 \(\hat{y}\) 是估計的目標輸出,\(y\) 是對應的(正確)目標輸出,而 \(Var\)變異數,即標準差的平方,則解釋變異數估計如下

\[解釋變異數(y, \hat{y}) = 1 - \frac{Var\{ y - \hat{y}\}}{Var\{y\}}\]

最佳分數為 1.0,數值越低表示越差。

在真實目標為常數的特殊情況下,解釋變異數分數不是有限值:它不是 NaN(完美預測)就是 -Inf(不完美預測)。這種非有限分數可能會阻礙正確的模型優化,例如網格搜尋交叉驗證的正確執行。因此,explained_variance_score 的預設行為是將它們替換為 1.0(完美預測)或 0.0(不完美預測)。您可以將 force_finite 參數設定為 False,以防止此修正發生並回退到原始的解釋變異數分數。

以下是 explained_variance_score 函數的使用範例

>>> from sklearn.metrics import explained_variance_score
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> explained_variance_score(y_true, y_pred)
0.957...
>>> y_true = [[0.5, 1], [-1, 1], [7, -6]]
>>> y_pred = [[0, 2], [-1, 2], [8, -5]]
>>> explained_variance_score(y_true, y_pred, multioutput='raw_values')
array([0.967..., 1.        ])
>>> explained_variance_score(y_true, y_pred, multioutput=[0.3, 0.7])
0.990...
>>> y_true = [-2, -2, -2]
>>> y_pred = [-2, -2, -2]
>>> explained_variance_score(y_true, y_pred)
1.0
>>> explained_variance_score(y_true, y_pred, force_finite=False)
nan
>>> y_true = [-2, -2, -2]
>>> y_pred = [-2, -2, -2 + 1e-8]
>>> explained_variance_score(y_true, y_pred)
0.0
>>> explained_variance_score(y_true, y_pred, force_finite=False)
-inf

3.4.6.9. 平均 Poisson、Gamma 和 Tweedie 偏差#

mean_tweedie_deviance 函數計算具有 power 參數 (\(p\)) 的平均 Tweedie 偏差誤差。這是一種引出回歸目標預期值的指標。

存在以下特殊情況:

如果 \(\hat{y}_i\) 是第 \(i\) 個樣本的預測值,而 \(y_i\) 是對應的真實值,則對於 power \(p\),在 \(n_{\text{樣本}}\) 上估計的平均 Tweedie 偏差誤差 (D) 定義為

\[\begin{split}\text{D}(y, \hat{y}) = \frac{1}{n_\text{samples}} \sum_{i=0}^{n_\text{samples} - 1} \begin{cases} (y_i-\hat{y}_i)^2, & \text{當 }p=0\text{(常態)}\\ 2(y_i \log(y_i/\hat{y}_i) + \hat{y}_i - y_i), & \text{當 }p=1\text{(Poisson)}\\ 2(\log(\hat{y}_i/y_i) + y_i/\hat{y}_i - 1), & \text{當 }p=2\text{(Gamma)}\\ 2\left(\frac{\max(y_i,0)^{2-p}}{(1-p)(2-p)}- \frac{y_i\,\hat{y}_i^{1-p}}{1-p}+\frac{\hat{y}_i^{2-p}}{2-p}\right), & \text{其他情況} \end{cases}\end{split}\]

Tweedie 偏差是 2-power 次的齊次函數。因此,power=2 的 Gamma 分佈表示同時縮放 y_truey_pred 對偏差沒有影響。對於 power=1 的 Poisson 分佈,偏差會線性縮放,而對於常態分佈 (power=0),則會以二次方縮放。一般而言,power 越高,真實目標和預測目標之間極端偏差的權重就越小。

例如,讓我們比較兩個預測值 1.5 和 150,它們都比對應的真實值大 50%。

均方誤差 (power=0) 對第二點的預測差異非常敏感,

>>> from sklearn.metrics import mean_tweedie_deviance
>>> mean_tweedie_deviance([1.0], [1.5], power=0)
0.25
>>> mean_tweedie_deviance([100.], [150.], power=0)
2500.0

如果我們將 power 增加到 1,

>>> mean_tweedie_deviance([1.0], [1.5], power=1)
0.18...
>>> mean_tweedie_deviance([100.], [150.], power=1)
18.9...

誤差的差異會減少。最後,透過設定 power=2

>>> mean_tweedie_deviance([1.0], [1.5], power=2)
0.14...
>>> mean_tweedie_deviance([100.], [150.], power=2)
0.14...

我們會得到相同的誤差。因此,當 power=2 時,偏差僅對相對誤差敏感。

3.4.6.10. 釘球損失#

mean_pinball_loss 函數用於評估分位數回歸模型的預測效能。

\[\text{釘球}(y, \hat{y}) = \frac{1}{n_{\text{樣本}}} \sum_{i=0}^{n_{\text{樣本}}-1} \alpha \max(y_i - \hat{y}_i, 0) + (1 - \alpha) \max(\hat{y}_i - y_i, 0)\]

當分位數參數 alpha 設定為 0.5 時,釘球損失的值等同於 mean_absolute_error 的一半。

以下是 mean_pinball_loss 函數的使用範例

>>> from sklearn.metrics import mean_pinball_loss
>>> y_true = [1, 2, 3]
>>> mean_pinball_loss(y_true, [0, 2, 3], alpha=0.1)
0.03...
>>> mean_pinball_loss(y_true, [1, 2, 4], alpha=0.1)
0.3...
>>> mean_pinball_loss(y_true, [0, 2, 3], alpha=0.9)
0.3...
>>> mean_pinball_loss(y_true, [1, 2, 4], alpha=0.9)
0.03...
>>> mean_pinball_loss(y_true, y_true, alpha=0.1)
0.0
>>> mean_pinball_loss(y_true, y_true, alpha=0.9)
0.0

可以使用特定的 alpha 選擇來建構評分器物件

>>> from sklearn.metrics import make_scorer
>>> mean_pinball_loss_95p = make_scorer(mean_pinball_loss, alpha=0.95)

此評分器可用於透過交叉驗證來評估分位數回歸器的泛化效能

>>> from sklearn.datasets import make_regression
>>> from sklearn.model_selection import cross_val_score
>>> from sklearn.ensemble import GradientBoostingRegressor
>>>
>>> X, y = make_regression(n_samples=100, random_state=0)
>>> estimator = GradientBoostingRegressor(
...     loss="quantile",
...     alpha=0.95,
...     random_state=0,
... )
>>> cross_val_score(estimator, X, y, cv=5, scoring=mean_pinball_loss_95p)
array([13.6..., 9.7..., 23.3..., 9.5..., 10.4...])

也可以建構評分器物件以進行超參數調整。必須切換損失的符號,以確保較大的值表示較好,如以下連結中的範例所述。

範例

  • 請參閱梯度提升回歸的預測區間,以取得使用釘球損失來評估和調整具有非對稱雜訊和離群值的資料上分位數回歸模型的超參數的範例。

3.4.6.11. D² 分數#

D² 分數計算解釋的偏差分數。它是 R² 的一般化,其中平方誤差被一般化並被選擇的偏差 \(\text{dev}(y, \hat{y})\) 取代(例如,Tweedie、釘球或平均絕對誤差)。D² 是 技能分數 的一種形式。其計算方式為

\[D^2(y, \hat{y}) = 1 - \frac{\text{dev}(y, \hat{y})}{\text{dev}(y, y_{\text{null}})} \,.\]

其中 \(y_{\text{null}}\) 是僅限截距模型的最佳預測(例如,對於 Tweedie 的情況,為 y_true 的平均值;對於絕對誤差,為中位數;對於釘球損失,為 alpha 分位數)。

與 R² 類似,最佳分數為 1.0,而且可以是負值(因為模型可能會任意差)。始終預測 \(y_{\text{null}}\),而忽略輸入特徵的常數模型,會得到 0.0 的 D² 分數。

D² Tweedie 分數#

d2_tweedie_score 函數實作 D² 的特殊情況,其中 \(\text{dev}(y, \hat{y})\) 是 Tweedie 偏差,請參閱平均 Poisson、Gamma 和 Tweedie 偏差。它也稱為 D² Tweedie,並且與 McFadden 的概似比指數有關。

參數 power 定義 Tweedie 的 power,如同 mean_tweedie_deviance 一樣。請注意,對於 power=0d2_tweedie_score 等於 r2_score(對於單一目標)。

可以使用特定的 power 選擇來建構評分器物件:

>>> from sklearn.metrics import d2_tweedie_score, make_scorer
>>> d2_tweedie_score_15 = make_scorer(d2_tweedie_score, power=1.5)
D² 釘球分數#

d2_pinball_score 函數實作了 D² 的特殊情況,其中使用了釘球損失,請參考 釘球損失,即:

\[\text{dev}(y, \hat{y}) = \text{pinball}(y, \hat{y}).\]

參數 alpha 定義了釘球損失的斜率,如同 mean_pinball_loss (釘球損失)。它決定了釘球損失以及 D² 最優的分位數水平 alpha。請注意,當 alpha=0.5 (預設值) 時,d2_pinball_score 等於 d2_absolute_error_score

可以使用以下方式建立具有特定 alpha 選擇的評分器物件:

>>> from sklearn.metrics import d2_pinball_score, make_scorer
>>> d2_pinball_score_08 = make_scorer(d2_pinball_score, alpha=0.8)
D² 絕對誤差分數#

d2_absolute_error_score 函數實作了 平均絕對誤差 的特殊情況:

\[\text{dev}(y, \hat{y}) = \text{MAE}(y, \hat{y}).\]

以下是 d2_absolute_error_score 函數的一些使用範例:

>>> from sklearn.metrics import d2_absolute_error_score
>>> y_true = [3, -0.5, 2, 7]
>>> y_pred = [2.5, 0.0, 2, 8]
>>> d2_absolute_error_score(y_true, y_pred)
0.764...
>>> y_true = [1, 2, 3]
>>> y_pred = [1, 2, 3]
>>> d2_absolute_error_score(y_true, y_pred)
1.0
>>> y_true = [1, 2, 3]
>>> y_pred = [2, 2, 2]
>>> d2_absolute_error_score(y_true, y_pred)
0.0

3.4.6.12. 迴歸模型的視覺評估#

在評估迴歸模型品質的方法中,scikit-learn 提供了 PredictionErrorDisplay 類別。它允許以兩種不同的方式視覺化檢查模型的預測誤差。

../_images/sphx_glr_plot_cv_predict_001.png

左側的圖表顯示了實際值與預測值。對於旨在預測 y 的 (條件) 期望值的無雜訊迴歸任務,一個完美的迴歸模型會在由預測值等於實際值定義的對角線上顯示資料點。離此最佳線越遠,模型的誤差就越大。在具有不可約雜訊的更真實設定中,也就是說,當 y 的所有變異都無法用 X 中的特徵解釋時,最佳模型會導致一團密集的點排列在對角線周圍。

請注意,以上僅在預測值為給定 Xy 的期望值時才成立。這通常是最小化均方誤差目標函數的迴歸模型的情況,或者更一般地說,對於其「冪」參數的任何值,是 平均 Tweedie 離差 的情況。

當繪製預測給定 Xy 的分位數的估計量時,例如 QuantileRegressor 或任何其他最小化 釘球損失 的模型,預計會有部分點位於對角線之上或之下,具體取決於估計的分位數水平。

總而言之,雖然直觀易懂,但此圖表並未真正告訴我們如何獲得更好的模型。

右側的圖表顯示了殘差(即實際值與預測值之間的差值)與預測值。

此圖表可以更容易地視覺化殘差是否遵循 同質性或異質性 分佈。

特別是,如果 y|X 的真實分佈是 Poisson 或 Gamma 分佈,則最佳模型的殘差變異數預計會隨著 E[y|X] 的預測值而增加(Poisson 線性增加,Gamma 二次增加)。

當擬合線性最小平方迴歸模型時(請參閱 LinearRegressionRidge),我們可以利用此圖表來檢查是否滿足某些 模型假設,特別是殘差應該是不相關的,它們的期望值應該為零,並且它們的變異數應該是恆定的(同質性)。

如果不是這種情況,特別是如果殘差圖顯示一些香蕉狀結構,則表示該模型可能指定錯誤,並且非線性特徵工程或切換到非線性迴歸模型可能很有用。

請參閱以下範例,以了解如何使用此顯示進行模型評估。

範例

3.4.7. 群集度量#

sklearn.metrics 模組實作了多個損失、分數和效用函數,以測量群集效能。有關更多資訊,請參閱 群集效能評估 章節,了解實例群集,以及 雙群集評估 章節,了解雙群集。

3.4.8. 虛擬估計器#

在進行監督式學習時,一個簡單的健全性檢查是將自己的估計器與簡單的經驗法則進行比較。DummyClassifier 實作了多種用於分類的簡單策略:

  • stratified 透過遵循訓練集類別分佈來產生隨機預測。

  • most_frequent 始終預測訓練集中最常出現的標籤。

  • prior 始終預測最大化類別先驗的類別(如 most_frequent),而 predict_proba 會傳回類別先驗。

  • uniform 會隨機產生均勻分佈的預測。

  • constant 始終預測使用者提供的常數標籤。

    此方法的主要動機是 F1 分數,當正類別是少數類別時。

請注意,使用所有這些策略,predict 方法會完全忽略輸入資料!

為了說明 DummyClassifier,首先讓我們建立一個不平衡的資料集:

>>> from sklearn.datasets import load_iris
>>> from sklearn.model_selection import train_test_split
>>> X, y = load_iris(return_X_y=True)
>>> y[y != 1] = -1
>>> X_train, X_test, y_train, y_test = train_test_split(X, y, random_state=0)

接下來,讓我們比較 SVCmost_frequent 的準確性:

>>> from sklearn.dummy import DummyClassifier
>>> from sklearn.svm import SVC
>>> clf = SVC(kernel='linear', C=1).fit(X_train, y_train)
>>> clf.score(X_test, y_test)
0.63...
>>> clf = DummyClassifier(strategy='most_frequent', random_state=0)
>>> clf.fit(X_train, y_train)
DummyClassifier(random_state=0, strategy='most_frequent')
>>> clf.score(X_test, y_test)
0.57...

我們看到 SVC 的表現並沒有比虛擬分類器好多少。現在,讓我們變更核心:

>>> clf = SVC(kernel='rbf', C=1).fit(X_train, y_train)
>>> clf.score(X_test, y_test)
0.94...

我們看到準確度已提升至幾乎 100%。如果 CPU 資源足夠,建議使用交叉驗證策略來更準確地估計準確度。更多資訊請參閱交叉驗證:評估估計器效能章節。此外,如果您想針對參數空間進行優化,強烈建議使用適當的方法;詳情請參閱調整估計器的超參數章節。

更廣泛來說,當分類器的準確度太接近隨機時,可能表示某些地方出錯了:特徵沒有幫助、超參數未正確調整、分類器受到類別不平衡的影響等等…

DummyRegressor 也為迴歸實現了四個簡單的經驗法則

  • mean 總是預測訓練目標的平均值。

  • median 總是預測訓練目標的中位數。

  • quantile 總是預測使用者提供的訓練目標分位數。

  • constant 總是預測使用者提供的常數值。

在所有這些策略中,predict 方法完全忽略輸入資料。