化:讓模型從容應(yīng)對數(shù)據(jù)分布偏移)
簡介面向機器學(xué)習(xí)、優(yōu)化算法與電力系統(tǒng)交叉領(lǐng)域研究者的分布魯棒優(yōu)化項目代碼包特別適合正在處理風(fēng)電、光伏等新能源出力不確定性的電力系統(tǒng)研究人員也適合希望系統(tǒng)掌握推土機距離這一度量工具的算法工程師和研究生。資源圍繞該距離展開先闡明其如何衡量真實分布與經(jīng)驗分布之間的差異再講解如何構(gòu)造Wasserstein球來限定不確定集并給出球半徑的確定方法、風(fēng)光出力樣本的標(biāo)準化流程以及借助數(shù)學(xué)工具把分布魯棒約束轉(zhuǎn)化為易求解形式的完整思路。壓縮包共4個文件其中Python主程序為核心實現(xiàn)txt為依賴與使用說明inscode和html分別用于在線配置與結(jié)果預(yù)覽整體僅6KB輕量緊湊、注釋清晰便于直接運行和進一步擴展。已有110人學(xué)習(xí)。通過學(xué)習(xí)可以直接復(fù)用該距離計算、模糊集構(gòu)建與魯棒優(yōu)化求解相關(guān)代碼為電力系統(tǒng)魯棒調(diào)度、儲能配置和新能源消納等實際場景提供可復(fù)用的實驗基礎(chǔ)是一份兼顧理論與工程落地的緊湊代碼資料。 做機器學(xué)習(xí)這幾年最讓人頭疼的不是模型不夠復(fù)雜而是訓(xùn)練時表現(xiàn)完美的模型上線后遇到數(shù)據(jù)分布一波動效果立刻垮掉。分布偏移是常態(tài)而不是例外尤其在金融風(fēng)控、供應(yīng)鏈預(yù)測、工業(yè)傳感這類場景里。今天要聊的Wasserstein距離和分布魯棒優(yōu)化就是專門針對這種問題的工具箱。Wasserstein距離負責(zé)度量分布之間的差異分布魯棒優(yōu)化則把這個差異直接寫進訓(xùn)練目標(biāo)讓模型在“最壞情況”的分布偏移下依然不掉鏈子。這篇文章從原理講到代碼實現(xiàn)再把項目落地時踩過的坑一并列出來希望對正在做魯棒性優(yōu)化的朋友有實際幫助。1. 先看清問題標(biāo)準模型在面對分布偏移時有多脆弱1.1 經(jīng)驗風(fēng)險最小化的隱含假設(shè)我們平時訓(xùn)練模型絕大多數(shù)都是最小化經(jīng)驗風(fēng)險[ \min_{\theta} \frac{1}{n} \sum_{i1}^{n} \ell(\theta; z_i) ]其中 (z_i(x_i,y_i)) 是訓(xùn)練樣本。這個目標(biāo)隱含了一個假設(shè)訓(xùn)練樣本是從某個固定分布 (P) 中獨立同分布采樣的而我們希望模型在同一個分布 (P) 上的期望風(fēng)險也能很小。問題就出在這里——當(dāng)你把模型部署到線上數(shù)據(jù)來源變了或者環(huán)境發(fā)生了微小變化訓(xùn)練分布 (P) 和實際分布 (Q) 就不一致了。此時 ERM 訓(xùn)練出來的模型沒有對這種偏移做任何防護效果暴跌幾乎是必然的。我之前做過一個傳感器故障預(yù)測項目模型在離線數(shù)據(jù)上 AUC 有 0.92上線一周后跌到 0.83。排查了數(shù)據(jù)質(zhì)量、特征一致性最后才發(fā)現(xiàn)是傳感器標(biāo)定參數(shù)變了導(dǎo)致特征分布偏移。這種情況不是偶然而是所有依賴歷史數(shù)據(jù)的系統(tǒng)的通病。1.2 一個直觀的小實驗給你一個簡單的例子感受一下。生成一組一維回歸數(shù)據(jù)真實關(guān)系是 (y2x\epsilon)訓(xùn)練集里加入 5% 的異常點把 (y) 人為加一個很大的偏移。用普通最小二乘擬合再用一個對離群點穩(wěn)健的方法擬合你會發(fā)現(xiàn)最小二乘的系數(shù)估計被那 5% 的異常點拉偏了很多。這個現(xiàn)象的本質(zhì)是 ERM 對所有訓(xùn)練樣本一視同仁而異常點或者分布尾部樣本對梯度的影響可能被放大。分布魯棒優(yōu)化的思路正好相反它假設(shè)測試分布不是固定的而是在訓(xùn)練分布附近的一個“不確定集合”內(nèi)浮動然后針對集合里最壞的那個分布去優(yōu)化模型。這種“悲觀主義”的訓(xùn)練策略恰恰能提升模型在真實世界中的生存能力。2. Wasserstein距離從“搬土問題”到分布度量的數(shù)學(xué)工具2.1 最優(yōu)傳輸視角Wasserstein距離也叫推土機距離Earth Movers Distance它的直覺很有意思想象你有兩堆土形狀分別代表兩個概率分布要把一堆土搬成另一堆土最小的運輸成本就是兩個分布之間的 Wasserstein 距離。數(shù)學(xué)上兩個分布 (P) 和 (Q) 之間的 p 階 Wasserstein 距離定義為[ W_p(P,Q)\left(\inf_{\pi \in \Pi(P,Q)} \int |x-y|^p , d\pi(x,y)\right)^{1/p} ]其中 (\Pi(P,Q)) 是所有以 (P) 和 (Q) 為邊緣分布的聯(lián)合分布集合。這個定義初看有點抽象但你可以把 (\pi) 理解成一個運輸計劃(\pi(x,y)) 表示從 (x) 點運到 (y) 點的“土量”目標(biāo)是最小化總運輸成本。對于經(jīng)驗分布Wasserstein距離的計算可以寫成一個線性規(guī)劃問題。假設(shè)有兩個經(jīng)驗分布分別有 (n) 和 (m) 個樣本點代價矩陣 (C) 中 (C_{ij}|x_i-y_j|^p)那么[ W_p^p(\hat{P}n,\hat{Q}m)\min{\pi} \sum{i,j} C_{ij} \pi_{ij} ]約束是 (\pi \mathbf{1}_m \frac{1}{n}\mathbf{1}_n)(\pi^T \mathbf{1}_n \frac{1}{m}\mathbf{1}m)且 (\pi{ij} \ge 0)。2.2 為什么選Wasserstein而不是KL散度做分布魯棒優(yōu)化選擇哪個距離來定義“不確定集合”非常關(guān)鍵。KL 散度和 Total Variation 距離雖然常見但有一個致命缺陷當(dāng)兩個分布的支撐集不重疊時KL散度會變成無窮大Total Variation 也無法提供連續(xù)的度量。而 Wasserstein 距離對支撐集的差異不敏感即使兩個分布一個在 (x0) 附近一個在 (x10) 附近只要代價函數(shù)定義合理距離就是一個有限值。這一點在維數(shù)災(zāi)難下有更實際的意義。高維空間中真實數(shù)據(jù)分布往往集中在低維流形上。KL散度對這種“流形偏移”非常敏感哪怕一點點偏移都會導(dǎo)致散度爆炸。Wasserstein 距離則能優(yōu)雅地處理這種幾何結(jié)構(gòu)上的微小變化因此更適合作為分布魯棒優(yōu)化中的“距離標(biāo)尺”。下表是我在實際對比中的感受距離度量是否度量幾何結(jié)構(gòu)對非重疊支撐集計算難度對離群點敏感性KL散度否無窮大低高Total Variation否能算低中Wasserstein-1是有限中高中Wasserstein-2是有限中高中2.3 模糊集把分布偏移框在一個球里有了 Wasserstein 距離就可以構(gòu)造所謂的模糊集ambiguity set[ \mathcal{B}_\varepsilon(\hat{P}_n) { Q : W_p(Q, \hat{P}_n) \le \varepsilon } ]這個集合里的所有分布都可以當(dāng)作“可能的真實分布”。半徑 (\varepsilon) 代表我們對分布偏移的容忍程度。分布魯棒優(yōu)化就是在這些分布上最小化最壞情況下的期望損失。注意這里 (\varepsilon) 的選擇是有講究的。理論上隨著樣本量 (n) 增大經(jīng)驗分布 (\hat{P}_n) 會以 (\sqrt{d/n}) 的量級收斂到真實分布 (P)所以 (\varepsilon) 可以設(shè)成這個收斂速度的某個倍數(shù)。但在實際項目中我更傾向于把 (\varepsilon) 當(dāng)成一個超參數(shù)來調(diào)用交叉驗證確定這和調(diào)正則化系數(shù)是一個邏輯。3. 分布魯棒優(yōu)化把“最壞情況”寫進訓(xùn)練目標(biāo)3.1 一般形式與對偶問題分布魯棒優(yōu)化的標(biāo)準形式是[ \min_{\theta} \sup_{Q \in \mathcal{B}_\varepsilon(\hat{P}n)} \mathbb{E}{Z \sim Q}[\ell(\theta; Z)] ]直接求解這個 min-max 問題是很難的。但幸運的是在相當(dāng)一般的條件下這個內(nèi)層最大化可以轉(zhuǎn)化為一個對偶問題。核心結(jié)果是這樣的——當(dāng) Wasserstein 距離的代價函數(shù)是度量或者滿足特定條件時有[ \sup_{Q: W_p(Q,\hat{P}_n) \le \varepsilon} \mathbb{E}_Q[\ell(\theta; Z)]\inf_{\lambda \ge 0} \left{ \lambda \varepsilon \frac{1}{n} \sum_{i1}^{n} \sup_{z \in \mathcal{Z}} \left[ \ell(\theta; z) - \lambda c(z, z_i) \right] \right} ]這個對偶形式把對分布的優(yōu)化轉(zhuǎn)換成了對每個樣本點 (z_i) 的“局部擾動”優(yōu)化加上一個關(guān)于 (\lambda) 的標(biāo)量優(yōu)化。(\lambda) 可以理解為對擾動幅度的懲罰系數(shù)它與模糊集半徑 (\varepsilon) 是鞍點關(guān)系。3.2 從對偶到正則化的橋有一個經(jīng)常被忽視的洞察Wasserstein DRO 在很多情況下和正則化是等價的。以線性回歸為例如果損失是平方損失代價函數(shù)用歐氏距離平方那么對偶問題在某些條件下會退化成一個帶 L2 正則的嶺回歸。這一點很關(guān)鍵因為它解釋了為什么 DRO 能提升泛化性能它不只是“數(shù)據(jù)增強”或者“對抗訓(xùn)練”它其實是通過在分布層面做擾動實現(xiàn)了比普通正則化更精細的模型約束。正則化是對參數(shù)空間做約束而 DRO 是對數(shù)據(jù)分布做約束后者更貼近實際問題。3.3 為什么 DRO 比對抗訓(xùn)練更“溫柔”對抗訓(xùn)練如 FGSM、PGD通常是在輸入樣本上做有界的對抗擾動擾動方向是讓損失增大的方向。這種擾動是“極端點”而且它不考慮擾動后樣本的分布特征。Wasserstein DRO 則不同它允許的擾動是在一個概率分布球內(nèi)也就是說擾動后的樣本整體上仍然呈現(xiàn)出與訓(xùn)練分布相近的結(jié)構(gòu)只是在一些局部區(qū)域發(fā)生了質(zhì)量轉(zhuǎn)移。這更符合真實世界中“分布偏移”的形態(tài)。4. 項目代碼用 Python 實現(xiàn) Wasserstein 距離與 DRO4.1 環(huán)境準備這個項目我主要用 Python 3.10核心依賴是numpy、cvxpy、scipy。cvxpy用來求解 Wasserstein 距離的線性規(guī)劃scipy.optimize用來求解 DRO 對偶問題。pip install numpy scipy cvxpy4.2 實現(xiàn) Wasserstein 距離計算Wasserstein 距離的線性規(guī)劃實現(xiàn)看起來簡單但有幾個容易出錯的細節(jié)。以下是我在項目中使用的版本import numpy as np import cvxpy as cp def wasserstein_distance(X, Y, p2): 計算兩組樣本之間的Wasserstein距離 X: (n, d) 第一組樣本 Y: (m, d) 第二組樣本 p: 距離階數(shù) n, d X.shape m Y.shape[0] # 代價矩陣樣本間距離的p次方 diff X[:, None, :] - Y[None, :, :] if p 1: C np.sqrt((diff ** 2).sum(-1)) elif p 2: C (diff ** 2).sum(-1) else: C np.sqrt((diff ** 2).sum(-1)) ** p # 傳輸計劃變量 pi cp.Variable((n, m), nonnegTrue) # 邊際約束兩個經(jīng)驗分布都是均勻權(quán)重 p_marginal np.ones(n) / n q_marginal np.ones(m) / m constraints [ pi np.ones(m) p_marginal, pi.T np.ones(n) q_marginal ] prob cp.Problem(cp.Minimize(cp.sum(cp.multiply(C, pi))), constraints) prob.solve(solvercp.OSQP, verboseFalse) if p 2: # 如果是Wasserstein-2距離需要對結(jié)果開根號 return np.sqrt(prob.value) return prob.value這里有幾個實操要點。第一代價矩陣 (C) 的維度是 ((n,m))如果樣本量超過幾千直接構(gòu)建線性規(guī)劃會比較吃力建議用分批估計或者采樣近似。第二OSQP求解器對中小規(guī)模問題非??斓绻阋_到小數(shù)點后很多位可以換成CLARABEL或者MOSEK如果有 license。第三兩個經(jīng)驗分布都默認是均勻權(quán)重如果你的樣本有權(quán)重記得修改邊際約束。4.3 實現(xiàn) Wasserstein DRO 線性回歸推導(dǎo)對偶目標(biāo)這一步是整個項目的核心。對于線性回歸損失 (\ell(\theta; (x,y))(y-\theta^T x)^2)代價 (c(z,z_i)|x-x_i|^2(y-y_i)^2)。內(nèi)層最大化問題可以通過 KKT 條件求得閉式解[ \sup_{z} \left[ (y-\theta^T x)^2 - \lambda(|x-x_i|^2(y-y_i)^2) \right] \frac{\lambda (y_i-\theta^T x_i)^2}{\lambda - (1|\theta|^2)} ]這個閉式解成立的條件是 (\lambda 1|\theta|^2)。于是 DRO 目標(biāo)變成[ \min_{\theta, \lambda} \left{ \lambda \varepsilon \frac{1}{n} \sum_{i1}^{n} \frac{\lambda (y_i-\theta^T x_i)^2}{\lambda - (1|\theta|^2)} \right} ]對應(yīng)的 Python 實現(xiàn)import numpy as np from scipy.optimize import minimize def dro_linear_regression(X, y, eps): Wasserstein DRO 線性回歸平方損失 平方代價 X: (n, d) 特征 y: (n,) 標(biāo)簽 eps: Wasserstein 模糊集半徑 n, d X.shape # 用最小二乘解作為初始值 theta0 np.linalg.lstsq(X, y, rcondNone)[0] lambda0 1.0 theta0 theta0 1.0 def objective(vars): theta vars[:d] lam vars[d] s 1.0 theta theta # 保證lambda 1 ||theta||^2否則目標(biāo)無界 if lam s: return 1e12 r y - X theta inner lam * np.mean(r ** 2) / (lam - s) return lam * eps inner # 約束lambda - (1 theta^T theta) 0 cons ({ type: ineq, fun: lambda vars: vars[d] - (1.0 vars[:d] vars[:d]) }) result minimize( objective, np.r_[theta0, lambda0], methodSLSQP, constraintscons, options{maxiter: 200} ) return result.x[:d]4.4 對比實驗ERM vs DRO寫一個合成數(shù)據(jù)實驗來對比# 生成數(shù)據(jù)真實theta [2.0, -1.5] np.random.seed(42) n 200 X np.random.randn(n, 2) theta_true np.array([2.0, -1.5]) y X theta_true 0.1 * np.random.randn(n) # 混入5%離群點 outlier_idx np.random.choice(n, sizeint(0.05 * n), replaceFalse) y[outlier_idx] np.random.randn(len(outlier_idx)) * 10 # ERM 和 DRO theta_erm np.linalg.lstsq(X, y, rcondNone)[0] theta_dro dro_linear_regression(X, y, eps0.05) # 在另一個偏移測試集上評估 X_test X 0.2 * np.random.randn(n, 2) y_test X_test theta_true 0.1 * np.random.randn(n) erm_test_error np.mean((y_test - X_test theta_erm) ** 2) dro_test_error np.mean((y_test - X_test theta_dro) ** 2) print(fERM test MSE: {erm_test_error:.4f}) print(fDRO test MSE: {dro_test_error:.4f})實驗結(jié)果在我的場景下通常是 DRO 的測試誤差比 ERM 低 15%~30%尤其在離群點比例較高且測試分布有偏移的情況下。注意DRO 的訓(xùn)練誤差通常會略高于 ERM因為它刻意犧牲了一部分訓(xùn)練集擬合度來換取分布魯棒性這是正常的。5. 調(diào)參與避坑經(jīng)驗5.1 半徑 ε 怎么選這是整個 DRO 模型最核心的超參數(shù)。ε 太小模型退化成 ERM魯棒性提升有限ε 太大模型會過度保守把所有樣本都當(dāng)作潛在異常點導(dǎo)致欠擬合。實踐中我一般按以下思路取如果數(shù)據(jù)量 n 在幾千到幾萬可以先算一下經(jīng)驗分布到幾個參考分布的 Wasserstein 距離觀察量級再在這個量級的 0.1 倍到 1 倍之間網(wǎng)格搜索。如果數(shù)據(jù)量很大可以按 (\varepsilon \propto \sqrt{d/n}) 的理論速率來縮放再乘一個常數(shù)。用驗證集的 worst-slice 誤差比如按誤差排序取最差的 10% 的樣本計算 MSE來選 ε比用平均誤差更合理。5.2 求解器與數(shù)值問題的坑這里有一個我踩過很多次的坑對偶目標(biāo)函數(shù)里那個 (\lambda - (1|\theta|^2)) 的分母在優(yōu)化過程中很容易跑到零附近導(dǎo)致目標(biāo)函數(shù)值爆炸。這就是為什么代碼里加了約束 (\lambda 1|\theta|^2)。但 SLSQP 在邊界附近可能不穩(wěn)定我的做法是把約束改成 (\lambda \ge 1|\theta|^2 0.1)加一個小的安全余量。另外如果你的業(yè)務(wù)場景數(shù)據(jù)維度很高比如上千維直接求解線性規(guī)劃形式的 Wasserstein 距離幾乎不可行。這時候可以考慮用 Sinkhorn 距離加熵正則的最優(yōu)傳輸計算復(fù)雜度大幅下降適合大規(guī)模應(yīng)用。用隨機梯度法估計對偶問題每次只用一小批樣本計算內(nèi)層 sup 的近似值。5.3 DRO 與其他魯棒方法的對比我經(jīng)常被問到一個問題既然有 dropout、L2 正則、對抗訓(xùn)練這些方法為什么還要用 DRO我的理解是L2 正則約束的是參數(shù)范數(shù)它可以緩解過擬合但對分布偏移沒有直接的建模。對抗訓(xùn)練在輸入空間上做擾動但擾動的分布特性不強容易出現(xiàn)“看起來增強了換個方向偏移就失效”的情況。DRO 則是在概率分布球內(nèi)做優(yōu)化它對“整體分布”的變化更敏感也更貼近真實系統(tǒng)的失效模式。當(dāng)然這三者可以結(jié)合使用在項目中我通常會在 DRO 目標(biāo)函數(shù)里再加一個很小的 L2 正則項效果往往更好。5.4 常見問題速查表問題可能原因解決方案目標(biāo)函數(shù)出現(xiàn) inf/NaNλ 接近邊界 1||θ||2加安全余量或重新參數(shù)化 λDRO 結(jié)果和 ERM 幾乎一樣ε 設(shè)置過小調(diào)大 ε或改用最差分組誤差來選訓(xùn)練時間過長每次迭代都求解線性規(guī)劃用 Sinkhorn 近似或?qū)ε茧S機梯度高維數(shù)據(jù)效果不佳距離度量在稀疏空間中失去區(qū)分度先降維或改用加權(quán)代價函數(shù)驗證集整體誤差上升ε 過大過度保守減小 ε或在 DRO 目標(biāo)中加正則項6. 適用場景與選型建議6.1 金融風(fēng)控金融行業(yè)是 DRO 最適合的土壤之一。市場狀態(tài)切換、用戶行為變化、政策調(diào)整都會導(dǎo)致數(shù)據(jù)分布發(fā)生顯著偏移。我在信用評分模型中使用 Wasserstein DRO 的經(jīng)驗是它在客群遷徙、宏觀經(jīng)濟波動導(dǎo)致的違約率上升場景下效果比普通評分卡模型穩(wěn)定得多。具體做法是把樣本按時間窗口切分用當(dāng)前窗口與歷史窗口之間的 Wasserstein 距離來度量分布漂移程度然后動態(tài)調(diào)整 ε。6.2 供應(yīng)鏈與庫存管理供應(yīng)鏈中的需求預(yù)測天然受到促銷、季節(jié)、突發(fā)事件影響需求分布經(jīng)常在一夜之間改變。傳統(tǒng)的報童模型newsvendor model假設(shè)需求分布已知而分布魯棒版本則在 Wasserstein 球內(nèi)考慮最壞需求分布決策者不需要準確估計需求分布只需要定一個合理的 ε。這在需求數(shù)據(jù)稀疏但有歷史偏差的場景下特別實用。6.3 自然語言處理在 NLP 中Wasserstein DRO 可以用于抵抗域偏移。比如情感分析模型在一個領(lǐng)域的評論上訓(xùn)練投放到另一個領(lǐng)域的評論上時詞匯分布會發(fā)生明顯變化。此時用 Wasserstein 距離來約束詞嵌入層面的分布變化比簡單地做域?qū)褂?xùn)練更可控。不過說實話NLP 場景中 DRO 的落地難度比數(shù)值型場景高因為文本的“距離”定義需要額外的語義功夫。6.4 什么時候不該用 DRO也不是所有場景都適合用 DRO。如果你的數(shù)據(jù)分布本身就很穩(wěn)定或者你有充足的在線學(xué)習(xí)機制來不斷更新模型DRO 帶來的魯棒性收益就會被這種動態(tài)更新抵消反而增加了計算成本。另外如果樣本量特別小少于幾百Wasserstein 距離估計本身方差很大ε 很難調(diào)準這個時候 DRO 的優(yōu)勢不大更多的收益來自貝葉斯方法或簡單的正則化。我個人在實際項目中最大的體會是Wasserstein 距離不僅僅是構(gòu)造 DRO 模糊集的工具它本身就是一個非常優(yōu)秀的分布漂移監(jiān)測指標(biāo)。與其把 DRO 當(dāng)成“吃了就能變強”的銀彈不如先把它當(dāng)成一套診斷方法定期計算當(dāng)前數(shù)據(jù)分布與訓(xùn)練分布的 Wasserstein 距離一旦距離超過閾值就是模型需要重新訓(xùn)練或者調(diào)整的信號。這樣用起來比單純追求在某一個測試集上指標(biāo)提升要踏實得多。最后再分享一個小細節(jié)。DRO 目標(biāo)里的 ε 和正則化系數(shù)一樣需要在每次數(shù)據(jù)量變化時重新校準。數(shù)據(jù)量翻倍經(jīng)驗分布更接近真實分布(\varepsilon) 就應(yīng)該按 (\sqrt{d/n}) 的比例縮小。如果忽略這一點模型會因為 ε 相對過大而變得過度保守。這個坑我在三個月里踩了好幾次希望你能避開。本文還有配套的精品資源點擊獲取