其中,??TP為真陽性,??TN為假陰性

假陽性率(FPR, False Positive Rate):?表示被錯誤預測為正類的負樣本占所有負樣本的比例,公式為:

其中,??FP為假陽性,??TN為真陰性

ROC曲線是以FPR為橫坐標,TPR為縱坐標繪制的,曲線上的每個點代表一個特定的閾值下分類器的表現。當模型性能較好時,ROC曲線會靠近左上角,這意味著在高TPR的同時保持低FPR。

2.AUC值

AUC(Area Under the Curve)是ROC曲線下的面積。AUC值介于0到1之間,AUC越接近1,模型的區分能力越強。一般情況下,AUC值可以這樣理解

(1)0.5:模型沒有區分能力,和隨機猜測差不多

(2)0.5-0.7:模型具有較低的區分能力

(3)0.7-0.9:模型具有較好的區分能力

(4)0.9-1.0:模型的區分能力非常強

3.多分類問題中的宏平均ROC曲線

ROC曲線通常用于二分類問題,但在多分類問題中也有相應的擴展方法。常見的策略有兩種:

(1)一對多(One-vs-Rest,OvR):將多分類問題中的每個類別當作正類,其他類別作為負類,分別計算每個類別的ROC曲線,并計算其AUC值。

宏平均ROC曲線:首先為每個類別分別計算ROC曲線,然后對這些曲線的TPR和FPR在每個閾值下進行平均,得到宏觀的ROC曲線。

宏平均AUC:對所有類別的AUC值進行平均,得到一個全局的AUC值,衡量多分類模型的整體性能。

(2)一對一(One-vs-One,OvO):在每兩個類別之間計算二分類的ROC曲線和AUC值,最后通過一定的加權方式計算整體的AUC。

4.擴展到多分類的宏平均ROC曲線

在多分類問題中,ROC曲線的構建比較復雜,主要因為我們需要針對每個類別計算一條ROC曲線并求平均。宏平均ROC的步驟如下:

(1)針對每一個類別,計算它與所有其他類別的ROC曲線,即將該類別視為正類,其他類別視為負類

(2)對于每一類ROC曲線,記錄不同閾值下的TPR和FPR

(3)將所有類別的ROC曲線進行平均,得到宏觀的ROC曲線

總結

ROC曲線作為分類器評估的經典方法,在處理二分類和多分類問題時都具有廣泛的應用。對于二分類問題,ROC曲線能夠直觀地展示模型的分類能力;在多分類問題中,通過宏平均ROC,可以得到一個全局的評價指標。AUC作為ROC曲線的衍生指標,為模型的比較提供了更簡潔有效的方式。

代碼實現

二分類模型下的ROC曲線繪制

數據讀取

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False

df = pd.read_excel("Breast_Cancer.xlsx")
df.head()

“Breast_Cancer.xlsx” 數據集的來源是UCI機器學習庫中的經典數據集之一——乳腺癌威斯康星數據集(Breast Cancer Wisconsin Dataset)。該數據集常用于二分類任務,幫助構建用于乳腺癌診斷的機器學習模型,這里將利用該數據集構建機器學習模型并繪制二分類模型下的ROC曲線

數據分割

from sklearn.model_selection import train_test_split

X = df.drop(['Diagnosis'], axis=1)
y = df['Diagnosis']

# 分割數據集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
random_state=42, stratify=df['Diagnosis'])

使用train_test_split函數按8:2的比例將特征數據X和目標標簽y進行隨機劃分,其中參數test_size=0.2表示20%數據用于測試集,random_state=42保證分割結果可重復,stratify=df[‘Diagnosis’]則確保按照標簽Diagnosis的類別比例進行分層抽樣

構建RF模型用于ROC繪制

from sklearn.ensemble import RandomForestClassifier

# 構建隨機森林模型,并設置多個參數
rf_model = RandomForestClassifier(
n_estimators=100, # 森林中樹的數量,更多的樹通常能提高模型的性能,但計算開銷也會增加
max_depth=10, # 樹的最大深度,防止樹過深導致過擬合。較小的深度可能導致欠擬合
min_samples_split=5, # 每個節點至少需要有5個樣本才能繼續分裂,增大可以防止過擬合
min_samples_leaf=2, # 每個葉子節點至少要有2個樣本,防止葉子節點過小導致模型過擬合
max_features='sqrt', # 每次分裂時考慮的特征數量,'sqrt' 表示使用特征數量的平方根,能提高模型的泛化能力
bootstrap=True, # 是否在構建每棵樹時進行有放回的抽樣,True 是默認設置,可以減少模型的方差
oob_score=True, # 是否使用袋外樣本來評估模型的泛化能力,開啟此項可以進行無偏驗證
random_state=42, # 保證結果可重復,設置隨機數種子
class_weight='balanced' # 類別權重,適用于樣本不均衡的情況,'balanced' 自動調整類別權重
)

# 訓練模型
rf_model.fit(X_train, y_train)

使用RandomForestClassifier構建并訓練隨機森林模型,其中設置了參數如n_estimators=100(樹的數量)、max_depth=10(最大深度)、min_samples_split=5(最小分裂樣本數)、class_weight=’balanced’(平衡類別權重)等,以避免過擬合并應對類別不平衡,模型訓練完成后才能基于其預測概率繪制ROC曲線來評估分類器的性能

ROC繪制

from sklearn.metrics import roc_curve, auc
# 預測概率
y_score = rf_model.predict_proba(X_test)[:, 1]

# 計算ROC曲線
fpr_rf, tpr_rf, _ = roc_curve(y_test, y_score)
roc_auc_rf = auc(fpr_rf, tpr_rf)

# 繪制ROC曲線
plt.figure(dpi=1200)
plt.plot(fpr_rf, tpr_rf, color='darkorange', lw=2, label='ROC curve (area = %0.4f)' % roc_auc_rf)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.legend(loc="lower right")
plt.savefig("Receiver Operating Characteristic_1.pdf", bbox_inches='tight')
plt.show()

通過predict_proba獲取測試集的預測概率后,使用roc_curve計算假陽性率(FPR)和真陽性率(TPR),再通過auc計算ROC曲線下面積(AUC),并繪制ROC曲線圖,其中參數如color=’darkorange’設置曲線顏色,lw=2指定線寬,最后將圖表保存為PDF文件以便后續使用,橙色曲線:表示模型的ROC曲線。曲線越接近左上角,說明模型的性能越好。這個模型的曲線幾乎貼近左上角,說明分類效果非常好,藍色虛線:表示隨機分類器的表現(即隨機猜測的模型),它是一條對角線,AUC值為0.5。相比之下,橙色曲線明顯優于隨機分類,AUC值(Area Under the Curve)= 0.9967:曲線下面積(AUC)為0.9967,接近1,這表示模型在區分正負類上非常強,幾乎可以完美地將正類和負類分開。

同畫布下多個模型ROC繪制

from sklearn.svm import SVC
from sklearn.tree import DecisionTreeClassifier

# 訓練決策樹模型
dt_model = DecisionTreeClassifier()
dt_model.fit(X_train, y_train)
y_score_dt = dt_model.predict_proba(X_test)[:, 1]
fpr_dt, tpr_dt, _ = roc_curve(y_test, y_score_dt)
roc_auc_dt = auc(fpr_dt, tpr_dt)

# 訓練SVM模型
svm_model = SVC(probability=True)
svm_model.fit(X_train, y_train)
y_score_svm = svm_model.predict_proba(X_test)[:, 1]
fpr_svm, tpr_svm, _ = roc_curve(y_test, y_score_svm)
roc_auc_svm = auc(fpr_svm, tpr_svm)

# 繪制ROC曲線
plt.figure(dpi=1200)
plt.plot(fpr_svm, tpr_svm, color='purple', lw=2, label='SVM ROC curve (area = %0.4f)' % roc_auc_svm)
plt.plot(fpr_rf, tpr_rf, color='red', lw=2, label='Random Forest ROC curve (area = %0.4f)' % roc_auc_rf)
plt.plot(fpr_dt, tpr_dt, color='blue', lw=2, label='Decision Tree ROC curve (area = %0.4f)' % roc_auc_dt)
plt.plot([0, 1], [0, 1], color='navy', lw=2, linestyle='--')
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver Operating Characteristic')
plt.savefig("Receiver Operating Characteristic_2.pdf", bbox_inches='tight')
plt.legend(loc="lower right")
plt.show()

同樣的道理再次訓練兩個基礎模型(決策樹、支持向量機(SVM)),分別訓練后計算它們的ROC曲線,并將它們繪制在同一個圖表上以便比較它們的分類性能,該圖展示了三個模型(SVM、隨機森林、決策樹)的ROC曲線,其中隨機森林的AUC值最高(0.9967),表現最佳;SVM的AUC值為0.9808,性能也較好;而決策樹的AUC值為0.9058,相對較低,模型表現稍遜。整體來看,隨機森林在這個分類任務中效果最優。

多分類模型下的宏平均ROC曲線繪制

數據讀取

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.family'] = 'Times New Roman'
plt.rcParams['axes.unicode_minus'] = False

df = pd.read_excel("heart.xlsx")
df.head()

該數據集是來自UCI機器學習庫的經典心臟病數據集(Heart Disease Dataset)。該數據集用于預測是否存在心臟病,并且標簽變量(num 列)包含多個類別,屬于一個多分類任務,接下來將利用這個數據集構建機器學習模型,用其繪制宏平均ROC曲線

數據分割

from sklearn.model_selection import train_test_split

X = df.drop(['num'], axis=1)
y = df['num']

# 分割數據集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2,
random_state=42, stratify=df['num'])

使用train_test_split函數將特征數據X和目標標簽y按8:2的比例劃分為訓練集和測試集,其中test_size=0.2表示20%的數據用于測試,random_state=42確保分割結果可重復,stratify=df[‘num’]根據標簽num的類別比例進行分層抽樣

構建RF模型用于宏平均ROC繪制

from sklearn.ensemble import RandomForestClassifier

# 構建隨機森林模型,并設置多個參數
rf_model = RandomForestClassifier(
n_estimators=100, # 森林中樹的數量,更多的樹通常能提高模型的性能,但計算開銷也會增加
max_depth=10, # 樹的最大深度,防止樹過深導致過擬合。較小的深度可能導致欠擬合
min_samples_split=5, # 每個節點至少需要有5個樣本才能繼續分裂,增大可以防止過擬合
min_samples_leaf=2, # 每個葉子節點至少要有2個樣本,防止葉子節點過小導致模型過擬合
max_features='sqrt', # 每次分裂時考慮的特征數量,'sqrt' 表示使用特征數量的平方根,能提高模型的泛化能力
bootstrap=True, # 是否在構建每棵樹時進行有放回的抽樣,True 是默認設置,可以減少模型的方差
oob_score=True, # 是否使用袋外樣本來評估模型的泛化能力,開啟此項可以進行無偏驗證
random_state=42, # 保證結果可重復,設置隨機數種子
class_weight='balanced' # 類別權重,適用于樣本不均衡的情況,'balanced' 自動調整類別權重
)

# 訓練模型
rf_model.fit(X_train, y_train)

通過設置參數構建隨機森林模型RandomForestClassifier,并使用訓練數據X_train和y_train進行模型訓練,以便后續用于計算宏平均ROC曲線并繪制其性能表現

計算多分類任務的宏平均ROC與AUC

from sklearn import metrics
from sklearn.preprocessing import label_binarize
# 預測并計算概率
ytest_proba_rf = rf_model.predict_proba(X_test)

# 將y標簽轉換成one-hot形式
ytest_one_rf = label_binarize(y_test, classes=[0, 1, 2])

# 宏平均法計算AUC
rf_AUC = {}
rf_FPR = {}
rf_TPR = {}

for i in range(ytest_one_rf.shape[1]):
rf_FPR[i], rf_TPR[i], thresholds = metrics.roc_curve(ytest_one_rf[:, i], ytest_proba_rf[:, i])
rf_AUC[i] = metrics.auc(rf_FPR[i], rf_TPR[i])
print(rf_AUC)

# 合并所有的FPR并排序去重
rf_FPR_final = np.unique(np.concatenate([rf_FPR[i] for i in range(ytest_one_rf.shape[1])]))

# 計算宏平均TPR
rf_TPR_all = np.zeros_like(rf_FPR_final)
for i in range(ytest_one_rf.shape[1]):
rf_TPR_all += np.interp(rf_FPR_final, rf_FPR[i], rf_TPR[i])
rf_TPR_final = rf_TPR_all / ytest_one_rf.shape[1]

# 計算最終的宏平均AUC
rf_AUC_final = metrics.auc(rf_FPR_final, rf_TPR_final)
AUC_final_rf = rf_AUC_final # 最終AUC

print(f"Macro Average AUC with Random Forest: {AUC_final_rf}")

通過將多分類標簽轉換為One-hot編碼形式,計算每個類別的ROC曲線和AUC值,然后合并各類別的假陽性率(FPR)并插值計算出宏平均真陽性率(TPR),最終使用宏平均法計算出隨機森林模型在多分類任務下的整體ROC曲線和宏平均AUC值,以評估模型的綜合分類性能,類別0的AUC值為 0.9372,表示模型在該類別上的分類性能非常好,類別1的AUC值為 0.5982,表示模型在該類別上的分類效果較差,類別2的AUC值為 0.7672,表示模型在該類別上的分類效果較為中等,最終的宏平均AUC為 0.7818,表示在所有類別上,模型整體的分類性能還算不錯,但在類別1上的表現較弱,拉低了整體的平均表現

宏平均ROC繪制

plt.figure(figsize=(10, 10), dpi=1200)
# 使用不同的顏色和線型
plt.plot(rf_FPR[0], rf_TPR[0], color='#1f77b4', linestyle='-', label='Class 0 ROC AUC={:.4f}'.format(rf_AUC[0]), lw=2)
plt.plot(rf_FPR[1], rf_TPR[1], color='#ff7f0e', linestyle='-', label='Class 1 ROC AUC={:.4f}'.format(rf_AUC[1]), lw=2)
plt.plot(rf_FPR[2], rf_TPR[2], color='#2ca02c', linestyle='-', label='Class 2 ROC AUC={:.4f}'.format(rf_AUC[2]), lw=2)
# 宏平均ROC曲線
plt.plot(rf_FPR_final, rf_TPR_final, color='#000000', linestyle='-', label='Macro Average ROC AUC={:.4f}'.format(rf_AUC_final), lw=3)
# 45度參考線
plt.plot([0, 1], [0, 1], color='gray', linestyle='--', lw=2, label='45 Degree Reference Line')
plt.xlabel('False Positive Rate (FPR)', fontsize=15)
plt.ylabel('True Positive Rate (TPR)', fontsize=15)
plt.title('Random Forest Classification ROC Curves and AUC', fontsize=18)
plt.grid(linestyle='--', alpha=0.7)
plt.legend(loc='lower right', framealpha=0.9, fontsize=12)
plt.savefig('RF_optimized.pdf', format='pdf', bbox_inches='tight')
plt.show()

這里繪制隨機森林模型在多分類任務中的ROC曲線,包括每個類別的ROC曲線、宏平均ROC曲線以及隨機猜測的參考線,圖中還顯示了每個類別及宏平均的AUC值,用于評估模型的分類性能,具體解釋前文已給出

文章轉自微信公眾號@Python機器學習AI

上一篇:

K折交叉驗證結合RFE與隨機森林:特征選擇全過程可視化

下一篇:

基于貝葉斯優化的支持向量機(SVM)模型構建

我們有何不同?

API服務商零注冊

多API并行試用

數據驅動選型,提升決策效率

查看全部API→
??

熱門場景實測,選對API

#AI文本生成大模型API

對比大模型API的內容創意新穎性、情感共鳴力、商業轉化潛力

25個渠道
一鍵對比試用API 限時免費

#AI深度推理大模型API

對比大模型API的邏輯推理準確性、分析深度、可視化建議合理性

10個渠道
一鍵對比試用API 限時免費