返回文章列表

邏輯迴歸模型評估與殘差分析

本文探討邏輯迴歸模型的評估方法與殘差分析技巧,涵蓋了關鍵指標如準確率、精確率、召回率、特異度、ROC 曲線和 AUC,並輔以 R 和 Python 程式碼示範如何計算和解讀這些指標,同時也闡述了在資料不平衡情況下如何使用精確度-召回率曲線進行模型評估。

機器學習 統計分析

邏輯迴歸模型在預測二元結果方面應用廣泛,但其評估方法與線性迴歸有所不同。除了常見的係數顯著性檢定外,更需要關注模型的分類別效能。由於邏輯迴歸處理的是機率,因此需要根據不同的閾值判斷分類別結果,並使用混淆矩陣計算精確率、召回率、特異度等指標。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等評估指標。

內容解密:

  1. 輸出結果的解讀:邏輯迴歸的輸出結果提供了係數估計、標準誤差、z值和p值等資訊,用於評估模型中各變數的重要性。
  2. 評估指標的差異:由於邏輯迴歸處理的是二元結果,因此不適用線性迴歸中的評估指標,如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')

內容解密:

  1. 部分殘差的計算:透過將模型的殘差與部分擬合值相加,得到部分殘差,以此來評估變數對結果的影響。
  2. 圖形化展示:利用ggplot2套件繪製部分殘差圖,以視覺化的方式呈現資料的非線性行為和異常值。
  3. 結果解釋:部分殘差圖中,點雲的分佈情況可以幫助我們理解模型的擬合程度和資料的特性。

分類別模型的評估

除了殘差分析外,分類別模型的評估還包括了對模型整體效能的評估。這通常透過將模型應用於測試資料集,並計算諸如準確率、精確率、召回率等指標來實作。

重點概念

  • 邏輯迴歸是一種用於二元分類別的廣義線性模型。
  • 邏輯迴歸的輸出需要經過轉換才能得到機率值。
  • 評估邏輯迴歸模型需要使用特定的指標和方法。
  • 殘差分析對於理解邏輯迴歸模型的表現至關重要。

進一步閱讀

  • 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

內容解密:

  1. predict 函式用於對訓練集進行預測,得到預測機率。
  2. as.numeric(pred > 0) 將預測機率轉換為二元分類別結果(0 或 1)。
  3. true_y 表示實際的分類別結果。
  4. true_postrue_negfalse_posfalse_neg 分別表示真正例、真反例、假正例和假反例。
  5. matrix 函式用於構建混淆矩陣。
  6. colnamesrownames 用於設定混淆矩陣的列名和行名。

在 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

內容解密:

  1. logit_reg.predict(X) 對輸入資料 X 進行預測,得到預測結果。
  2. pred_y 表示預測結果是否為 ‘default’。
  3. true_y 表示實際結果是否為 ‘default’。
  4. true_postrue_negfalse_posfalse_neg 分別表示真正例、真反例、假正例和假反例。
  5. 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. 將記錄按照被預測為 1 的機率排序,從最可能的到最不可能的。
  2. 根據排序後的記錄計算累積特異度和召回率。

在 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以及精確度-召回率曲線。每種方法都有其特定的應用場景和解讀方式,為理解和最佳化分類別模型的效能提供了多維度的視角。