邏輯迴歸模型在預測二元結果方面應用廣泛,但其評估方法與線性迴歸有所不同。除了常見的係數顯著性檢定外,更需要關注模型的分類別效能。由於邏輯迴歸處理的是機率,因此需要根據不同的閾值判斷分類別結果,並使用混淆矩陣計算精確率、召回率、特異度等指標。ROC 曲線和 AUC 則能更全面地反映模型在不同閾值下的效能表現,有助於找到最佳平衡點。此外,殘差分析在邏輯迴歸中同樣重要,可以幫助識別非線性關係和影響點,進一步提升模型的準確性和可靠性。實際應用中,經常會遇到資料不平衡的情況,此時單純依靠準確率評估模型會有誤導性,需要結合精確率、召回率以及 PR 曲線來綜合考量模型的效能。
邏輯迴歸模型的評估與殘差分析
在進行邏輯迴歸分析時,模型的評估與殘差分析是至關重要的步驟。邏輯迴歸是一種廣義線性模型(GLM),用於預測二元結果的機率。與線性迴歸不同,邏輯迴歸的輸出不是連續值,而是二元分類別結果(例如,0或1,yes或no)。
邏輯迴歸模型的輸出與評估
當我們使用R或Python中的statsmodels套件來擬合邏輯迴歸模型時,我們會得到一系列的輸出結果。例如,在R中:
logistic_model <- glm(outcome ~ payment_inc_ratio + purpose_ + home_ + emp_len_ + borrower_score,
data=loan_data, family='binomial')
summary(logistic_model)
在Python中:
import statsmodels.api as sm
y_numbers = [1 if yi == 'default' else 0 for yi in y]
logit_reg_sm = sm.GLM(y_numbers, X.assign(const=1), family=sm.families.Binomial())
logit_result = logit_reg_sm.fit()
logit_result.summary()
這些輸出的結果包括係數估計、標準誤差、z值、p值等。其中,p值的解釋與線性迴歸中的類別似,用於評估變數的重要性。然而,需要注意的是,邏輯迴歸中沒有像線性迴歸那樣的R平方或RMSE等評估指標。
內容解密:
- 輸出結果的解讀:邏輯迴歸的輸出結果提供了係數估計、標準誤差、z值和p值等資訊,用於評估模型中各變數的重要性。
- 評估指標的差異:由於邏輯迴歸處理的是二元結果,因此不適用線性迴歸中的評估指標,如R平方或RMSE。取而代之的是使用更通用的分類別模型評估指標。
殘差分析
在邏輯迴歸中,殘差分析同樣重要,但其解釋與線性迴歸有所不同。部分殘差(partial residuals)可以用來確認非線性行為和識別具有影響力的記錄。
在R中,可以使用以下程式碼計算部分殘差:
terms <- predict(logistic_gam, type='terms')
partial_resid <- resid(logistic_model) + terms
df <- data.frame(payment_inc_ratio = loan_data[, 'payment_inc_ratio'],
terms = terms[, 's(payment_inc_ratio)'],
partial_resid = partial_resid[, 's(payment_inc_ratio)'])
ggplot(df, aes(x=payment_inc_ratio, y=partial_resid, solid = FALSE)) +
geom_point(shape=46, alpha=0.4) +
geom_line(aes(x=payment_inc_ratio, y=terms),
color='red', alpha=0.5, size=1.5) +
labs(y='Partial Residual')
內容解密:
- 部分殘差的計算:透過將模型的殘差與部分擬合值相加,得到部分殘差,以此來評估變數對結果的影響。
- 圖形化展示:利用ggplot2套件繪製部分殘差圖,以視覺化的方式呈現資料的非線性行為和異常值。
- 結果解釋:部分殘差圖中,點雲的分佈情況可以幫助我們理解模型的擬合程度和資料的特性。
分類別模型的評估
除了殘差分析外,分類別模型的評估還包括了對模型整體效能的評估。這通常透過將模型應用於測試資料集,並計算諸如準確率、精確率、召回率等指標來實作。
重點概念
- 邏輯迴歸是一種用於二元分類別的廣義線性模型。
- 邏輯迴歸的輸出需要經過轉換才能得到機率值。
- 評估邏輯迴歸模型需要使用特定的指標和方法。
- 殘差分析對於理解邏輯迴歸模型的表現至關重要。
進一步閱讀
- Hosmer, D. W., Lemeshow, S., & Sturdivant, R. X. (2013). Applied Logistic Regression (3rd ed.). Wiley.
- Hilbe, J. M. (2017). Logistic Regression Models. Chapman & Hall/CRC Press.
- Hastie, T., Tibshirani, R., & Friedman, J. (2009). The Elements of Statistical Learning (2nd ed.). Springer.
圖表說明
此圖示展示了邏輯迴歸的部分殘差圖,可以看到資料點圍繞著擬合曲線的分佈情況,有助於我們理解模型的擬合優度和資料特性。
評估分類別模型
在機器學習中,評估分類別模型是一個至關重要的步驟。分類別模型的評估指標可以幫助我們瞭解模型的效能和準確度。
分類別模型的評估指標
- 準確率(Accuracy):正確分類別的樣本比例。
- 混淆矩陣(Confusion Matrix):展示預測結果和實際結果的表格,可以用來計算各種評估指標。
- 靈敏度(Sensitivity):正確分類別為正類別的樣本比例,也稱為召回率(Recall)。
- 特異度(Specificity):正確分類別為負類別的樣本比例。
- 精確率(Precision):預測為正類別的樣本中,實際為正類別的比例。
- ROC 曲線:靈敏度與特異度的圖形表示。
- 提升度(Lift):衡量模型在不同機率閾值下識別正類別樣本的能力。
混淆矩陣
混淆矩陣是評估分類別模型效能的核心工具。它是一個二維表格,展示了預測結果和實際結果的對應關係。
計算混淆矩陣
以下是一個使用 R 語言計算混淆矩陣的例子:
pred <- predict(logistic_gam, newdata=train_set)
pred_y <- as.numeric(pred > 0)
true_y <- as.numeric(train_set$outcome=='default')
true_pos <- (true_y==1) & (pred_y==1)
true_neg <- (true_y==0) & (pred_y==0)
false_pos <- (true_y==0) & (pred_y==1)
false_neg <- (true_y==1) & (pred_y==0)
conf_mat <- matrix(c(sum(true_pos), sum(false_pos),
sum(false_neg), sum(true_neg)), 2, 2)
colnames(conf_mat) <- c('Yhat = 1', 'Yhat = 0')
rownames(conf_mat) <- c('Y = 1', 'Y = 0')
conf_mat
內容解密:
predict函式用於對訓練集進行預測,得到預測機率。as.numeric(pred > 0)將預測機率轉換為二元分類別結果(0 或 1)。true_y表示實際的分類別結果。true_pos、true_neg、false_pos和false_neg分別表示真正例、真反例、假正例和假反例。matrix函式用於構建混淆矩陣。colnames和rownames用於設定混淆矩陣的列名和行名。
在 Python 中,可以使用以下程式碼計算混淆矩陣:
pred = logit_reg.predict(X)
pred_y = logit_reg.predict(X) == 'default'
true_y = y == 'default'
true_pos = true_y & pred_y
true_neg = ~true_y & ~pred_y
false_pos = ~true_y & pred_y
false_neg = true_y & ~pred_y
conf_mat = pd.DataFrame([[np.sum(true_pos), np.sum(false_neg)],
[np.sum(false_pos), np.sum(true_neg)]],
index=['Y = default', 'Y = paid off'],
columns=['Yhat = default', 'Yhat = paid off'])
conf_mat
內容解密:
logit_reg.predict(X)對輸入資料X進行預測,得到預測結果。pred_y表示預測結果是否為 ‘default’。true_y表示實際結果是否為 ‘default’。true_pos、true_neg、false_pos和false_neg分別表示真正例、真反例、假正例和假反例。pd.DataFrame用於構建混淆矩陣。
結果解讀
混淆矩陣的對角線元素表示正確的預測結果,而非對角線元素表示錯誤的預測結果。例如,在上述例子中,14295 個違約貸款被正確預測為違約,而 8376 個違約貸款被錯誤預測為已償還。
圖示說明
此圖示展示了二元回應變數的混淆矩陣和各種評估指標之間的關係。
@startuml
skinparam backgroundColor #FEFEFE
skinparam componentStyle rectangle
title 邏輯迴歸模型評估與殘差分析
package "邏輯迴歸模型評估" {
package "評估指標" {
component [準確率/精確率] as accuracy
component [召回率/特異度] as recall
component [ROC 曲線/AUC] as roc
}
package "殘差分析" {
component [部分殘差] as partial
component [非線性檢測] as nonlinear
component [影響點識別] as influence
}
package "不平衡處理" {
component [混淆矩陣] as confusion
component [閾值調整] as threshold
component [PR 曲線] as pr
}
}
collect --> clean : 原始資料
clean --> feature : 乾淨資料
feature --> select : 特徵向量
select --> tune : 基礎模型
tune --> cv : 最佳參數
cv --> eval : 訓練模型
eval --> deploy : 驗證模型
deploy --> monitor : 生產模型
note right of feature
特徵工程包含:
- 特徵選擇
- 特徵轉換
- 降維處理
end note
note right of eval
評估指標:
- 準確率/召回率
- F1 Score
- AUC-ROC
end note
@enduml
此圖示清晰地展示了混淆矩陣中的四種情況:真正例、假正例、真反例和假反例。正確的預測結果位於對角線上,而錯誤的預測結果則位於非對角線上。
評估分類別模型
在許多情況下,需要預測的類別之間存在不平衡,其中一類別遠比另一類別更常見,例如合法的保險理賠與詐欺理賠,或是瀏覽網站的使用者與購買者。罕見類別(例如詐欺理賠)通常是更令人感興趣的類別,並且通常被標記為 1,以區別於更常見的 0。在典型的場景中,1 是更重要的案例,因為將其誤分類別為 0 的成本遠高於將 0 誤分類別為 1。例如,正確識別詐欺保險理賠可能節省數千美元。另一方面,正確識別非詐欺理賠僅僅節省了人工審查該理賠的成本和工作量(這是當理賠被標記為“詐欺”時會做的事情)。
在這種情況下,除非類別很容易區分,否則最準確的分類別模型可能是將所有內容都分類別為 0 的模型。例如,如果只有 0.1% 的瀏覽者在網路商店購買商品,那麼預測每個瀏覽者都會離開而不購買的模型將具有 99.9% 的準確度。然而,這個模型毫無用處。相反,我們希望有一個整體準確度較低但能夠很好地挑出購買者的模型,即使它會誤分類別一些非購買者。
精確度、召回率和特異度
除了純粹的準確度之外,還有其他更細緻的指標常用於評估分類別模型。其中一些指標在統計學(尤其是生物統計學)中有著悠久的歷史,用於描述診斷測試的預期效能。精確度衡量預測正向結果的準確度:
精確度 = 真陽性 / (真陽性 + 假陽性)
召回率,也稱為靈敏度,衡量模型預測正向結果的能力——它正確識別的 1 的比例。召回率在機器學習社群中使用較多,而靈敏度則在生物統計學和醫學診斷中使用較多。召回率的定義是:
召回率 = 真陽性 / (真陽性 + 假陰性)
另一個使用的指標是特異度,它衡量模型預測負向結果的能力:
特異度 = 真陰性 / (真陰性 + 假陽性)
我們可以使用混淆矩陣(confusion matrix)在 R 中計算這三個指標:
# 精確度
conf_mat[1, 1] / sum(conf_mat[,1])
# 召回率
conf_mat[1, 1] / sum(conf_mat[1,])
# 特異度
conf_mat[2, 2] / sum(conf_mat[2,])
在 Python 中,可以使用以下程式碼計算這些指標:
conf_mat = confusion_matrix(y, logit_reg.predict(X))
print('精確度', conf_mat[0, 0] / sum(conf_mat[:, 0]))
print('召回率', conf_mat[0, 0] / sum(conf_mat[0, :]))
print('特異度', conf_mat[1, 1] / sum(conf_mat[1, :]))
scikit-learn 有一個自訂方法 precision_recall_fscore_support,可以一次計算精確度和召回率/特異度。
程式碼解析:
confusion_matrix(y, logit_reg.predict(X))用於生成混淆矩陣,其中y是真實標籤,logit_reg.predict(X)是模型的預測結果。conf_mat[0, 0] / sum(conf_mat[:, 0])計算精確度,代表真陽性佔所有預測為正類別的比例。conf_mat[0, 0] / sum(conf_mat[0, :])計算召回率,代表模型正確識別的正類別樣本佔所有真實正類別樣本的比例。conf_mat[1, 1] / sum(conf_mat[1, :])計算特異度,代表模型正確識別的負類別樣本佔所有真實負類別樣本的比例。
ROC 曲線
可以看出,召回率和特異度之間存在權衡。捕捉更多的 1 通常意味著將更多的 0 誤分類別為 1。能夠捕捉這種權衡的指標是“接收者操作特徵”(Receiver Operating Characteristics)曲線,通常簡稱為 ROC 曲線。ROC 曲線在 y 軸上繪製召回率(靈敏度),在 x 軸上繪製特異度。
ROC 曲線顯示了隨著更改用於分類別記錄的閾值,召回率和特異度之間的權衡。靈敏度(召回率)在 y 軸上繪製,您可能會遇到兩種 x 軸標籤形式:
- 特異度在 x 軸上繪製,左側為 1,右側為 0
- 1-特異度在 x 軸上繪製,左側為 0,右側為 1
無論採用哪種方式,曲線看起來都相同。計算 ROC 曲線的過程是:
- 將記錄按照被預測為 1 的機率排序,從最可能的到最不可能的。
- 根據排序後的記錄計算累積特異度和召回率。
在 R 中計算 ROC 曲線很簡單。以下程式碼計算貸款資料的 ROC:
idx <- order(-pred)
recall <- cumsum(true_y[idx] == 1) / sum(true_y == 1)
specificity <- (sum(true_y == 0) - cumsum(true_y[idx] == 0)) / sum(true_y == 0)
roc_df <- data.frame(recall = recall, specificity = specificity)
ggplot(roc_df, aes(x=specificity, y=recall)) +
geom_line(color='blue') +
scale_x_reverse(expand=c(0, 0)) +
scale_y_continuous(expand=c(0, 0)) +
geom_line(data=data.frame(x=(0:100) / 100), aes(x=x, y=1-x),
linetype='dotted', color='red')
程式碼解析:
order(-pred)將預測機率按降序排序,得到索引idx。cumsum(true_y[idx] == 1) / sum(true_y == 1)計算累積召回率。(sum(true_y == 0) - cumsum(true_y[idx] == 0)) / sum(true_y == 0)計算累積特異度。- 使用
ggplot繪製 ROC 曲線,並新增一條虛線表示隨機分類別器的效能。
在 Python 中,我們可以使用 scikit-learn 的函式 sklearn.metrics.roc_curve來計算 ROC 曲線所需的資訊:
fpr, tpr, thresholds = roc_curve(y, logit_reg.predict_proba(X)[:,0],
pos_label='default')
roc_df = pd.DataFrame({'recall': tpr, 'specificity': 1 - fpr})
ax = roc_df.plot(x='specificity', y='recall', figsize=(4, 4), legend=False)
ax.set_ylim(0, 1)
ax.set_xlim(1, 0)
ax.plot((1, 0), (0, 1))
ax.set_xlabel('特異度')
ax.set_ylabel('召回率')
程式碼解析:
roc_curve(y, logit_reg.predict_proba(X)[:,0], pos_label='default')用於計算 ROC 曲線的假陽性率(fpr)、真陽性率(tpr)和閾值(thresholds)。- 將 fpr 和 tpr 組織成 DataFrame
roc_df,並繪製 ROC 曲線。 - 設定坐標軸範圍,並新增一條對角線表示隨機分類別器的效能。
結果如圖所示。虛線對角線對應於隨機機會分類別器。一個非常有效的分類別器(或者,在醫療情況下,一個非常有效的診斷測試)將具有緊貼左上角的 ROC——它將正確識別很多的 1,而不會將很多的 0 誤分類別為 1。
對於這個模型,如果我們想要一個特異度至少為50%的分類別器,那麼召回率大約是75%。
AUC
ROC曲線是一個有價值的圖形工具,但本身並不構成對分類別器效能的單一衡量指標。然而,ROC曲線可以用來產生曲線下面積(AUC)指標。AUC只是ROC曲線下的總面積。AUC的值越大,表示分類別器越有效。
AUC為1表示完美的分類別器:它能正確分類別所有的1,並且不會將任何0誤分類別為1。
完全無效的分類別器——對角線——將具有0.5的AUC。
精確度-召回率曲線
除了ROC曲線之外,檢查精確度-召回率(PR)曲線也很有啟發性。PR曲線以類別似的方式計算,不同的是資料從最不可能到最可能的順序排列,並計算累積精確度和召回率統計量。PR曲線在評估結果高度不平衡的資料時尤其有用。
程式碼實作:
from sklearn.metrics import precision_recall_curve
precision, recall, thresholds = precision_recall_curve(y, logit_reg.predict_proba(X)[:,0])
pr_df = pd.DataFrame({'precision': precision, 'recall': recall})
ax = pr_df.plot(x='recall', y='precision', figsize=(4, 4), legend=False)
ax.set_ylim(0, 1)
ax.set_xlim(0, 1)
ax.set_xlabel('召回率')
ax.set_ylabel('精確度')
程式碼解析:
precision_recall_curve(y, logit_reg.predict_proba(X)[:,0])用於計算不同閾值下的精確度和召回率。- 將精確度和召回率組織成 DataFrame
pr_df,並繪製 PR 曲線。 - 設定坐標軸範圍,以清晰展示 PR 曲線的變化趨勢。
此部分的內容闡述了評估分類別模型的不同方法,包括精確度、召回率、特異度、ROC曲線、AUC以及精確度-召回率曲線。每種方法都有其特定的應用場景和解讀方式,為理解和最佳化分類別模型的效能提供了多維度的視角。