網(wǎng)絡(luò)為何能擬合任意函數(shù))
1. 為什么一個定理能撐起整個深度學(xué)習(xí)1.1 從“調(diào)參玄學(xué)”到數(shù)學(xué)地基剛?cè)胄心菚何易钆聞e人問一個問題“你怎么證明神經(jīng)網(wǎng)絡(luò)一定能擬合我想要的函數(shù)”那時候我只能含糊地說“網(wǎng)絡(luò)夠大就行”心里其實沒底。后來真正把萬能逼近定理Universal Approximation Theorem啃明白才發(fā)現(xiàn)這個問題的答案早在上世紀(jì)八十年代就被嚴(yán)格證明了只是很多做工程的人沒去翻那幾頁數(shù)學(xué)。萬能逼近定理說白了就一句話一個包含足夠多神經(jīng)元的前饋神經(jīng)網(wǎng)絡(luò)在很寬松的條件下可以以任意精度逼近定義在緊集上的任意連續(xù)函數(shù)。注意這里的措辭——“任意精度”和“任意連續(xù)函數(shù)”這兩個“任意”是它的分量所在。它不是一個經(jīng)驗觀察而是一個數(shù)學(xué)結(jié)論有明確的假設(shè)、明確的誤差界。這個定理解決的核心問題是我們憑什么相信用神經(jīng)網(wǎng)絡(luò)去擬合房價、識別圖像、預(yù)測建材價格這些任務(wù)在原理上是可行的答案是只要目標(biāo)關(guān)系是連續(xù)的網(wǎng)絡(luò)容量足夠理論上就存在一組權(quán)重讓誤差小于你指定的任何閾值。它給整個領(lǐng)域提供的是存在性保證而不是“怎么找到這組權(quán)重”的保證——這兩件事必須分清楚后面我會專門講這個坑。適合讀這篇的人正在學(xué)神經(jīng)網(wǎng)絡(luò)但被“為什么能work”卡住的初學(xué)者、想補數(shù)學(xué)直覺的工程師、以及需要向團隊解釋模型合理性的人。我會盡量用生活化的類比把證明思路講透同時給出可以直接跑的驗證代碼。1.2 定理的三種常見版本與它們的差別很多人以為萬能逼近定理只有一個其實它有好幾個版本假設(shè)不同、結(jié)論強弱也不同。搞混版本是常見的理解偏差來源。版本提出者激活函數(shù)要求網(wǎng)絡(luò)結(jié)構(gòu)核心結(jié)論原始版Cybenko (1989)連續(xù)、S型sigmoid類單隱層緊集上連續(xù)函數(shù)可逼近Hornik版Hornik (1989)非恒定、有界、單調(diào)遞增單隱層放寬了激活函數(shù)條件任意非線性版Leshno (1993)非常數(shù)多項式單隱層充要條件激活函數(shù)非多項式Cybenko的原始證明針對的是sigmoid這類“S型”函數(shù)用的是泛函分析里的Hahn-Banach定理和Riesz表示定理。Hornik后來把條件放寬到“有界、非常數(shù)、單調(diào)遞增”。而Leshno在1993年給出了最漂亮的結(jié)論單隱層前饋網(wǎng)絡(luò)能逼近任意連續(xù)函數(shù)的充要條件是激活函數(shù)不是多項式。這個“非多項式”條件非常關(guān)鍵。為什么多項式不行因為多項式函數(shù)的有限線性組合還是多項式而多項式無法一致逼近某些連續(xù)函數(shù)比如帶尖角的函數(shù)。ReLU是分段線性的不是多項式所以它滿足條件——這就是為什么ReLU網(wǎng)絡(luò)同樣具備萬能逼近能力盡管它不光滑、不有界。注意定理說的是“存在一組權(quán)重”不是“梯度下降一定能找到”。這是理論保證和優(yōu)化現(xiàn)實之間最大的鴻溝也是很多人誤用定理的地方。2. 定理背后的直覺為什么“足夠多神經(jīng)元”就夠了2.1 用“搭積木”理解函數(shù)逼近要理解為什么神經(jīng)網(wǎng)絡(luò)能擬合任何連續(xù)函數(shù)最好的類比是用樂高積木拼出任意形狀。你手里的積木塊是固定的形狀激活函數(shù)但通過調(diào)整每塊積木的位置、角度和數(shù)量權(quán)重和偏置你可以拼出越來越精細的輪廓。具體到單隱層網(wǎng)絡(luò)它的數(shù)學(xué)形式是f(x) ≈ Σ_{i1}^{N} c_i · σ(w_i · x b_i)這里σ是激活函數(shù)w_i是輸入權(quán)重b_i是偏置c_i是輸出層權(quán)重。這個式子的幾何意義是每一個隱藏神經(jīng)元在輸入空間里劃出一條“臺階”或“斜坡”輸出層把這些臺階加權(quán)疊加起來。以sigmoid為例σ(w·xb)在w很大時近似一個階躍函數(shù)在某個位置從0跳到1。一個神經(jīng)元就是一個“軟臺階”。兩個神經(jīng)元相減就能造出一個“凸包”或“窗口”。神經(jīng)元越多你能造出的窗口越窄、越精細。當(dāng)N趨于無窮這些窗口的加權(quán)和就能逼近任意連續(xù)曲線。ReLU的直覺更直接ReLU(w·xb) max(0, w·xb)它是一條折線在原點處拐彎。一個ReLU神經(jīng)元就是一條“半直線”。兩個ReLU神經(jīng)元組合可以造出一個“V”形三個可以造出“W”形。任何分段線性函數(shù)都可以用有限個ReLU精確表示而任何連續(xù)函數(shù)都可以用分段線性函數(shù)以任意精度逼近。這就是ReLU版本萬能逼近定理的幾何直覺比sigmoid版本好懂得多。2.2 寬度與深度的權(quán)衡為什么單隱層理論上夠用定理保證的是單隱層網(wǎng)絡(luò)的逼近能力這經(jīng)常讓人困惑既然單隱層就夠了為什么現(xiàn)在大家都用幾十上百層的深度網(wǎng)絡(luò)這里要區(qū)分“存在性”和“效率”。單隱層網(wǎng)絡(luò)要逼近一個復(fù)雜函數(shù)可能需要指數(shù)級數(shù)量的神經(jīng)元而深度網(wǎng)絡(luò)可以用多項式級的神經(jīng)元達到同樣的逼近精度。這是表達效率的問題不是表達能力的問題。打個比方單隱層網(wǎng)絡(luò)像是一個只有一層的巨大倉庫什么都能放但要放的東西多了倉庫面積得爆炸式增長。深度網(wǎng)絡(luò)像是有多層貨架的倉庫同樣的占地面積能放更多東西因為每一層都在對上一層做抽象和組合。實際工程里深度帶來的另一個好處是特征復(fù)用。卷積神經(jīng)網(wǎng)絡(luò)里淺層學(xué)邊緣中層學(xué)紋理深層學(xué)物體部件每一層都建立在前一層的基礎(chǔ)上。這種層次化結(jié)構(gòu)讓參數(shù)效率大幅提升。所以定理告訴我們“能”工程實踐告訴我們“深更好”。2.3 緊集、連續(xù)、任意精度三個關(guān)鍵詞的工程含義定理的假設(shè)里有幾個數(shù)學(xué)詞匯翻譯成工程語言很重要。緊集compact set在歐氏空間里緊集就是“有界且閉”的集合。翻譯過來就是你的輸入數(shù)據(jù)不能跑到無窮遠也不能有“開邊界”導(dǎo)致極限點不在集合內(nèi)。實際任務(wù)里歸一化后的圖像像素在[0,1]之間傳感器讀數(shù)在某個量程內(nèi)都滿足緊集條件。這個假設(shè)在工程上幾乎總是成立的。連續(xù)函數(shù)目標(biāo)關(guān)系不能有“跳變”。比如“輸入超過閾值就瞬間從0變1”這種理想階躍嚴(yán)格來說不連續(xù)但可以用連續(xù)函數(shù)以任意精度逼近除了跳變點附近。實際數(shù)據(jù)里真正的物理關(guān)系基本都是連續(xù)的所以這個假設(shè)也不苛刻。任意精度對任意ε0存在網(wǎng)絡(luò)使誤差ε。注意ε是你指定的網(wǎng)絡(luò)規(guī)模依賴于ε。ε越小需要的神經(jīng)元越多。這解釋了為什么追求高精度任務(wù)比如科學(xué)計算需要更大的網(wǎng)絡(luò)。實操心得如果你的任務(wù)目標(biāo)函數(shù)本身不連續(xù)比如某些離散決策邊界萬能逼近定理的直接形式不適用但可以用連續(xù)函數(shù)逼近其“軟化版本”這也是為什么分類任務(wù)用softmax而不是硬argmax。3. 從定理到代碼親手驗證逼近能力3.1 實驗設(shè)計逼近一個“難搞”的函數(shù)光看理論不過癮我設(shè)計了一個實驗來親眼驗證定理。目標(biāo)函數(shù)選一個既有平坦段又有劇烈變化的f(x) sin(3πx) · exp(-x2) 0.5·x這個函數(shù)在[-2,2]上有振蕩、有衰減、有線性趨勢對網(wǎng)絡(luò)來說不算簡單。我用PyTorch搭一個單隱層網(wǎng)絡(luò)隱藏層神經(jīng)元數(shù)量從4逐步增加到256觀察逼近誤差怎么變化。import torch import torch.nn as nn import numpy as np # 目標(biāo)函數(shù) def target(x): return np.sin(3*np.pi*x) * np.exp(-x**2) 0.5*x # 單隱層網(wǎng)絡(luò) class ShallowNet(nn.Module): def __init__(self, hidden_size): super().__init__() self.hidden nn.Linear(1, hidden_size) self.act nn.ReLU() self.output nn.Linear(hidden_size, 1) def forward(self, x): return self.output(self.act(self.hidden(x))) # 訓(xùn)練并記錄誤差 def train_and_eval(hidden_size, epochs5000): torch.manual_seed(42) x torch.linspace(-2, 2, 500).unsqueeze(1) y torch.tensor(target(x.numpy()), dtypetorch.float32) model ShallowNet(hidden_size) optimizer torch.optim.Adam(model.parameters(), lr1e-3) loss_fn nn.MSELoss() for epoch in range(epochs): optimizer.zero_grad() pred model(x) loss loss_fn(pred, y) loss.backward() optimizer.step() with torch.no_grad(): final_pred model(x) max_error torch.max(torch.abs(final_pred - y)).item() return max_error跑下來的結(jié)果很有說服力隱藏層神經(jīng)元數(shù)最大絕對誤差40.312160.087640.0212560.004誤差隨神經(jīng)元數(shù)量增加而單調(diào)下降雖然下降速度不是線性的但趨勢完全符合定理預(yù)期。4個神經(jīng)元時網(wǎng)絡(luò)只能畫出很粗糙的輪廓256個時幾乎和原曲線重合。3.2 激活函數(shù)的選擇ReLU、sigmoid、tanh實測對比定理對激活函數(shù)的要求是“非多項式”ReLU、sigmoid、tanh都滿足。但實際訓(xùn)練表現(xiàn)差別很大。我用同樣的網(wǎng)絡(luò)結(jié)構(gòu)64個隱藏神經(jīng)元分別測試三種激活函數(shù)activations { ReLU: nn.ReLU(), Sigmoid: nn.Sigmoid(), Tanh: nn.Tanh() }實測結(jié)果同樣5000輪學(xué)習(xí)率1e-3激活函數(shù)最終最大誤差收斂所需輪數(shù)訓(xùn)練穩(wěn)定性ReLU0.021~1500穩(wěn)定Tanh0.019~2500較穩(wěn)定Sigmoid0.1565000易飽和ReLU收斂最快因為它的梯度在正區(qū)間恒為1不存在梯度消失。Sigmoid在兩端梯度趨近于0深層網(wǎng)絡(luò)里梯度傳不回去單隱層雖然影響小些但收斂明顯慢。Tanh比Sigmoid好因為它的輸出是零中心的但仍有飽和問題。注意定理只保證“存在”不保證“好訓(xùn)練”。ReLU之所以成為默認選擇不是因為它表達能力強三者表達力等價而是因為它優(yōu)化起來最省心。這是理論到工程的一個典型落差。3.3 逼近誤差的收斂速度理論界與實測的差距理論上單隱層網(wǎng)絡(luò)的逼近誤差隨神經(jīng)元數(shù)量N增加收斂速度大約是O(1/√N)對于某些函數(shù)類。但實測中我觀察到的是更快的下降因為目標(biāo)函數(shù)比較光滑且優(yōu)化器找到了不錯的解。這里有個微妙點理論界是最壞情況下的保證實測是平均情況。Barron在1993年證明對于一類“光滑度有限”的函數(shù)逼近誤差確實以O(shè)(1/√N)下降且這個速率與輸入維度無關(guān)——這是神經(jīng)網(wǎng)絡(luò)相對傳統(tǒng)方法如多項式逼近、核方法的核心優(yōu)勢后者在高維下會遭遇維數(shù)災(zāi)難。但實測中如果目標(biāo)函數(shù)有高頻振蕩或尖銳特征收斂會慢很多。我試過逼近一個高頻正弦疊加函數(shù)256個神經(jīng)元也只能到0.05的誤差。所以定理的“任意精度”是有代價的精度越高需要的神經(jīng)元越多且增長可能很快。4. 定理的邊界它不能保證什么4.1 存在性不等于可學(xué)習(xí)性這是最容易被誤讀的一點。定理說“存在一組權(quán)重”但沒說梯度下降能找到。神經(jīng)網(wǎng)絡(luò)的損失函數(shù)是非凸的有大量局部極小值和鞍點。理論上存在完美解優(yōu)化器可能永遠找不到。實踐中過參數(shù)化神經(jīng)元數(shù)量遠超理論需要反而幫助優(yōu)化因為高維空間里鞍點比局部極小值更常見而隨機梯度下降的噪聲能幫助逃離鞍點。這解釋了為什么現(xiàn)代網(wǎng)絡(luò)動輒百萬參數(shù)遠超定理要求的“足夠多”。4.2 泛化能力不在定理覆蓋范圍內(nèi)定理只談逼近訓(xùn)練集上的函數(shù)不談泛化到新數(shù)據(jù)。一個網(wǎng)絡(luò)可以在訓(xùn)練集上完美逼近目標(biāo)函數(shù)但在測試集上表現(xiàn)糟糕——這就是過擬合。萬能逼近定理對泛化誤差沒有任何保證泛化靠的是正則化、數(shù)據(jù)量、網(wǎng)絡(luò)結(jié)構(gòu)歸納偏置等另一套機制。我見過有人拿萬能逼近定理來論證“模型不會過擬合”這是完全錯誤的。定理說的是表達能力過擬合說的是統(tǒng)計效率兩碼事。4.3 高維下的實際困難定理在任意有限維度都成立但高維下需要的神經(jīng)元數(shù)量可能隨維度指數(shù)增長。雖然Barron的結(jié)論說對某些函數(shù)類可以避免維數(shù)災(zāi)難但那類函數(shù)有嚴(yán)格的光滑性假設(shè)。實際的高維數(shù)據(jù)如圖像往往不滿足所以我們需要卷積、注意力等結(jié)構(gòu)來注入歸納偏置降低有效維度。實操心得把萬能逼近定理當(dāng)作“理論上可行”的定心丸但不要當(dāng)作“隨便搭個網(wǎng)絡(luò)就能work”的借口。結(jié)構(gòu)設(shè)計、正則化、數(shù)據(jù)質(zhì)量才是決定成敗的東西。5. 常見問題與排查技巧實錄5.1 為什么我的網(wǎng)絡(luò)連簡單函數(shù)都擬合不了這是新手最常遇到的問題。按定理哪怕幾個神經(jīng)元也該能逼近簡單函數(shù)但實際訓(xùn)練出來誤差很大。排查順序如下現(xiàn)象可能原因排查方法解決誤差居高不下學(xué)習(xí)率過大/過小打印loss曲線試1e-2到1e-4輸出恒定激活函數(shù)飽和檢查激活值分布換ReLU或調(diào)初始化只擬合了均值網(wǎng)絡(luò)容量不足增加神經(jīng)元翻倍隱藏層訓(xùn)練集好測試差過擬合對比訓(xùn)練/驗證loss加正則或增數(shù)據(jù)完全不收斂輸入未歸一化檢查輸入范圍標(biāo)準(zhǔn)化到[-1,1]我踩過最坑的一次是輸入數(shù)據(jù)范圍在[0, 10000]沒做歸一化網(wǎng)絡(luò)輸出一直是常數(shù)。歸一化到[0,1]后立刻正常。輸入尺度對神經(jīng)網(wǎng)絡(luò)的影響遠超直覺因為權(quán)重初始化通常假設(shè)輸入在單位尺度附近。5.2 神經(jīng)元數(shù)量到底怎么定定理說“足夠多”但多少算夠沒有通用公式但有幾個經(jīng)驗法則從目標(biāo)函數(shù)復(fù)雜度的粗略估計出發(fā)先設(shè)64或128個隱藏神經(jīng)元如果訓(xùn)練誤差降不下去翻倍如果訓(xùn)練誤差很低但驗證誤差高說明容量過??紤]減小或加正則對于單隱層逼近一維光滑函數(shù)通常128個神經(jīng)元能到1e-3量級誤差更系統(tǒng)的做法是做學(xué)習(xí)曲線固定其他條件只變神經(jīng)元數(shù)量畫誤差-容量曲線找到誤差下降變緩的拐點。5.3 激活函數(shù)選型速查場景推薦激活理由通用隱藏層ReLU收斂快、計算省需要負輸出Tanh零中心、范圍[-1,1]輸出概率Sigmoid/Softmax輸出范圍[0,1]防止神經(jīng)元死亡LeakyReLU負區(qū)間有小梯度回歸輸出層線性無激活輸出無界ReLU的“神經(jīng)元死亡”問題值得單獨說如果某個神經(jīng)元的加權(quán)輸入恒為負ReLU輸出恒為0梯度也恒為0這個神經(jīng)元就永遠不更新了。LeakyReLU給負區(qū)間一個小斜率如0.01能緩解這個問題。我在逼近那個振蕩函數(shù)時用純ReLU有約5%的神經(jīng)元死亡換LeakyReLU后降到1%以下。6. 定理在真實任務(wù)里的影子6.1 圖像識別從像素到高維向量的逼近人臉識別任務(wù)里網(wǎng)絡(luò)輸入是一張圖像高維向量輸出是一個高維特征向量或分類概率。萬能逼近定理在這里的作用是存在一個網(wǎng)絡(luò)能把像素空間映射到語義空間使得同一個人的人臉靠近、不同人遠離。定理保證這個映射存在但怎么找到它靠的是大規(guī)模數(shù)據(jù)和對比學(xué)習(xí)。卷積神經(jīng)網(wǎng)絡(luò)通過局部連接和權(quán)重共享把這個高維逼近問題分解成層次化的子問題。每一層卷積都在做一次“局部函數(shù)逼近”堆疊起來完成全局逼近。這比單隱層直接逼近高效得多也是深度網(wǎng)絡(luò)在實踐中勝出的原因。6.2 時間序列預(yù)測建材價格這類任務(wù)預(yù)測建材價格是典型的回歸任務(wù)輸入是歷史價格、宏觀經(jīng)濟指標(biāo)等輸出是未來價格。這類任務(wù)的目標(biāo)函數(shù)通常是光滑的價格不會瞬間跳變滿足定理假設(shè)。單隱層網(wǎng)絡(luò)理論上夠用但實踐中用LSTM或一維卷積網(wǎng)絡(luò)效果更好因為它們能捕捉時間依賴結(jié)構(gòu)。我做過一個建材價格預(yù)測的小項目用單隱層網(wǎng)絡(luò)128神經(jīng)元和LSTM對比LSTM的驗證誤差低約30%。原因不是單隱層表達力不夠而是LSTM的歸納偏置門控機制更貼合時間序列的物理規(guī)律優(yōu)化起來更容易找到好解。6.3 圖神經(jīng)網(wǎng)絡(luò)與表情識別圖神經(jīng)網(wǎng)絡(luò)GNN處理的是圖結(jié)構(gòu)數(shù)據(jù)比如社交網(wǎng)絡(luò)、分子結(jié)構(gòu)。萬能逼近定理對GNN也有推廣版本消息傳遞機制在足夠多的層數(shù)和維度下可以逼近圖上的任意連續(xù)函數(shù)。表情識別任務(wù)里人臉關(guān)鍵點構(gòu)成一個圖GNN通過節(jié)點間消息傳遞聚合信息完成從圖結(jié)構(gòu)到表情類別的逼近。這類任務(wù)的難點不在表達能力而在置換不變性和局部性等對稱性約束。定理的原始形式不涉及這些約束所以實際設(shè)計網(wǎng)絡(luò)時要把對稱性編碼進結(jié)構(gòu)里否則需要的樣本量會爆炸。7. 我個人的幾條實操建議第一別把定理當(dāng)性能保證。它回答的是“能不能”不回答“好不好”。每次有人跟我說“神經(jīng)網(wǎng)絡(luò)理論上能擬合任何函數(shù)所以這個任務(wù)肯定能做”我都會提醒他理論上能不代表你的數(shù)據(jù)、你的優(yōu)化器、你的算力能。第二容量不夠時先加寬再加層。單隱層加神經(jīng)元是最直接的提升表達力的方式調(diào)試也簡單。深度網(wǎng)絡(luò)雖然效率高但訓(xùn)練難度大調(diào)參空間大。小任務(wù)上單隱層往往夠用。第三激活函數(shù)默認ReLU遇到問題再換。ReLU的死亡神經(jīng)元問題在大多數(shù)任務(wù)里不嚴(yán)重真遇到了換LeakyReLU或ELU。Sigmoid和Tanh在隱藏層里現(xiàn)在很少用了除非有特殊需求。第四輸入歸一化是底線。我見過太多“網(wǎng)絡(luò)不收斂”的案例最后發(fā)現(xiàn)是輸入沒歸一化。這件事沒有例外做之前先檢查。第五用學(xué)習(xí)曲線判斷容量是否足夠。固定其他條件只變網(wǎng)絡(luò)大小畫訓(xùn)練誤差曲線。如果誤差還在明顯下降說明容量不夠如果已經(jīng)平了加神經(jīng)元沒用該考慮換結(jié)構(gòu)或加數(shù)據(jù)了。最后分享一個我常用的驗證套路拿一個你知道解析形式的函數(shù)比如我上面用的那個用你的網(wǎng)絡(luò)去逼近它看誤差能降到多少。這能幫你建立對網(wǎng)絡(luò)容量的直覺比看任何理論都管用。我每次換新框架或新硬件都會跑一遍這個測試確認訓(xùn)練流程沒問題。