
這次我們來看一類偏理論、但直接決定模型該怎么選的問題An Optimal Agnostic PAC Algorithm。如果你做機器學習理論、模型選擇或者想搞清楚“為什么 ERM經驗風險最小化在很多場景下夠用”這篇文章值得往下看。這里討論的不是某個需要 24G 顯存的大模型而是一套關于樣本復雜度最優的學習框架。它回答的問題很直接當標簽本身有噪聲、目標概念不一定落在我們的假設類里時我們要多少樣本才能保證學到的模型誤差不超過“類內最優誤差 ε”。這個標準叫 Agnostic PAC也就是不可知 PAC。本文會做四件事先講清楚 Agnostic PAC 和“最優”到底指什么再給出有限假設類和無限假設類下的樣本復雜度結論然后用 Python 寫一個可運行的 ERM 加聚合算法骨架最后給出一套驗證流程和常見坑位。全文不依賴 GPU單機 CPU 就能跑通適合理論學習、課程實驗和算法對比。1. 核心概念速覽維度說明問題設定不可知 PACAgnostic PAC學習學習目標以至少 1-δ 的概率輸出假設 h使 R(h) ≤ OPT εOPT 定義假設類 H 內的最小真實風險即 min R(h)不要求目標概念在 H 內核心對象假設類 H、樣本復雜度、ERM、聚合算法、VC 維最優含義樣本復雜度達到信息論下界常數意義下最優典型算法ERM、最小不一致假設、權重聚合、結構風險最小化運行環境Python 3.9NumPy / scikit-learnCPU 足夠適合場景模型選擇、理論驗證、帶噪標簽分類、算法對比實驗這個表里的每一項后面都會展開。第一步是把問題的定義理清楚。2. 不可知 PAC 學習要解決什么問題2.1 從標準 PAC 到不可知 PAC標準 PAC 學習有一個強假設存在一個目標概念 c且 c 一定在假設類 H 中。學習器的目標是輸出一個近似 c 的假設。這個設定在理論推導里很干凈但真實場景幾乎都不滿足標簽有噪聲、特征表達不完整、模型族選錯了目標概念根本不在我們枚舉的假設類里。Agnostic PAC 去掉了這個約束。它不要求目標概念屬于 H只要求輸出假設的風險接近 H 內最優假設的風險。真實風險定義為R(h) E_{(x,y)~D}[ 1{h(x) ≠ y} ]假設類 H 內的最優風險是OPT min_{h∈H} R(h)算法希望以至少 1-δ 的概率輸出 h滿足R(h) ≤ OPT ε這才是 Agnostic PAC 的核心目標。意味著即使數據存在不可消除的噪聲學習器也不比“假設類里最好的假設”差太多。2.2 “最優”是什么意思在計算學習理論里“最優算法”通常不是指某個具體代碼實現而是指樣本復雜度達到信息論下界。給定誤差 ε 和置信度 δ算法需要的最少樣本量如果能同時匹配上界和下界就稱它在樣本復雜度意義下最優。對于有限假設類 |H|下界是Ω((log|H| log(1/δ)) / ε2)在常數因子范圍內ERM 可以匹配這個下界所以它是統計意義上最優的。這里要區分兩個概念統計最優和計算最優。理論上最優的 ERM在實際計算中可能因為假設類復雜而 NP-hard。這也是后面引入聚合算法的原因之一用可計算的近似方式換取接近最優的統計保證。2.3 誤差分解近似誤差與估計誤差理解不可知學習要把總誤差拆成兩部分。近似誤差approximation error來自 H 本身不夠強即 OPT 不為 0。這不是算法能消除的只能靠擴大假設類解決。估計誤差estimation error來自有限樣本帶來的偏差即算法輸出的 h 與最優假設之間的差距。Agnostic PAC 的目標是控制估計誤差R(?) - OPT ≤ εERM 在有限樣本下做的事就是用經驗風險代替真實風險在假設類里找一個經驗風險最低的模型。只要樣本量足夠經驗風險會一致逼近真實風險估計誤差就會被壓到 ε 以內。3. 最優不可知 PAC 算法的理論框架3.1 有限假設類ERM 與 Union Bound先看最簡單的情況H 是有限集合比如 10 棵決策樹、5 個 SVM 變體一共 15 個候選模型。對每個 h∈H用 Hoeffding 不等式可以得到P(|R?(h) - R(h)| ε) ≤ 2exp(-2nε2)要讓所有 h 同時成立需要用 Union Bound 把所有假設的失敗概率加起來P(?h∈H, |R?(h) - R(h)| ε) ≤ 2|H|exp(-2nε2)令右側等于 δ可以反解出樣本復雜度n ≥ (log|H| log(2/δ)) / (2ε2)ERM 輸出經驗風險最低的假設 ?那么R(?) ≤ OPT 2ε把 ε 換成 ε/2就得到標準的 Agnostic PAC 上界。誤差里出現 log|H| 而不是 |H|說明假設類數量不要命只要候選模型數量是有限的ERM 的樣本復雜度就只隨 log|H| 增長。3.2 無限假設類VC 維與覆蓋數當 H 是無限集合時log|H| 沒有定義需要用 VC 維或覆蓋數來度量假設類的復雜度。VC 維刻畫的是 H 能打散的最大樣本數直觀理解是“假設類有多強的表達能力”。無限假設類下的樣本復雜度上界是n ≥ O((VC(H) log(1/δ)) / ε2)對應下界同樣包含 VC(H)因此 ERM 在無限假設類下也能達到最優量級。但如果 H 的 VC 維太大比如一個表達能力過強的深度網絡估計誤差會很大模型就過擬合了。這里引出一個實際建議不要盲目擴大假設類。Agnostic PAC 的最優性說的是“給定 H 時 ERM 最優”但 H 本身的復雜度同樣進入樣本復雜度。模型選擇要在近似誤差和估計誤差之間做權衡這就是結構風險最小化SRM的思路。3.3 聚合算法從在線學習到批量最優ERM 統計最優但計算可能困難。另一個方向是聚合算法不直接選一個假設而是給多個假設分配權重輸出加權投票結果。經典范式來自在線學習的 Hedge 算法。每個假設當作一個專家通過 multiplicative weights 更新權重最后用加權多數投票輸出。批處理版本需要在給定 n 個樣本時構造一個聚合分布其風險上界為R(agg) ≤ OPT O(sqrt((log|H|) / n))從量級看聚合算法和 ERM 一樣能達到 O(log|H| / n) 級別的估計誤差但常數因子會更大。好處是計算上更友好而且對“假設類里誰最優”這件事不需要提前知道。如果 H 是無限集合可以把聚合建立在覆蓋數上先用覆蓋數把 H 離散化為有限集合再在覆蓋集合上做聚合。這樣得到的算法仍然有可證明的樣本復雜度上界。4. 最小可運行的實驗環境準備這部分是實操。先準備環境本文所有實驗不依賴 GPU。依賴用途版本建議Python運行環境3.9 或更高NumPy數組與隨機數1.24 或更高scikit-learn分類模型、交叉驗證、評估1.3 或更高安裝命令pip install numpy scikit-learn如果想要復現更嚴謹的隨機種子建議同時固定 Python 的隨機數避免交叉驗證劃分不一致導致結果抖動。5. 實現一個基礎版最優不可知 PAC 算法這里實現一個“有限假設類上的 ERM 交叉驗證”骨架再加一個聚合版本。代碼是教學模板實際項目需要按自己的候選模型列表替換。5.1 候選假設類用 scikit-learn 自帶模型構造一個有限的假設類集合from sklearn.tree import DecisionTreeClassifier from sklearn.linear_model import LogisticRegression from sklearn.svm import SVC CANDIDATE_MODELS { tree_depth_1: DecisionTreeClassifier(max_depth1, random_state42), tree_depth_3: DecisionTreeClassifier(max_depth3, random_state42), logistic: LogisticRegression(max_iter1000), svm_rbf: SVC(C1.0, kernelrbf, probabilityTrue, random_state42), }這里故意放入不同復雜度的模型用來模擬一個常見的模型選擇場景。注意SVC的probabilityTrue是為了后面聚合時能輸出概率。5.2 最小經驗風險實現import numpy as np from sklearn.model_selection import KFold, cross_val_score def agnostic_erm(X, y, candidatesNone, cv_folds5, random_state42): ERM 交叉驗證選擇返回驗證誤差最小、再在全量數據上訓練的模型 candidates candidates or CANDIDATE_MODELS cv KFold(n_splitscv_folds, shuffleTrue, random_staterandom_state) best_model None best_score -np.inf scores {} for name, model in candidates.items(): fold_scores cross_val_score(model, X, y, cvcv, scoringaccuracy) mean_score fold_scores.mean() scores[name] mean_score if mean_score best_score: best_score mean_score best_model model.fit(X, y) return best_model, scores邏輯很簡單對每個候選假設用同一組 K 折劃分計算交叉驗證準確率取均值最高者再在全部訓練集上重新訓練。這與理論上“最小化經驗風險”的 ERM 略有差異但工程上更穩因為交叉驗證能減少一次劃分帶來的方差。5.3 加權聚合實現聚合版本不需要選一個模型而是讓所有候選模型投票。這里用 scikit-learn 的軟投票from sklearn.ensemble import VotingClassifier def agnostic_voting(X, y, candidatesNone, random_state42): 加權聚合對所有候選模型的概率做軟投票 candidates candidates or CANDIDATE_MODELS estimators list(candidates.items()) ensemble VotingClassifier(estimatorsestimators, votingsoft) ensemble.fit(X, y) return ensemble注意VotingClassifier默認每個模型權重相同。要接近理論上“根據經驗表現分配權重”的聚合需要手動構建權重或者用weights參數傳入交叉驗證準確率。一個簡單做法是先跑agnostic_erm拿到scores再把準確率歸一化后當作權重def agnostic_weighted_voting(X, y, candidatesNone, cv_folds5, random_state42): candidates candidates or CANDIDATE_MODELS _, scores agnostic_erm(X, y, candidates, cv_folds, random_state) weights np.array([scores[name] for name in candidates.keys()]) weights np.clip(weights, 1e-6, None) weights weights / weights.sum() estimators list(candidates.items()) ensemble VotingClassifier( estimatorsestimators, votingsoft, weightsweights ) ensemble.fit(X, y) return ensemble這段代碼的意義在于它把“選擇最優”改成了“按經驗權重聚合”對應理論里聚合算法的批處理版本。實際運行中它不一定比單個最優 ERM 更準但通常更穩定。6. 功能測試與效果驗證6.1 構造帶噪聲標簽的合成數據為了驗證算法在“不可知”設定下的表現用make_classification生成一組帶標簽翻轉的合成數據from sklearn.datasets import make_classification from sklearn.model_selection import train_test_split X, y make_classification( n_samples2000, n_features8, n_informative6, n_redundant2, flip_y0.2, random_state0 ) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42 )flip_y0.2表示有約 20% 的標簽被隨機翻轉。在這個合成數據里即使假設類再強真實風險也降不到 0所以這是一個典型的 agnostic 場景。6.2 驗證 ERM 在有限假設類上的行為運行 ERM 選擇model, scores agnostic_erm(X_train, y_train) print(候選模型交叉驗證準確率, scores) print(測試集準確率, model.score(X_test, y_test))預期結果是不同候選模型的交叉驗證準確率有明顯差異ERM 會選擇交叉驗證得分最高的模型。判斷成功的標準是測試集準確率與交叉驗證得分差異不大。如果差異過大優先懷疑數據劃分泄漏、樣本量不足或假設類過擬合。6.3 觀察樣本量對泛化誤差的影響這是重點驗證樣本復雜度增長帶來的誤差下降趨勢。用不同規模的訓練集重復實驗sample_sizes [100, 300, 500, 1000, 2000] for n in sample_sizes: subset_X, _, subset_y, _ train_test_split( X, y, train_sizen, random_state0, stratifyy ) model, scores agnostic_erm(subset_X, subset_y) test_acc model.score(X_test, y_test) print(fn{n}, test_acc{test_acc:.4f})不需要預設具體數字但通常會觀察到樣本量從 100 漲到 1000 時測試準確率明顯上升再往后上升變緩。這個趨勢與不可知 PAC 的樣本復雜度 O(log|H| / ε2) 一致誤差減半所需的樣本量大致按平方增長。6.4 對比 ERM 與聚合再對比一下“選擇最優”和“加權聚合”erm_model, _ agnostic_erm(X_train, y_train) vote_model agnostic_weighted_voting(X_train, y_train) print(ERM 測試準確率, erm_model.score(X_test, y_test)) print(聚合測試準確率, vote_model.score(X_test, y_test))單次實驗里結果可能互有勝負更嚴謹的做法是多次換隨機種子跑然后比較均值和方差。聚合的優勢通常體現在方差上少數幾次實驗里不明顯。判斷實驗是否成功的標準很明確ERM 選中的模型至少不能顯著差于隨機選擇聚合模型在多次重復中不應出現極端壞結果。如果 ERM 選出來的模型測試準確率反而最低說明交叉驗證劃分或候選模型集合配置有問題。7. 接口設計與批量任務上面的函數已經具備接口雛形。實際工程里可以把算法封裝成統一入口def agnostic_pac_fit(X, y, modeerm, candidatesNone, cv_folds5, random_state42): if mode erm: return agnostic_erm(X, y, candidates, cv_folds, random_state) if mode voting: return agnostic_weighted_voting(X, y, candidates, cv_folds, random_state) raise ValueError(funknown mode: {mode})批量任務可以這樣組織把不同的樣本量、噪聲比例、候選模型列表寫成一個配置循環執行并記錄結果。results [] configs [ {n_samples: 500, flip_y: 0.1, mode: erm}, {n_samples: 500, flip_y: 0.2, mode: erm}, {n_samples: 1000, flip_y: 0.2, mode: voting}, ] for cfg in configs: X, y make_classification( n_samplescfg[n_samples], n_features8, n_informative6, n_redundant2, flip_ycfg[flip_y], random_state0 ) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, random_state42 ) if cfg[mode] erm: model, scores agnostic_pac_fit(X_train, y_train, modeerm) else: model agnostic_pac_fit(X_train, y_train, modevoting) results.append({ **cfg, test_acc: model.score(X_test, y_test), }) print(results)跑批量任務時建議加日志和失敗重試。比如某個候選模型在特定數據上不收斂應該捕獲異常并跳過而不是讓整個實驗中斷。8. 資源占用與性能觀察這一節不涉及顯存但同樣需要關注資源。Agnostic PAC 算法的計算開銷主要由三部分構成開銷來源影響因素降低方式交叉驗證訓練候選模型數量 × 折數減少候選模型、減少折數、并行計算模型擬合樣本量、特征維度降采樣、特征篩選聚合預測候選模型數量剪枝、權重稀疏化可以這樣粗略估算如果候選模型有 10 個K 折是 5那么一次函數調用最多觸發 50 次訓練實際還有一次全量訓練。幾百到幾千條樣本、8 個特征時訓練通常在秒級完成具體耗時以本機測試為準。觀察訓練耗時可以用簡單的時間戳import time start time.perf_counter() model, scores agnostic_erm(X_train, y_train) elapsed time.perf_counter() - start print(f訓練耗時{elapsed:.3f}s)內存占用方面這種規模的數據集不會構成壓力。特征維度上升到幾萬、候選模型變成隨機森林或核 SVM 時才需要關注內存。常規手段是限制候選模型規模、使用線性模型做快速篩選、或者對特征做 PCA 降維。9. 常見問題與排查方法問題現象可能原因排查方式解決方案交叉驗證結果波動大折數太少、樣本不均衡、隨機種子不同打印每折得分增大折數、使用分層采樣、固定隨機種子訓練很慢候選模型復雜、樣本量大統計每輪耗時降采樣、減少候選模型、并行訓練ERM 選出的模型在測試集上很差假設類過擬合、交叉驗證泄漏對比訓練集與測試集準確率降低模型復雜度、使用結構風險最小化驗證準確率和測試準確率差距大數據分布不一致、劃分不隨機檢查數據切分邏輯使用分層 train_test_split、避免時間泄漏聚合結果不如單個最優模型聚合權重分配不合理打印各候選模型得分與權重按交叉驗證準確率歸一化權重某些候選模型訓練報錯數據特征不適合該模型單獨測試該模型捕獲異常、跳過失敗模型增加樣本后準確率不再提升近似誤差占主導觀察 OPT 是否遠大于 0擴大假設類或增加特征表達其中最容易踩的坑是交叉驗證泄漏如果先在全量數據上做特征縮放再劃分訓練集和測試集驗證結果會虛高。本文實驗沒有做特征縮放所以不涉及這個問題。如果你用自己的數據務必把預處理放進交叉驗證循環內部。10. 最佳實踐與使用建議先在小樣本、低噪聲數據上跑通 ERM確認候選假設類、交叉驗證、評估流程都正常再進入正式實驗。固定隨機種子。Agnostic PAC 的結論是概率性的單次實驗不能說明問題多次重復取均值才有意義。候選假設類從小到大逐步加。先放兩個簡單模型確認代碼無誤再引入復雜模型。把數據集、候選模型、交叉驗證折數、隨機種子、測試準確率記錄成表。批量實驗尤其要留日志。聚合不一定總贏過 ERM但更穩。如果只關心“選一個模型上線”用 ERM如果關心穩定性用加權聚合。當假設類本身很強但樣本不足時優先考慮減少模型復雜度而不是繼續加候選模型。樣本復雜度隨 VC 維增長。11. 總結與下一步An Optimal Agnostic PAC Algorithm 的核心結論可以濃縮成一句話在不可知設定下ERM 已經達到樣本復雜度的最優量級而聚合算法提供了一種計算上更穩的近似實現。它不是某個現成模型而是一種判斷“算法好不好”的標準。如果只驗證一個功能建議先跑通第 6 節的樣本量實驗親眼看一下誤差隨樣本量的變化曲線。最值得踩的坑是交叉驗證泄漏一定要在劃分之后再做任何預處理。下一步可以看兩個方向一是從有限假設類擴展到無限假設類理解 VC 維和覆蓋數如何替代 log|H|二是把在線學習的聚合算法改寫成批處理版本重新推導權重更新過程和風險上界。這套框架理解到位之后再去看深度學習里的模型選擇、早停和正則化會有完全不同的視角。