題幹與適用情境
一個詐欺辨識模型在隨機切分的離線驗證中表現異常出色,上線後效果卻明顯下降。每一列樣本代表一筆交易,模型需要在交易發生時決定是否攔截;標籤是交易後 30 天內是否確認拒付。候選特徵來自交易事件、帳戶歷史彙總、最終拒付結果和人工審核狀態。
請解釋什麼是資料洩漏,排查目標、時間、實體重複與預處理四類洩漏,並重新設計特徵生成、訓練/驗證/測試切分、交叉驗證和最終評估流程。還要說明怎樣區分洩漏、訓練—服務偏差和真實分布漂移。
這類問題常見於機器學習工程、資料科學、風控和推薦系統面試。面試官通常不滿足於「先切分再預處理」這一句,而會追問某個特徵在真實預測時間是否已經存在、同一實體能否跨集合,以及團隊是否藉測試集反覆調過模型。
面試官考察重點
第一,看候選人能否給出可操作的定義。資料洩漏是模型開發或評估使用了真實預測時不可取得的資訊,或者讓驗證/測試集合的資訊反向影響了訓練、特徵選擇或模型選擇。它通常讓離線指標過度樂觀,但線上下降本身不能證明洩漏;資料漂移、標籤定義不一致和線上特徵計算錯誤也會產生相似現象。
第二,看是否先定義預測契約。對每一列樣本,都要明確 prediction_at、標籤觀察窗口、允許使用的資料截止時間和線上服務對象。沒有這個邊界,「過去七天交易數」也可能偷偷包含預測之後的事件;一個業務欄位是否洩漏,取決於它何時可用,而不取決於欄位名稱看起來多麼合理。
第三,看切分是否重現部署方式。獨立同分布樣本才適合普通隨機切分;有時間順序時應做前向驗證,有使用者、裝置、商戶等群組結構時應做分組隔離或至少增加分組壓力測試。縮放、填補、特徵選擇和編碼必須在每個訓練折內擬合,最終測試集不能參與調參。
最後,看診斷是否有證據鏈:時間點重放、特徵可用性台帳、跨集合重複檢查、可疑特徵消融、標籤置亂負對照,以及隨機切分與部署一致切分的差異。高品質回答還會承認更嚴格的評估通常降低指標、減少可訓練資料,卻換來更可信的泛化估計。
回答前需要釐清的問題
- 預測發生在什麼時候? 本題假設交易到達時立即評分,之後產生的資訊一律不能進入該列特徵。
- 標籤什麼時候成熟? 本題以交易後 30 天內確認拒付為正例;靠近資料截止日、尚未走完觀察窗口的樣本不能當作負例。
- 模型服務舊實體還是新實體? 若線上會重複看到舊帳戶,時間切分是主評估;若要泛化到新商戶或新裝置,還需要按實體隔離的測試。
- 歷史彙總按什麼時間計算? 必須用事件時間和當時可見的資料做 point-in-time/as-of 計算,不能從今天的資料倉儲快照回填歷史。
- 是否有重複或近重複樣本? 同一交易重試、鏡像日誌、同一案件的多筆記錄和高度相似文字都可能跨集合。
- 哪些步驟從資料中學習參數? 缺失值、正規化、詞彙表、特徵選擇、降維、目標編碼和門檻選擇都算;不能只檢查最終模型。
- 測試集看過多少次? 若團隊依據測試結果改過特徵或超參數,它已經參與模型選擇,需要重新建立未接觸的最終留出集。
- 線上下降的具體形態是什麼? 要同時比較輸入分布、特徵缺失率、標籤延遲、離線重放和線上服務日誌,避免把所有問題都叫作洩漏。
30 秒回答框架
「我先定義預測時間和 30 天標籤窗口,逐項確認特徵當時確實可用;再排查事後結果、未來資料、跨集合重複,以及在全量資料上擬合預處理這四條洩漏路徑。開發集按時間前向驗證,需要時隔離實體,所有可學習轉換只在訓練折擬合。模型和門檻鎖定後,最終測試集只評一次。我再用時間點重放、重複稽核、特徵消融和標籤置亂定位問題,並單獨檢查線上計算偏差與分布漂移。」
分步深入解答
先寫預測契約,而不是先挑切分函式。每一列至少記錄:業務實體、事件時間 eventat、系統實際看見該事件的時間 availableat、預測時間 predictionat、標籤成熟時間 labelreadyat。一項特徵只有在 availableat <= prediction_at,且其所有上游資料也滿足這個條件時,才能用於該列預測。
本題的特徵審查可以這樣做:
| 候選特徵 | 交易發生時能否使用 | 處理規則 | |---|---:|---| | 本筆交易金額、管道 | 是 | 以線上請求實際攜帶的值為準 | | 帳戶過去 7 天交易數 | 有條件 | 只統計該筆交易前且當時已到達的事件 | | 最終拒付原因 | 否 | 它是標籤形成過程的一部分,必須刪除 | | 人工審核最終狀態 | 否 | 預測之後才產生,必須刪除 | | 裝置風險分數 | 有條件 | 讀取當時版本的快照,不能用今天重算的值 |
接著按資訊穿越邊界的方式分類。目標洩漏包括直接放入標籤、標籤代理變數或事後處置結果,例如拒付原因、退款完成狀態。時間洩漏包括未來事件、用全時間段計算的滾動彙總、晚到資料回填,以及「先彙總再按時間切分」。實體洩漏包括同一交易的副本、同一案件的多列記錄、近重複文字,或模型透過帳戶 ID 記住了驗證樣本。預處理洩漏發生在全量資料上擬合填補值、縮放參數、詞彙表、特徵選擇或目標編碼;即使最終分類器從未見過測試標籤,整條訓練流程仍已看見評估集合。
切分方案要由上線問題決定:
- 先按
prediction_at排序,把較早時間段作為開發資料,把最新且標籤已成熟的連續時間段封存為最終測試集。 - 在開發資料上做前向交叉驗證:每一折只用更早資料訓練,用隨後時間段驗證。標籤觀察窗口可能跨過邊界時,在訓練尾部與驗證開頭之間做 purge/gap,避免訓練樣本的標籤資訊來自驗證期。
- 在切分前建立重複群集和實體群組。目標是新實體泛化時,讓同組樣本只出現在一側;線上會反覆服務舊實體時,時間切分仍是主指標,但要額外報告按帳戶、裝置或商戶隔離的壓力測試。
- 只有訓練折可以呼叫
fit。驗證折和測試集只允許呼叫由該訓練折參數執行的transform。目標編碼在訓練資料內部使用交叉擬合,讓每一列的編碼來自不包含自身標籤的其他折。 - 用交叉驗證選擇特徵、超參數和決策門檻。全部決策凍結後,在完整開發集上重新擬合一次,再對最終測試集評估一次;若看完結果繼續改模型,就需要新的測試集。
流程可以用下面的虛擬程式碼表達。forwardsplits 負責時間順序和標籤窗口隔離,makepipeline 把全部可學習轉換與模型綁在一起:
dev, test = point_in_time_split(rows, test_period="latest_mature_period")
for train_idx, valid_idx in forward_splits(
dev,
time="prediction_at",
purge="label_horizon",
):
pipeline = make_pipeline(
imputer="fit_on_train_fold",
scaler="fit_on_train_fold",
target_encoder="out_of_fold",
model="candidate",
)
pipeline.fit(dev[train_idx].X, dev[train_idx].y)
record(pipeline, dev[valid_idx])
locked_pipeline = select_and_lock()
locked_pipeline.fit(dev.X, dev.y)
final_result = evaluate_once(locked_pipeline, test)然後做診斷。第一層是靜態血緣稽核:為每個特徵記錄來源表、事件時間、可用時間、彙總窗口、更新延遲和標籤依賴,自動拒絕截止時間之後的資料。第二層是集合稽核:比較精確雜湊、近重複指紋和實體 ID 的交集;重複群集應作為一個切分單位。第三層是實驗性負對照:移除最可疑特徵、把標籤在合法分組內置亂、把隨機切分替換為時間/分組切分。置亂後結果應回到無訊號基線;部署一致切分大幅下降是洩漏警報,但不是單獨的定罪證據。
第四層是時間點重放。選取歷史交易,把特徵服務的時鐘固定在當時,比較離線訓練列與線上日誌中真實可見的欄位。若離線值使用了之後回填的資料,這是時間洩漏;若兩邊的計算規則、預設值或版本不同,則屬於訓練—服務偏差。即使這些都正確,使用者結構或詐欺手法隨時間改變仍會產生分布漂移,所以還要按時間群組比較輸入分布、標籤率和分段指標。
最後把防線產品化:資料集快照不可變,切分清單可重現,特徵定義帶可用時間,訓練 pipeline 有版本,最終測試集有存取記錄。每次新增特徵都要回答一句話:「對這一列預測,在 prediction_at 當時能否真實算出完全相同的值?」回答不清楚就不能進入訓練。
高品質示範回答
「資料洩漏的核心是資訊越過了我們聲稱的預測邊界。這裡模型在交易發生時評分,所以我會先定義每列的 prediction_at,標籤則要等 30 天拒付窗口結束才成熟。最終拒付原因和人工審核終態是明顯的結果洩漏;帳戶過去 7 天交易數看似合理,但若從今天的資料倉儲快照回算,可能包含晚到或預測後的事件,同樣是洩漏。
我會為每個特徵建立 event time、available time、彙總窗口和標籤依賴台帳,用 as-of join 重建當時可見值。資料先按預測時間切出最新的成熟時間段作為封存測試集,開發集用前向交叉驗證;若標籤窗口跨越折邊界,就在邊界做 purge。重複交易、同一案件和近重複記錄先組成群集再切分。是否把帳戶完全隔離,取決於線上是預測舊帳戶還是新帳戶,我會把部署一致評估作為主指標,實體隔離作為泛化壓力測試。
填補、縮放、特徵選擇和編碼都放進 pipeline,每折只在訓練部分擬合。目標編碼用交叉擬合,不能讓一列自己的標籤參與自己的編碼。驗證結果用於選特徵、超參數和門檻;選擇完成後鎖定流程,在完整開發集重訓,只看一次最終測試集。
排查時我會查跨集合雜湊、近重複和實體交集,做可疑特徵消融、合法分組內的標籤置亂,並比較隨機切分與時間/分組切分。再用歷史時鐘重放特徵,核對線上日誌。隨機切分分數下降只能說明原評估邊界可疑;如果時間點資料無穿越但線上計算不一致,是訓練—服務偏差;兩邊一致而後續時間段持續變差,才進一步檢查真實分布漂移。更嚴格的流程可能讓離線分數變低,卻給出了可以拿去做上線決策的估計。」
常見錯誤
- 只把「測試標籤進入訓練」叫洩漏 → 會漏掉未來特徵、重複樣本和全量預處理 → 稽核從原始資料到模型選擇的整條資訊流。
- 看到線上下降就斷言洩漏 → 漂移、標籤偏差和線上實作錯誤也會下降 → 分別檢查時間點血緣、離線重放和時間分段分布。
- 先在全量資料上縮放或選特徵再切分 → 評估集合影響了轉換參數 → 先切分,並讓 pipeline 在每個訓練折內擬合。
- 所有資料都隨機切分 → 未來樣本和同實體副本可能進入訓練 → 按部署的時間與實體結構選擇切分器。
- 歷史彙總只過濾
event_at→ 晚到或回填記錄在當時可能尚不可見 → 同時約束事件時間與可用時間。 - 按列去重但忽略近重複和案件群組 → 模型仍能記住幾乎相同的樣本 → 先生成重複群集和業務群組,再整體分配。
- 目標編碼直接在整份訓練集上計算 → 每列標籤會進入自己的特徵 → 使用折外編碼或帶內部交叉擬合的實作。
- 反覆查看測試集並據此改模型 → 測試集逐漸變成驗證集 → 保留存取受控的最終留出集,決策凍結後只評一次。
- 用固定「隨機分數」判斷標籤置亂測試 → 不同指標和類別分布的無訊號基線不同 → 與該指標在相同採樣規則下的基線比較。
- 為了消除洩漏刪除所有實體歷史 → 可能丟掉線上真實可用的有效訊號 → 保留預測時可用的資訊,用正確邊界評估而非機械刪特徵。
追問及應對
追問一:什麼時候隨機切分是合理的?
當樣本確實近似獨立同分布,生產流量與收集資料來自同一生成過程,而且沒有時間、使用者、裝置、實驗批次或重複群集結構時,隨機切分可以給出合理估計。仍應先檢查重複和預處理邊界。若生產目標是預測未來,時間留出通常更接近真實部署。
追問二:為什麼標籤延遲需要 purge 或 gap?
一筆訓練交易的標籤可能在之後 30 天才確定。若訓練期緊貼驗證期,這個訓練標籤會使用驗證時間段內發生的結果;團隊在真實驗證起點並不擁有它。邊界隔離應覆蓋標籤觀察窗口,或只納入在每個訓練截止點已經成熟的樣本。
追問三:同一帳戶的歷史能否作為特徵?
可以,前提是線上在預測時確實擁有這段歷史,並且彙總只使用當時可見的過去事件。是否讓同一帳戶跨訓練和測試取決於目標:服務回訪帳戶時可以跨時間保留,評估新帳戶泛化時必須按帳戶隔離。最好分別報告兩種情境,避免一個分數回答兩個問題。
追問四:交叉擬合怎樣防止目標編碼洩漏?
把訓練資料分成若干折。每一折的類別統計只由其他折的標籤計算,再用於編碼該折;因此一列自己的標籤不會直接參與自己的特徵。驗證集和測試集則使用對應訓練資料學到的映射。交叉擬合只能解決編碼內部的標籤洩漏,不能替代正確的外層時間或分組驗證。
追問五:怎樣區分資料洩漏與分布漂移?
先用時間點重放證明每個離線特徵在預測時都可用,再核對線上與離線的同一批樣本是否算出相同值。前者失敗是洩漏,後者失敗是訓練—服務偏差。兩者都通過後,再觀察不同時間段的輸入、標籤率和分段指標是否變化;這才是漂移證據。幾個問題也可能同時存在。
追問六:預訓練模型或大型語言模型會帶來什麼額外洩漏?
評測樣本或近重複內容可能已經出現在預訓練語料、檢索庫或提示範例中,傳統的本地 train/test 清單未必能看到這條路徑。可以使用時間上晚於訓練截止點、私有生成或經過近重複稽核的留出集,並記錄檢索索引和提示版本。無法證明預訓練語料完全無重合時,應把結果表述為受污染風險約束的估計,而不是絕對泛化能力。