進階已經雙重審閱,尚未人工抽查

迴歸模型診斷

四張殘差圖各自在抓什麼、為什麼全部通過還是可能漏掉問題、VIF 的重要性被高估在哪裡、影響點怎麼量,以及逐步迴歸為什麼是醫學論文最常見的統計錯誤之一——用模擬把它做給你看。

診斷在檢查什麼

跑出一組係數不代表模型是對的。線性迴歸的每一個 p 值與信賴區間,都建立在四個假設上:

  1. 設定正確——放進去的變項與結果的關係形狀對了(線性、有沒有交互作用)
  2. 變異數固定(homoscedasticity)——殘差的散布不隨預測值改變
  3. 殘差近似常態——影響的主要是小樣本時的區間,大樣本靠中央極限定理救得回來
  4. 觀察彼此獨立——這一條看不出來,要靠設計(重複測量、群集抽樣、同一家醫院的病人都會違反)。 違反之後怎麼辦,見重複測量與群集資料

診斷就是逐條檢查前三條,外加兩個報表看不出來的問題:共線性影響點。 本頁沿用 B2-01 的線性模型與 B2-02 的邏輯模型,你已經讀過它們的報表。

殘差圖要看什麼

四張診斷圖:殘差對預測值、常態 Q-Q 圖、尺度位置圖、槓桿值對標準化殘差並附 Cook's distance 等高線。四張圖都沒有明顯的系統性型態。
B2-01 那個模型的四張標準診斷圖。紅線是 lowess 平滑;D 圖的紅色虛線是 Cook's distance 0.5 與 1 的等高線,圈起來的是本模型 Cook's D 最大的那一位。產圖腳本 figures/scripts/B2-04-model-diagnostics.R
在抓什麼壞掉長什麼樣本模型
A. 殘差 vs 預測值設定是否正確(漏掉的曲率、交互作用)平滑線呈 U 形或倒 U 形未偵測到整體曲率(Tukey 檢定 p 0.632,未達統計顯著)
B. 常態 Q-Q殘差分布的尾巴兩端離開對角線(厚尾、偏態)未偵測到偏離常態(Shapiro-Wilk p 0.765,未達統計顯著)
C. 尺度位置變異數是否固定平滑線往右上爬(喇叭形)未偵測到變異數隨預測值變化(Breusch-Pagan p 0.765,未達統計顯著)
D. 槓桿 vs 殘差有沒有單點在主導模型有點落在 Cook’s D 0.5 或 1 的等高線外最大 Cook’s D 0.118

殘差在低預測值那一半的標準差是 628, 高預測值那一半是 643——幾乎一樣,C 圖平坦是有數字支持的。

兩張殘差圖:左圖殘差對產婦年齡,lowess 平滑線在兩端往上翹;右圖殘差對產婦體重,平滑線大致水平。
同一組殘差,換成對單一變項作圖。年齡那張的平滑線兩端上翹,正是上一節整體檢定漏掉的東西;產婦體重那張是對照組,看起來就該是這樣。產圖腳本 figures/scripts/B2-04-model-diagnostics.R

共線性與 VIF

共線性(collinearity)是指某個變項幾乎可以被其他變項的線性組合預測出來。 變異數膨脹因子(variance inflation factor, VIF)量的就是這件事:

VIFj=11Rj2\mathrm{VIF}_j = \frac{1}{1 - R_j^2}

其中 Rj2R_j^2 是「把第 jj 個變項當結果、用其他所有變項去迴歸」得到的 R²。 VIF=4\mathrm{VIF} = 4 代表那個係數的標準誤被放大了 2 倍。

B2-01 那個模型的 VIF 全部很低(最大 1.34)。 為了示範,故意再放進一個「同一個體重換算成公斤」的欄位——這在真實資料合併之後很常見。 注意換算時帶了一點量測/四捨五入誤差lwt * 0.4536 + rnorm(n, 0, 0.5)), 這正是真實資料合併後的樣子;如果換算是完全等比例的,R 會判定它與 lwt 完全共線(aliased)、 係數直接給 NA、VIF 是無限大,跑不出下面這張表:

變項原模型 VIF加入重複欄位後 VIF
age1.101.11
lwt1.22771.05
lwt_kg771.66
smoke_fYes1.161.16
race_fBlack1.191.19
race_fOther1.341.35
ht1.081.08
ui1.041.04

影響點

離群值(outlier)、槓桿(leverage)、影響力(influence)是三件不同的事:

  • 離群值yy 離預測值很遠 → 看標準化殘差
  • 槓桿xx 落在共變項空間的邊緣 → 看 hat value;平均值是 p/np/n = 0.042
  • 影響力:把它拿掉,係數會不會變 → Cook’s distance,它是前兩者的乘積效果
Di=j(y^jy^j(i))2pσ^2D_i = \frac{\sum_j (\hat{y}_j - \hat{y}_{j(i)})^2}{p \cdot \hat{\sigma}^2}

只有第三件事真的要緊。xx 很極端但落在迴歸線上的點,槓桿高、影響力低, 它其實在幫模型固定斜率。

本模型 Cook’s D 最大的五位:

列號新生兒體重 (g)產婦年齡產婦體重 (lb)槓桿標準化殘差Cook’s D
1304990451230.1062.820.118
1331135341870.153-1.710.066
1321021291300.057-2.900.063
1063790252410.1431.660.058
1023756191840.1081.720.045

這一頁的診斷還替 B2-01 收了一個尾。那頁的年齡平方項在統計上被支持(p 0.018), 但把 3 位超過 35 歲的產婦拿掉重跑,證據就消失了(p 0.373)。 3 個人可以決定一個 189 人模型裡的一項結論—— 這就是為什麼「顯著」與「穩健」是兩件事,也是為什麼多項式不如樣條。

二元與計數結果的診斷不一樣

線性模型的那四張圖不能直接搬到邏輯迴歸上。 原因很簡單:結果只有 0 與 1 兩個值,原始殘差只能落在兩條曲線上, 畫出來永遠是兩條帶子,看不出任何東西(這個模型的原始殘差範圍是 -0.74 到 0.91, 但形狀完全由結果值決定)。

要看的東西換成三樣:

1. 校準(calibration)——預測機率與實際發生率對不對得上。把病人依預測機率分成十組:

十分位人數平均預測機率預期事件數實際事件數
1190.0571.10
2190.1021.92
3190.1542.95
4190.2073.93
5190.2434.64
6180.2835.17
7190.3416.56
8190.4508.68
9190.55110.511
10190.73113.913

Hosmer-Lemeshow 檢定統計量 4.68,df = 8, p 0.792——未偵測到系統性的校準偏差

2. 區辨力(discrimination)——見ROC 與 AUC(B4 家族)。校準與區辨是兩件獨立的事: 一個模型可以排序很準但機率整體偏高,也可以機率很準但排不出順序。

3. 影響力仍然要看——glm 物件一樣有 cooks.distance()hatvalues(),判讀方式相同。

至於Poisson 迴歸,最關鍵的診斷不是殘差圖而是分散度: Pearson 卡方除以自由度是否接近 1。那一頁的例子是 11.05,也就是說標準誤要放大約 3.32 倍。

逐步迴歸:醫學論文最常見的統計錯誤之一

逐步迴歸(stepwise regression)是指讓演算法依 p 值或 AIC 自動增刪變項, 最後留下一組「顯著」的變項。R 的 step() / stepAIC()、SPSS 的 forward / backward 選項都是。

它在論文裡非常普遍,而且幾乎總是錯的。用模擬把它做給你看: 拿 B2-01 那個模型,額外塞進 10 個純粹的標準常態亂數 (與新生兒體重毫無關係),跑 stepAIC(),重複 300 次。

兩張長條圖。左圖是每次執行留下的純亂數變項個數分布,多數落在一到三個。右圖是最終模型裡達到 p 小於 0.05 的亂數變項個數分布,接近一半的執行至少有一個。
300 次模擬。左:stepAIC 平均留下 1.81 個純亂數變項。右:其中平均 0.63 個在最終模型裡達到 p < 0.05,有 48% 的執行至少出現一個「顯著」的亂數。產圖腳本 figures/scripts/B2-04-model-diagnostics.R

更狠的版本:把結果變項也換成亂數,只丟 15 個亂數預測項進去, 資料裡沒有任何東西可以找。結果是 300 次執行中:

  • 平均留下 2.59 個變項
  • 55% 的最終模型至少有一個變項 p < 0.05
  • 平均 R² 是 0.047
  • 64% 的最終模型整體 F 檢定也「顯著」

最後這一項要小心分母:這 300 次裡有 24 次 stepAIC 把變項全部刪光、只剩截距,那種模型沒有整體 F 檢定。 上面的 64% 是把這 24 次 算成「不顯著」的版本(分母 300);若只算 276 次 真的有 F 檢定的執行,比例是 70%。 兩個數字都要看——只報後者等於把「逐步迴歸什麼都沒選中」這些最接近虛無的執行悄悄拿掉, 數字會往「逐步迴歸很會製造假象」的方向多推幾個百分點。順帶一提, 連純亂數資料都有 92% 的執行被 stepAIC 留下至少一個變項。

那變項該怎麼選

你的問題是該怎麼做
估某個暴露的效應(大多數臨床研究)依因果圖(DAG)決定要校正哪些變項,事先寫進計畫書。不看 p 值決定去留。
建預測模型先算所需樣本數,再用懲罰性方法(LASSO、ridge、彈性網),並做內部驗證(bootstrap / 交叉驗證)與外部驗證。報告依 TRIPOD。
探索性、沒有事先假設可以做,但整篇要標明為探索性,不報 p 值當結論,且結果需要另一份資料驗證。

三種情況都有一個共同點:變項的去留不由同一份資料的 p 值決定。

動手跑一次

library(MASS)
data(birthwt, package = "MASS")
bw <- birthwt
bw$race_f  <- factor(bw$race,  levels = 1:3, labels = c("White", "Black", "Other"))
bw$smoke_f <- factor(bw$smoke, levels = 0:1, labels = c("No", "Yes"))

fit <- lm(bwt ~ age + lwt + smoke_f + race_f + ht + ui, data = bw)

par(mfrow = c(2, 2)); plot(fit)          # 四張標準診斷圖

# ⚠️ 標準四張圖的橫軸是預測值;單一變項的曲率會被稀釋掉
plot(bw$age, residuals(fit)); lines(lowess(bw$age, residuals(fit)))

# VIF,從定義算(不需要 car)
X <- model.matrix(fit)[, -1]
sapply(seq_len(ncol(X)), function(j) 1 / (1 - summary(lm(X[, j] ~ X[, -j]))$r.squared))

# 共線性示範:把體重換算成公斤再放一次
# ⚠️ 換算要帶一點誤差,否則兩欄完全等比例,R 會判為 aliased、係數給 NA、算不出 VIF
bw$lwt_kg <- bw$lwt * 0.4536 + rnorm(nrow(bw), 0, 0.5)
fit_col <- lm(bwt ~ age + lwt + lwt_kg + smoke_f + race_f + ht + ui, data = bw)
summary(fit_col)$coefficients[c("lwt", "lwt_kg"), ]

# 影響點:找出來,然後實際重跑看結論會不會變
cd <- cooks.distance(fit)
worst <- which.max(cd)
coef(fit)["smoke_fYes"]
coef(lm(formula(fit), data = bw[-worst, ]))["smoke_fYes"]

# 逐步迴歸會撿到什麼:塞 10 個亂數進去試一次
d <- bw[, c("bwt", "age", "lwt", "smoke_f", "race_f", "ht", "ui")]
for (j in 1:10) d[[paste0("z", j)]] <- rnorm(nrow(d))
summary(stepAIC(lm(bwt ~ ., data = d), direction = "both", trace = 0))

驗證環境:R 4.6.0 + MASS 7.3.65。car 套件未安裝,本頁的 VIF 由定義計算;car::vif() 對因子給的是 GVIF,數值不同。

常見誤用

誤用為什麼錯
跑完迴歸不看任何診斷p 值與信賴區間的效力建立在假設上
只看標準四張圖就宣告設定正確單一變項的曲率會在預測值裡被稀釋;要逐變項畫殘差
用常態性檢定決定要不要用線性迴歸假設是「殘差」近似常態不是結果變項;大樣本時這條最不重要
看到 VIF 高就刪變項共線性只傷害捲進去的變項;你關心的那個不在裡面就不必動
把 VIF 5 或 10 當成硬門檻都是慣例;該問的是標準誤還夠不夠回答問題
把 car::vif() 的 GVIF 與逐欄 VIF 混著比兩者定義不同,數值不可互比
把高槓桿點當成離群值刪掉槓桿高不等於有影響力;要看 Cook’s distance
用 Cook’s D 門檻自動清資料應該查是不是資料錯誤,並做敏感度分析
刪掉影響點但不申報資料操弄
把線性模型的殘差圖搬到邏輯迴歸0/1 結果的原始殘差只會排成兩條帶子
Hosmer-Lemeshow 不顯著就宣稱校準良好那是「沒有證據說它壞掉」;分組方式與樣本數都會左右結果
用逐步迴歸挑變項再照常報 p 值選擇本身是多重比較;p 值、CI、R² 全部過度樂觀
用逐步迴歸的結果宣稱「獨立危險因子」那組變項換個子樣本就會變
先看單變項 p 值再決定放進多變項模型同一種問題的另一個版本,一樣讓推論失效

重跑本頁的所有數字

/opt/homebrew/bin/Rscript figures/scripts/B2-04-model-diagnostics.R

讀讀看這張圖

答案取自產生本頁圖表的同一份統計輸出,不是另外打上去的。

把母親體重同時以磅與公斤兩種單位放進同一個模型。lwt 那一項會怎麼變?

看答案與解析

正確答案: VIF 變成 771.1——兩個幾乎相同的變項會互相解釋

lwt 的 VIF 從 1.2 爆到 771.1。「單位不同、資訊沒變」這個直覺對資料是對的,對估計卻不是:兩個幾乎完全相同的變項會互相解釋,模型無法把效果分給誰,個別係數的標準誤因此暴增。771.7 是全模型的最大 VIF,落在公斤那個版本上,不是 lwt 這一列。值得注意的是 R 平方與殘差標準差幾乎沒變——共線性不會讓模型預測得比較差,它讓個別係數變得無法解讀。

共線性讓 lwt 的 VIF 爆炸。抽菸那一項的係數會受到什麼影響?

看答案與解析

正確答案: 變成 -358.5——只動了很小的幅度,因為它與那兩項不相關

抽菸的係數從 -360.7 移到 -358.5,動了不到一個百分點。共線性只影響彼此高度相關的那幾項,與它們無關的係數不受牽連——所以看到一個很大的 VIF 不代表整個模型要重做,要問的是「我在意的那一項有沒有被捲進去」。647.4 是殘差標準差,不是任何一個係數;它幾乎沒變,正好呼應共線性不傷預測這件事。

這個模型的整體殘差圖、常態性與變異數齊一性檢定都很漂亮。那麼把殘差對各共變項的二次項再迴歸一次,是為了看什麼?

看答案與解析

正確答案: 看年齡是不是線性,p = 0.017,有證據反對線性

整體診斷通過,只代表殘差沒有一眼可見的結構;拆到單一變項才看得出 age 的二次項顯著(0.017),也就是它可能不是線性的。0.749 是母親體重那一項,那一項確實沒問題;0.632 是 Tukey 的 non-additivity 檢定,它問的是整體有沒有非可加性,而它同樣沒抓到年齡這件事。「診斷全部過關」很多時候只代表沒有拆得夠細。

延伸觀看

生物統計學一 93.【迴歸分析 (1)】Simple Linear Regression Model
繁中臺大開放式課程 NTU OCW· 22 min繁中,把線性迴歸的假設一條一條列清楚。本頁在檢查的就是這幾條,先確認自己知道要檢查什麼。
Lec04 統計學(二) Ch11.1-11.5 簡單廻歸分析與相關分析
繁中NYCU OCW· 143 min本站盤點的已驗證影片裡沒有專講迴歸診斷的一集;這支長課的殘差與模型檢定段落是最接近的補充。

素材來源與授權

本頁為原創內容

回報內容問題

這個站的統計內容由 AI 撰寫、AI 互審,人工只做抽查。你看得出來的錯,我們不一定看得出來。

寫得越具體越修得動,例如哪一句話跟哪本教科書/哪篇論文的說法不一致。

留了才回得了信;不留也會看。

一併送出的資訊

這些是自動帶上的,每一項都可以取消。