演算法金 | 一文徹底理解機器學習 ROC-AUC 指標

算法金「全网同名」發表於2024-06-11

大俠幸會,在下全網同名「演算法金」 0 基礎轉 AI 上岸,多個演算法賽 Top 「日更萬日,讓更多人享受智慧樂趣」

在機器學習和資料科學的江湖中,評估模型的好壞是非常關鍵的一環。而 ROC(Receiver Operating Characteristic)曲線和 AUC(Area Under Curve)正是評估分類模型效能的重要工具。

這個知識點在面試中也很頻繁的出現。儘管理解這些概念本身不難,但許多人在複習時容易混淆,或在面試緊張時忘記,影響回答效果。

本篇文章將會從基礎概念入手,逐步深入到實際操作。我們會詳細解釋 ROC 曲線和 AUC 的定義和意義,透過例項和程式碼示範幫助大俠掌握這些工具的使用方法,最後透過一些實際應用案例和相關概念的對比,力求全面理解並靈活運用 ROC 和 AUC。

1. 基礎概念介紹

1.1 什麼是 ROC 曲線

ROC 曲線,即接收者操作特徵曲線,ROC曲線產生於第二次世界大戰期間,最早用在訊號檢測領域,偵測戰場上的敵軍載具(飛機、船艦)。現在是是用來評價二分類模型效能的常用圖形工具。它透過顯示真陽性率(True Positive Rate,簡稱 TPR)與假陽性率(False Positive Rate,簡稱 FPR)之間的權衡來幫助我們理解模型的分類能力。

1.2 什麼是 AUC

AUC,即曲線下面積(Area Under Curve),是 ROC 曲線下面積的一個數值表示。它提供了一個定量的指標,用來衡量分類模型的整體表現。AUC 值範圍從 0 到 1,值越大表示模型效能越好。

1.3 為何需要 ROC/AUC

在分類任務中,特別是當資料集類別不平衡時,單純依賴準確率(Accuracy)可能會造成誤導。為了更好地理解這一點,讓我們透過一個例子來說明。

例子說明

假設我們有一個武俠元素的資料集,其中 95% 的樣本是普通弟子,5% 的樣本是高手。

讓我們透過程式碼示例來演示這一點(程式碼供復現使用,可直接跳過下滑到解釋部分):

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.metrics import roc_curve, roc_auc_score, accuracy_score, confusion_matrix

# 生成一個極度不平衡的武俠資料集
# 假設特徵表示武功修煉時間、戰鬥勝率等,標籤表示是否為高手
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, weights=[0.95, 0.05], random_state=42)

# 將資料集分為訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 建立一個總是預測普通弟子的模型
class AlwaysNegativeModel:
    def predict(self, X):
        return np.zeros(X.shape[0])

# 訓練和預測
model = AlwaysNegativeModel()
y_pred = model.predict(X_test)

# 計算混淆矩陣和準確率
cm = confusion_matrix(y_test, y_pred)
accuracy = accuracy_score(y_test, y_pred)

# 計算 ROC 曲線和 AUC
# 在這裡我們需要一個機率預測來計算 ROC 曲線和 AUC,為了演示,我們假設模型輸出的是一個常量機率
y_pred_prob = np.zeros(X_test.shape[0])
fpr, tpr, thresholds = roc_curve(y_test, y_pred_prob)
auc = roc_auc_score(y_test, y_pred_prob)

# 視覺化結果
plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1)
plt.title("混淆矩陣")
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.colorbar()
plt.xlabel("預測標籤")
plt.ylabel("真實標籤")
plt.xticks([0, 1], ["普通弟子", "高手"])
plt.yticks([0, 1], ["普通弟子", "高手"])
for i in range(2):
    for j in range(2):
        plt.text(j, i, cm[i, j], ha="center", va="center", color="red")


print(f"準確率: {accuracy:.2f}")
print(f"AUC: {auc:.2f}")

結果分析

如果我們使用一個簡單的分類器,它總是預測所有樣本為普通弟子。

這個模型的準確率為 95%,看起來表現很好,但實際上它根本無法識別高手,是一個毫無用處的分類器。

這個分類器沒有任何實際的分類能力,因為它無法識別出真正的高手。

  • ROC 曲線和 AUC:透過繪製 ROC 曲線並計算 AUC,我們可以看到 AUC 為 0.50,這表明模型沒有任何區分能力。ROC 曲線是一條對角線,顯示模型在隨機猜測。

準確率只告訴我們模型整體預測正確的比例,但在類別不平衡的情況下,這個指標可能會誤導我們。ROC 曲線和 AUC 提供了更全面的視角,展示了模型在不同閾值下的效能,幫助我們更準確地評估模型的分類能力。

更多內容,見免費知識星球

2. 詳細解釋

2.1 TPR(True Positive Rate)和 FPR(False Positive Rate)的定義

要理解 ROC 曲線,首先需要明白 TPR 和 FPR 的概念:

  • TPR(True Positive Rate):也稱為靈敏度(Sensitivity)或召回率(Recall),表示的是在所有真實為正的樣本中,被正確預測為正的比例。其計算公式為:

其中,TP(True Positives)是將正類正確分類為正類的樣本數,FN(False Negatives)是將正類錯誤分類為負類的樣本數。

  • FPR(False Positive Rate):表示的是在所有真實為負的樣本中,被錯誤預測為正的比例。其計算公式為:

其中,FP(False Positives)是將負類錯誤分類為正類的樣本數,TN(True Negatives)是將負類正確分類為負類的樣本數。

2.2 AUC 的數學定義

AUC(Area Under Curve)是 ROC 曲線下的面積,用於評估分類模型的效能。AUC 值的範圍從 0 到 1,值越大表示模型的效能越好。

數學上,AUC 可以透過積分計算:

在離散情況下,AUC 可以透過梯形法則近似計算:

3 繪製 ROC 曲線的步驟

繪製 ROC 曲線的步驟如下:

  1. 選擇閾值:從 0 到 1 的不同閾值。
  2. 計算 TPR 和 FPR:對於每個閾值,計算相應的 TPR 和 FPR。
  3. 繪製曲線:以 FPR 為橫軸,TPR 為縱軸,繪製 ROC 曲線。

選擇閾值:從 0 到 1 的不同閾值

from sklearn.metrics import roc_curve

# 預測測試集機率
y_pred_prob = model.predict_proba(X_test)[:, 1]

# 計算 ROC 曲線
fpr, tpr, thresholds = roc_curve(y_test, y_pred_prob)

# 輸出部分閾值
print("閾值: ", thresholds[:10])  # 僅展示前10個閾值

計算 TPR 和 FPR:對於每個閾值,計算相應的 TPR 和 FPR

# 輸出部分閾值對應的 TPR 和 FPR
for i in range(10):  # 僅展示前10個閾值的對應值
    print(f"閾值: {thresholds[i]:.2f} -> 假陽性率 (FPR): {fpr[i]:.2f}, 真陽性率 (TPR): {tpr[i]:.2f}")

繪製曲線:以 FPR 為橫軸,TPR 為縱軸,繪製 ROC 曲線

import matplotlib.pyplot as plt

# 視覺化 ROC 曲線
plt.figure(figsize=(8, 6))
plt.plot(fpr, tpr, color='blue', lw=2, label='ROC 曲線')
plt.plot([0, 1], [0, 1], color='gray', lw=1, linestyle='--', label='隨機猜測')
plt.xlabel("假陽性率 (FPR)")
plt.ylabel("真陽性率 (TPR)")
plt.title("ROC 曲線")
plt.legend(loc="lower right")

# 在曲線上標出幾個閾值點
threshold_points = [0.2, 0.5, 0.8]
for threshold in threshold_points:
    idx = np.where(thresholds >= threshold)[0][0]
    plt.scatter(fpr[idx], tpr[idx], marker='o', color='red')
    plt.text(fpr[idx], tpr[idx], f"閾值={threshold:.2f}", fontsize=12)

plt.show()

4 AUC 的意義

AUC 值越大,模型的效能越好。具體來說:

  • AUC = 0.5 表示模型沒有分類能力,相當於隨機猜測。
  • 0.5 < AUC < 0.7 表示模型有一定的分類能力,但效果一般。
  • 0.7 ≤ AUC < 0.9 表示模型有較好的分類能力。
  • AUC ≥ 0.9 表示模型有非常好的分類能力。

AUC 的優缺點

優點:

  • 閾值無關:AUC 衡量的是模型在所有可能的分類閾值下的表現,因此不受單一閾值的影響。
  • 綜合效能評估:AUC 綜合了 TPR 和 FPR 的資訊,能夠全面評估模型的效能。

缺點:

  • 可能不適用於極度不平衡的資料:在極度不平衡的資料集上,AUC 可能無法準確反映模型的效能,需要結合其他評估指標使用。
  • 解釋複雜:對於非專業人士來說,AUC 的解釋和理解可能比較困難。

程式碼示例

下面我們透過程式碼示例來計算 AUC 並解釋其意義:

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve, roc_auc_score, accuracy_score, confusion_matrix

# 生成一個不平衡的武俠資料集
# 假設特徵表示武功修煉時間、戰鬥勝率等,標籤表示是否為高手
X, y = make_classification(n_samples=1000, n_features=20, n_classes=2, weights=[0.9, 0.1], random_state=42)

# 將資料集分為訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 訓練一個邏輯迴歸模型
model = LogisticRegression()
model.fit(X_train, y_train)

# 預測測試集
y_pred_prob = model.predict_proba(X_test)[:, 1]

# 計算 ROC 曲線和 AUC
fpr, tpr, thresholds = roc_curve(y_test, y_pred_prob)
auc = roc_auc_score(y_test, y_pred_prob)

# 視覺化結果
plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1)
plt.title("ROC 曲線")
plt.plot(fpr, tpr, color='blue', lw=2, label=f"AUC = {auc:.2f}")
plt.plot([0, 1], [0, 1], color='gray', lw=1, linestyle='--')
plt.xlabel("假陽性率")
plt.ylabel("真陽性率")
plt.legend(loc="lower right")

plt.subplot(1, 2, 2)
plt.title("AUC 值示意")
plt.fill_between(fpr, tpr, color='blue', alpha=0.3)
plt.plot(fpr, tpr, color='blue', lw=2, label=f"AUC = {auc:.2f}")
plt.xlabel("假陽性率")
plt.ylabel("真陽性率")
plt.legend(loc="lower right")

plt.tight_layout()
plt.show()

print(f"AUC: {auc:.2f}")

ROC 曲線圖

  • 橫軸(假陽性率,FPR):表示負類樣本中被錯誤分類為正類的比例。
  • 縱軸(真陽性率,TPR):表示正類樣本中被正確分類為正類的比例。
  • 藍色曲線:展示了模型在不同閾值下的 FPR 和 TPR 之間的關係。
  • 灰色虛線:表示一個隨機猜測模型的表現,其 AUC 值為 0.5。
  • AUC 值:圖中顯示的 AUC 值(在圖例中標註),越接近 1 說明模型的分類效能越好。

AUC 值示意圖

  • 藍色區域:ROC 曲線下的面積,即 AUC 值。這個面積越大,說明模型的分類效能越好。
  • AUC 值標註:同樣在圖例中標註了 AUC 值。

透過這兩個圖,可以直觀地看到模型在不同閾值下的分類效能,以及透過 AUC 值來量化這種效能。

5. 實際應用案例

為了讓大俠更好地理解 ROC 和 AUC 在實際中的應用,我們將展示它們在不同領域中的應用,如醫學診斷和金融風險評估,並透過實際案例進行程式碼實現。

5.1 在不同領域中的應用

醫學診斷

在醫學診斷中,ROC 曲線和 AUC 被廣泛用於評估診斷測試的效能。例如,在篩查癌症時,醫生希望測試能夠正確識別出患病和未患病的患者。ROC 曲線可以幫助醫生選擇最佳的閾值,從而最大化檢測的準確性。

金融風險評估

在金融領域,ROC 和 AUC 被用於評估信用評分模型的效能。例如,銀行希望識別高風險借款人,以降低貸款違約率。ROC 曲線可以幫助銀行選擇適當的閾值,以平衡風險和收益。

5.2 實際案例分析及程式碼實現

我們將使用一個模擬的醫學診斷資料集來演示如何應用 ROC 和 AUC。假設我們有一個資料集,包含患者的各種特徵以及他們是否患有某種疾病。

程式碼示例和結果分析

import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import roc_curve, roc_auc_score, accuracy_score, confusion_matrix

# 載入乳腺癌資料集
data = load_breast_cancer()
X = data.data
y = data.target

# 將資料集分為訓練集和測試集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# 訓練一個邏輯迴歸模型
model = LogisticRegression(max_iter=10000)
model.fit(X_train, y_train)

# 預測測試集
y_pred = model.predict(X_test)
y_pred_prob = model.predict_proba(X_test)[:, 1]

# 計算混淆矩陣和準確率
cm = confusion_matrix(y_test, y_pred)
accuracy = accuracy_score(y_test, y_pred)

# 計算 ROC 曲線和 AUC
fpr, tpr, thresholds = roc_curve(y_test, y_pred_prob)
auc = roc_auc_score(y_test, y_pred_prob)

# 視覺化結果
plt.figure(figsize=(10, 5))

plt.subplot(1, 2, 1)
plt.title("混淆矩陣")
plt.imshow(cm, interpolation='nearest', cmap=plt.cm.Blues)
plt.colorbar()
plt.xlabel("預測標籤")
plt.ylabel("真實標籤")
plt.xticks([0, 1], ["未患病", "患病"])
plt.yticks([0, 1], ["未患病", "患病"])
for i in range(2):
    for j in range(2):
        plt.text(j, i, cm[i, j], ha="center", va="center", color="red")

plt.subplot(1, 2, 2)
plt.title("ROC 曲線")
plt.plot(fpr, tpr, color='blue', lw=2, label=f"AUC = {auc:.2f}")
plt.plot([0, 1], [0, 1], color='gray', lw=1, linestyle='--', label='隨機猜測')
plt.xlabel("假陽性率")
plt.ylabel("真陽性率")
plt.legend(loc="lower right")

plt.tight_layout()
plt.show()

print(f"準確率: {accuracy:.2f}")
print(f"AUC: {auc:.2f}")

結果分析

  • 準確率:模型的準確率(Accuracy)為 0.98,這意味著在所有測試樣本中,有 98% 的樣本被正確分類。
  • AUC 值:AUC 值為 0.998,這意味著模型在區分未患病和患病患者方面表現非常完美。AUC = 0.998 表示模型在所有可能的閾值下都能完全區分正類和負類樣本,這是一種理想狀態。

解釋

  • 準確率為 0.98:在大多數情況下,這是一個很高的準確率,表明模型幾乎所有的預測都是正確的。
  • AUC = 0.998:表示模型在所有可能的閾值下都能完全區分未患病和患病患者,展示了模型極高的區分能力。

6. 相關概念的對照和對比

在這部分內容中,我們將對 ROC/AUC 與其他評估指標進行對照和對比,以便大俠更全面地理解這些指標在模型評估中的作用。

6.1 ROC/AUC 與混淆矩陣

混淆矩陣是一種用來評價分類模型效能的工具,它透過展示真陽性(TP)、假陽性(FP)、真陰性(TN)和假陰性(FN)的數量來評估模型。ROC 曲線和 AUC 則是從不同的閾值下綜合評估模型的效能。

示例程式碼:

from sklearn.metrics import confusion_matrix, accuracy_score

# 預測測試集
y_pred = model.predict(X_test)
y_pred_prob = model.predict_proba(X_test)[:, 1]

# 計算混淆矩陣
cm = confusion_matrix(y_test, y_pred)
accuracy = accuracy_score(y_test, y_pred)

# 輸出混淆矩陣和準確率
print("混淆矩陣:")
print(cm)


6.2 ROC/AUC 與 PR 曲線

PR 曲線(Precision-Recall Curve)是另一種評估二分類模型的方法,特別適用於不平衡資料集。它透過展示查準率(Precision)和召回率(Recall)之間的關係來評估模型效能。

  • 查準率(Precision):表示在所有被預測為正類的樣本中,實際為正類的比例。
  • 召回率(Recall):表示在所有實際為正類的樣本中,被正確預測為正類的比例。

示例程式碼:

from sklearn.metrics import precision_recall_curve

# 計算 PR 曲線
precision, recall, _ = precision_recall_curve(y_test, y_pred_prob)

# 視覺化 PR 曲線
plt.figure()
plt.plot(recall, precision, color='blue', lw=2, label='PR 曲線')
plt.xlabel("召回率")
plt.ylabel("查準率")
plt.title("PR 曲線")
plt.legend(loc="lower left")
plt.show()

6.3 其他評估指標(如 Precision、Recall)與 ROC/AUC 的關係

除了 ROC/AUC 和 PR 曲線,其他常用的評估指標還有:

  • 準確率(Accuracy):表示被正確分類的樣本佔總樣本的比例。
  • 查準率(Precision):表示在所有被預測為正類的樣本中,實際為正類的比例。
  • 召回率(Recall):表示在所有實際為正類的樣本中,被正確預測為正類的比例。
  • F1 分數(F1 Score):查準率和召回率的調和平均數,用於綜合評價模型的精確性和召回率。

示例程式碼:

from sklearn.metrics import precision_score, recall_score, f1_score

# 計算查準率、召回率和 F1 分數
precision = precision_score(y_test, y_pred)
recall = recall_score(y_test, y_pred)
f1 = f1_score(y_test, y_pred)

# 輸出結果
print(f"查準率: {precision:.2f}")
print(f"召回率: {recall:.2f}")
print(f"F1 分數: {f1:.2f}")

7. 誤區和注意事項

在使用 ROC 和 AUC 評估分類模型效能時,大俠需要注意一些常見的誤區和使用注意事項,以便準確地理解和應用這些指標。

7.1 常見誤區

誤區一:高準確率等於高效能

高準確率並不一定意味著模型效能優秀,尤其是在類別不平衡的情況下。正如前文所示,即使一個模型總是預測為大多數類,其準確率也可能很高,但其實際分類能力可能非常差。

誤區二:AUC 值越高越好

雖然 AUC 值高表示模型效能好,但在某些應用場景下,其他指標如查準率(Precision)和召回率(Recall)可能更加重要。例如,在醫療診斷中,召回率(即靈敏度)通常比 AUC 更加關鍵,因為漏診的代價非常高。

誤區三:單一指標評價模型

依賴單一指標評價模型效能是不全面的。最好結合多個指標(如 AUC、準確率、查準率、召回率和 F1 分數)來綜合評估模型的效能。

7.2 使用 ROC/AUC 時的注意事項

注意事項一:資料不平衡問題

在處理類別不平衡的資料集時,AUC 和 ROC 曲線可以提供更全面的評估,但仍需要結合 PR 曲線等其他指標進行綜合分析。

注意事項二:選擇合適的閾值

ROC 曲線展示了模型在不同閾值下的效能表現,需要根據具體應用場景選擇合適的閾值。例如,在金融風險評估中,選擇較低的閾值可能會增加風險,但可以減少漏檢。

注意事項三:模型的校準

確保模型的機率輸出是校準的,即輸出的機率與實際發生的機率一致。模型校準可以透過可靠性圖(Calibration Curve)等方法進行評估和調整。

[ 抱個拳,總個結 ]

經過前面的詳細講解,我們已經全面瞭解了 ROC 曲線和 AUC 的概念、計算方法、程式碼實現以及在不同領域中的應用。下面對文章的核心內容進行簡要回顧:

核心要點回顧

  1. 基礎概念:ROC 曲線是用來評價二分類模型效能的工具,透過顯示真陽性率(TPR)和假陽性率(FPR)之間的權衡來幫助我們理解模型的分類能力。AUC(曲線下面積)是 ROC 曲線下的面積,用於量化模型的整體表現。
  2. 詳細解釋:我們詳細解釋了 TPR 和 FPR 的定義,繪製 ROC 曲線的步驟,並透過例項程式碼演示瞭如何計算和繪製 ROC 曲線以及 AUC。還對 AUC 的數學定義、意義及其優缺點進行了分析。
  3. 程式碼示範:透過使用 Python 和 scikit-learn 庫,我們實現瞭如何計算和繪製 ROC 曲線及 AUC,並透過例項展示了這些指標在實際應用中的效果。
  4. 實際應用案例:我們使用乳腺癌資料集進行模型訓練和評估,展示了 ROC 和 AUC 在醫學診斷中的實際應用,並透過程式碼詳細演示瞭如何計算和解釋這些指標。
  5. 相關概念對照和對比:我們對 ROC/AUC 與混淆矩陣、PR 曲線等其他評估指標進行了對照和對比,幫助全面理解這些指標的作用,並根據具體應用場景選擇合適的評估方法。
  6. 誤區和注意事項:我們討論了在使用 ROC 和 AUC 時常見的誤區和需要注意的事項,提醒大俠避免在模型評估中常見的錯誤,並提供了結合多種評估指標綜合分析模型效能的方法。

關鍵概念回顧

  • ROC 曲線:評估模型在不同閾值下的效能,透過展示 TPR 和 FPR 的關係來幫助理解模型的分類能力。
  • AUC:量化 ROC 曲線下的面積,用於綜合評價模型的整體表現,AUC 值越大表示模型效能越好。
  • 混淆矩陣:展示模型的分類結果,透過四個基本要素(TP、FP、TN、FN)來評估模型效能。
  • PR 曲線:展示查準率和召回率之間的關係,特別適用於類別不平衡的資料集。
  • 校準曲線:評估模型的機率輸出是否與實際機率一致,確保模型的機率預測是準確的。

透過這篇文章的講解,希望大俠們能夠更加全面地理解和應用 ROC 曲線和 AUC,在實際專案中靈活運用這些知識,提升模型評估的準確性和可靠性。

- 科研為國分憂,創新與民造福 -

日更時間緊任務急,難免有疏漏之處,還請大俠海涵 內容僅供學習交流之用,部分素材來自網路,侵聯刪

[ 演算法金,碎碎念 ]

全網同名,日更萬日,讓更多人享受智慧樂趣

如果覺得內容有價值,煩請大俠多多 分享、在看、點贊,助力演算法金又猛又持久、很黃很 BL 的日更下去;

同時邀請大俠 關注、星標 演算法金,圍觀日更萬日,助你功力大增、笑傲江湖

相關文章