預測模型研究
預測模型問的不是「哪個變項有關」而是「這個人的風險是多少」,而這個轉變改變了驗收標準——本章用一個真實的外部驗證示範:鑑別力只掉一點,校準卻系統性偏掉。
問題換了,驗收標準也跟著換
前面幾章的模型都在回答病因學的問題:這個暴露與這個結果有沒有關聯、關聯有多大、是不是因果。 預測模型問的是完全不同的事:給我這個人的資料,他的風險是多少。
這個轉變的後果比它聽起來大:
| 病因學研究 | 預測模型 | |
|---|---|---|
| 想知道 | 某個變項的效應 | 某個人的風險 |
| 變項要不要進模型 | 看因果結構(是干擾因子嗎、是中介嗎) | 看它有沒有幫助預測,因果無關緊要 |
| 共線性 | 會讓目標係數不穩,是問題 | 只要預測值穩定就不是問題 |
| 好壞怎麼判斷 | 估計是否無偏、假設是否成立 | 在沒看過的人身上表現如何 |
這一章的例子:一個真的外部驗證
用兩份乳癌世代:survival::rotterdam(2982 人)開發模型,
survival::gbsg(686 人)做外部驗證。
選這一對的理由只有一個:它是本站唯一能誠實示範外部驗證的組合。 把同一份資料切成兩半叫 internal validation,穿上外部驗證的衣服而已—— 真正的外部驗證要求另一群人、另一批研究者、另一個時空。
先講通常不會被寫出來的那一半:資料調和
兩份資料的欄位定義不一樣,所以在跑任何模型之前,得先做一連串對應決定。 這些決定每一個都可能改變結果,但論文的 Methods 常常只寫一句「兩個世代的變項經調和後納入分析」。
本章把它們全部列出來:
| # | 調和決定 |
|---|---|
| 1 | rotterdam records recurrence and death separately: recurrence-free survival is taken as the first of the two, to match gbsg's single rfstime endpoint. |
| 2 | rotterdam records tumour size in bands (<=20, 20-50, >50 mm); each band is mapped to its midpoint (15, 35, 60 mm) so it can enter the model as a continuous term alongside gbsg's millimetres. |
| 3 | Grade is collapsed to 1-2 versus 3 because the two cohorts do not use the same grading detail. |
| 4 | Complete cases only, on the four predictors and the endpoint. |
開發:EPV 與變數選擇
模型是 Cox 迴歸,四個預測變項(年齡、腫瘤大小、淋巴結數、分級)。
開發世代有 2982 人、1713 個事件, 每個變項分到 428 個事件(EPV, events per variable)。
EPV 的經驗法則是「每個變項至少 10 個事件」。這裡遠遠超過,所以樣本量不是這個模型的限制。
模型的係數:
| 變項 | HR | 95% CI | p |
|---|---|---|---|
| age_y | 1.01 | 1.00–1.01 | 0.005 |
| size_mm | 1.01 | 1.01–1.02 | < 0.001 |
| nodes_n | 1.07 | 1.07–1.08 | < 0.001 |
| grade_f3 | 1.39 | 1.24–1.57 | < 0.001 |
內部驗證:樂觀偏誤有多大
在開發模型的同一份資料上量出來的表現一定偏好,因為係數就是為了讓那份資料好看而挑的。 這個差距叫 optimism,用 bootstrap 量它:重抽樣、在重抽樣上配模型、 比較它在重抽樣與在原始資料上的表現,差額就是樂觀的量。
| 指標 | 值 |
|---|---|
| 表面 C-index(apparent) | 0.666 |
| Bootstrap optimism(200 次) | 0.0004 |
| 校正後 C-index | 0.666 |
Optimism 只有 0.0004——幾乎為零。 這不是模型特別好,而是樣本量相對於參數數量非常充足(EPV 428), 沒有什麼可以過度配適的空間。EPV 只有個位數的模型,這個差距會大得多。
外部驗證:鑑別力還行,校準偏了
這是本章的重點。同一個模型丟到 gbsg(686 人、299 個事件):
| 指標 | 開發世代 | 外部世代 |
|---|---|---|
| C-index | 0.666 | 0.642 |
| 校準斜率 | 1(依定義) | 0.691(95% CI 0.539–0.842) |
如果只看 C-index,你會以為這個模型移植得還可以——從 0.666 掉到 0.642,掉了約 2.4 個百分點, 論文裡這種程度通常會被寫成「鑑別力維持良好」。
然後看校準圖:
figures/scripts/D5-prediction-rotterdam-gbsg.R| 預測風險五分位 | n | 預測 5 年風險 | 實際觀察 | 差距 |
|---|---|---|---|---|
| 第 1 組 | 138 | 28.7% | 36.4% | 7.7 個百分點 |
| 第 2 組 | 137 | 33.2% | 44.4% | 11.2 個百分點 |
| 第 3 組 | 137 | 38.8% | 46.0% | 7.3 個百分點 |
| 第 4 組 | 137 | 47.2% | 55.1% | 7.9 個百分點 |
| 第 5 組 | 137 | 70.5% | 72.1% | 1.7 個百分點 |
校準斜率 0.691 明顯小於 1,說的是另一件事: 模型給出的風險差異在這個族群太極端——它把高風險的人推得太高、低風險的人壓得太低。 斜率 < 1 是外部驗證最常見的形態,通常代表開發時有過度配適,或兩個族群的風險結構不同。
校準壞了怎麼辦
不是丟掉模型,而是重新校準(recalibration),從輕到重有三個層次:
- 只調截距(calibration-in-the-large)——修正整體風險水準的偏移。這裡「整體被低估」的那一半就屬於這一類, 而且是最容易修的:新族群基準風險較高,把基準風險換掉即可。至於 0.691 的斜率是另一個問題, 仍然需要第 2 層。
- 調截距 + 斜率——連風險差異的幅度一起修。
- 重新估計全部係數——那已經接近重新開發一個模型了。
TRIPOD 要求你講清楚的事
TRIPOD+AI 的清單很長,但對讀者而言最關鍵的是這幾項是否交代:
- 模型完整可用嗎:所有係數、截距、基準風險(存活模型還需要基準存活函數)。少一項就無法重現。
- 預測變項怎麼測、什麼時候測:如果某個變項在部署情境下拿不到,模型就用不了。
- 缺失值怎麼處理:開發時用多重插補、部署時病人少一個檢驗值——那時候怎麼辦?
- 驗證是內部還是外部:切一半不是外部。
- 校準有沒有報:只報 C-index 或 AUC 的預測模型論文,等於沒報一半。
常見誤用
| 誤用 | 為什麼錯 |
|---|---|
| 只報 C-index / AUC 不報校準 | 排序對了不代表數值對;本章的例子就是鑑別力尚可而校準系統性偏移 |
| 把資料切一半叫「外部驗證」 | 那是內部驗證;外部要求另一群人、另一批研究者 |
| 在同一份資料上挑最佳切點再報表現 | 樂觀偏誤;切點也需要驗證 |
| 用逐步迴歸挑變項再報 p 值 | 選變項的過程本身用掉了自由度,事後的 p 值沒有意義 |
| 校準壞掉就宣布模型無效 | 多數情況重新校準即可,尤其只是整體風險水準偏移時 |
| 不報資料調和的決定 | 每個對應決定都可能改變結果,讀者無從判斷 |
| EPV < 10 還宣稱模型穩健 | 幾乎一定過度配適;但 EPV ≥ 10 也不保證足夠,該用 Riley 的樣本量計算 |
| 模型缺基準風險就發表 | 沒有基準風險就算不出絕對風險,模型無法使用 |
重跑本頁的所有數字
/opt/homebrew/bin/Rscript figures/scripts/D5-prediction-rotterdam-gbsg.R讀讀看這張圖
答案取自產生本頁圖表的同一份統計輸出,不是另外打上去的。
模型從開發世代移到外部世代,鑑別力只掉了一點。可以據此說「模型移植得還可以」嗎?
看答案與解析
正確答案: 不行。校準斜率是 0.691,明顯小於完美校準,而 C-index 對整條刻度的平移與縮放完全免疫
C-index 只問「模型有沒有把高風險的人排在低風險的人前面」。把每個人的預測風險同時乘上或加上一個常數,排序完全不變,C-index 也就一動不動。所以 0.666 掉到 0.642 這件事,對「預測值本身準不準」什麼都沒說。校準斜率 0.691 說的是另一件事:模型給出的風險差異在這個族群太極端,高風險的人被推得太高、低風險的人被壓得太低。只報 C-index 或曲線下面積、不報校準的預測模型論文,等於只報了一半。
外部驗證的校準圖裡,五個風險五分位的觀察值全部落在對角線上方。最低風險那一組該怎麼讀?
看答案與解析
正確答案: 模型給他們的預測是 0.287,實際發生的是 0.364——這一組會被歸進低風險,而他們實際的風險並不低
五組全部落在對角線上方,代表整條刻度被往下平移,不是某一組的抽樣意外。最低風險那組預測 0.287、實際 0.364,臨床上這正是最危險的位置:門檻式的決策拿預測值去跟門檻比,而預測值系統性偏低就會把該治療的人歸進不治療那一邊。0.721 確實是最高風險那組的觀察值,但那一組的預測值幾乎與它吻合——偏移不是均勻的,低風險端偏得多。這個形狀是兩件事疊在一起:整條刻度被往下平移,再加上校準斜率小於完美校準把高風險端往回拉。單靠斜率偏小產生不出這張圖,那會讓高風險端落到對角線下方。
bootstrap 量出來的樂觀偏誤幾乎等於零。這代表這個模型特別好嗎?
看答案與解析
正確答案: 不代表。樂觀偏誤 0.0004 這麼小,是因為事件數相對於參數個數非常充足,沒有什麼可以過度配適的空間
樂觀偏誤量的是「在自己身上量出來的表現,比在沒看過的資料上高多少」。它會很小,通常是因為模型沒有機會過度配適——這裡四個變項配上一千七百多個事件,每個變項分到的事件數是三位數,遠遠超過經驗法則。所以 0.0004 說的是樣本量相對於參數很充足,不是模型抓到了什麼。0.6661 與 0.6657 幾乎一樣,正是這件事的兩種寫法。更重要的是,內部驗證再乾淨也回答不了外部的問題:這個模型在外部世代的校準系統性偏掉,而那件事 bootstrap 在開發資料上永遠看不到。
這一章用一份世代開發、另一份世代驗證,而不是把一份資料切成兩半。差別在哪?
看答案與解析
正確答案: 外部驗證用的是另一群人。那 686 位病人的收案年代、地點與臨床流程都與開發世代不同
把同一份資料切成兩半,兩半仍然共用同一套收案條件、同一批研究者、同一個時空與同一份變項定義,所以它量到的是內部的穩定性,不是移植的表現。686 位驗證世代病人與 2982 位開發世代病人的差別不在人數,在於他們是另一個世代——這也是為什麼跑模型之前得先做一連串資料調和的決定,例如把分組的腫瘤大小換算成各組中點。那個換算是一個假設,不是資料,而且它不會出現在任何統計檢定裡。事件數 1713 確實充足,但事件夠多不會讓內部驗證變成外部驗證。
這個模型有四個預測變項,每個變項分到的事件數遠超過「每個變項至少十個事件」的經驗法則。可以據此宣稱樣本量足夠嗎?
看答案與解析
正確答案: 大致可以,但理由要說對。每個變項 428 個事件遠超過經驗法則,樣本量不是這個模型的限制
每個變項十個事件這條規則來自一九九零年代的模擬,後續研究顯示需要的樣本量遠比單一數字複雜,Riley 等人提出的樣本量計算才是現在的建議做法。所以 428 這個數字能支持的結論很有限:它足以說「樣本量不是這裡的限制」,不足以說「因為超過門檻所以足夠」。這條規則真正還有用的方向是反面——每個變項只分到個位數事件的模型幾乎一定過度配適。1713 與 2982 都是總量,總量大而變項也多的模型一樣可能不夠;決定的是比值,不是任何一個絕對數。
外部世代的校準壞了:五組全部被低估,而且校準斜率明顯小於完美校準。該怎麼處理?
看答案與解析
正確答案: 先調截距修掉整體被低估的那一半,再處理斜率——0.691 這個斜率不是平移能修的,它需要第二層的重新校準
重新校準從輕到重有三層:只調截距、調截距加斜率、重新估計全部係數。這張圖是兩件事疊在一起,所以兩層都需要——整體被低估屬於第一層,把基準風險換掉即可;0.691 的斜率屬於第二層,平移動不了它。0.444 是第二組的實際風險,也是偏離最大的那一組,但「偏離最大」不等於「只要把它對齊就好」,其他四組的偏離幅度並不相同。至於 0.539 只是斜率區間的下界,校準壞掉幾乎從來不是丟掉模型的理由——多數情況重新校準即可,選哪一層取決於新族群有多少資料,而且不論哪一層,校準之後都需要再驗證一次。
本章用到的統計方法
延伸觀看
Hazard Ratios – Best explanation for beginners
COX REGRESSION and HAZARD RATIOS素材來源與授權
- TRIPOD+AI statement: updated guidance for reporting clinical prediction modelsCC BY本章的節次順序依 TRIPOD+AI 的項目編排,文字為原創改寫。