§01學習重點
- 分辨【觀察】【假說】【理論】【已削弱】【未決】五種證據等級,往後讀到任何關於深度學習的解釋時,先追問它屬於哪一級
- 說出本章兩個謎題各自「意外」在哪裡:最壞情況的理論預告與日常訓練經驗之間的落差,以及完美擬合訓練集之後居然還能泛化
- 用「必要條件」與「有幫助」的區分,複述隨機性、顯式正則化、資料的良善結構為什麼被排除出「訓練成功的必要條件」名單
- 親手重現三個實驗:用全批次梯度下降擬合隨機標籤、對損失地景做兩種直線切片、對訓練完的網路做迭代剪枝
- 解釋「從起點到解的直線上損失一路下降」為什麼推不出「損失面是凸的」
- 說出平坦極小假說的支持與反對證據各兩條,並親手示範尖銳度的度量如何被重新參數化憑空改動
- 區分「訓練需要冗餘」「部署需要冗餘」「一開始就能省」三件事,並用剪枝實驗說明前兩件都推不出第三件
§02課程內容
一、先把意外立起來:兩個謎題與一套標記
這一章跟前面十九章都不一樣,開始之前得把話說明白。前面每一章交付的都是一套機制:折線怎麼拼出形狀、梯度怎麼傳、注意力怎麼打分。本章沒有機制可交付,因為它要講的是領域到今天還不知道為什麼的事。第 1 章結尾埋過一句話:表達力強的模型不難設計,難的是表達力強而且好搜——這兩件事同時成立是深度學習能用的根本原因,也是留給本章的謎。現在到了兌現的時候,而最誠實的兌現方式是:把「哪些觀察需要解釋、目前有哪幾種說法、各自的證據與反例」攤開給你看,並且把「知道」與「猜測」畫清界線。
為了畫清這條界線,本章立一套標記,掛在關鍵句的句尾:【觀察】=可重現的實驗事實,你自己跑一遍也會看到;【假說】=候選解釋,有證據支持但未定案;【理論】=數學上證明了,但證明所需的假設與實務相距很遠;【已削弱】=有明確反證的說法;【未決】=連候選答案都還在吵。讀本章時請盯著這些標記——把假說當成定論,是這個題目最常見的講錯方式,本章寧可多掛幾個標記,也不把話說死。
意外有兩個,分開立。
謎題一:訓練不該這麼順。 深度網路的損失對參數不是凸的,第 6 章分析過:非凸地景上梯度為零的點可以是極小、極大或鞍點,純下坡只保證你停在起點所屬的那一個。計算複雜度理論還補了一刀:一般的非凸最佳化屬於它分類裡最難的那一族(NP-困難,NP-hard)【理論】。但這個詞要小心讀——它是對最壞情況的陳述,意思是「存在某些問題實例,能讓任何演算法都跑不完」,不是「你手上這一個實例一定跑不動」。真正的謎在落差:理論給的是最壞情況的警告,而日常經驗是深度網路幾乎總是訓練得起來【觀察】——第 6 章末尾就承認過,理論分析預告災難、實作卻大致相安無事,並且把已知線索留給本章整理。所以要解釋的不是「為什麼理論錯了」(它沒錯),而是「為什麼我們天天碰到的實例都不是壞實例」。
謎題二:泛化不該這麼好。 第 8 章你已經親眼看過雙下降:模型容量大到把訓練誤差壓到零之後,測試誤差還能再降一次【觀察】。把這件事放回背景看才知道它多奇怪。第 8 章量過高維空間有多空曠——維度夠高時,最近的鄰居跟最遠的點幾乎一樣遠;第 4 章數過深度網路能切出的線性區域數隨深度指數成長。把兩者拼起來:想像一個中等規模的網路,它能把輸入空間切出天文數字級的區域,而訓練資料只有幾萬筆——絕大多數區域從頭到尾沒有任何一筆資料經過,模型在那些區域的行為完全沒被訓練過問,憑什麼表現得體?
這裡需要一個貫穿全章的概念:剩餘自由度。假設你為一座橋建一個健康監測模型,參數有二十萬個,手上的量測快照只有一萬兩千筆。就算每筆資料都「用掉」一個參數去記住它,還剩下十八萬八千個參數沒有任何資料管——這些就是剩餘自由度。現代深度學習的常態是參數量配到資料量的許多倍,這個狀態叫過參數化(over-parameterization,有些文獻寫成「過度參數化」,同一件事)。要先把第 8 章破過的誤解再破一次:過參數化不是過擬合(overfitting)的同義詞——前者說的是參數數量對資料數量的比例,後者說的是測試表現變差這個結果,雙下降曲線的右半段就是「過參數化而不過擬合」的活例子。順帶一提,連「實務上的大模型到底算不算過參數化」都有爭議【未決】:資料增強會把一筆資料變出許多變體,有效資料量因此難以估算,比例的分母本身就是筆糊塗帳。
這兩個謎題在領域裡由兩群人分頭研究——最佳化理論管謎題一,學習理論管謎題二——本章也按這個分工走:第二、三節處理訓練,第四節處理泛化,第五節問一個收尾的問題:這些多出來的參數,是必要的嗎?
最後交代本章例子的世界。本章所有例子都種在橋樑工程裡,特別是它的冗餘設計傳統:一座桁架橋(truss bridge)的桿件數往往超過靜力平衡所需,安全係數(factor of safety)刻意配到遠超計算需求。你會看到,這個「多配料」的工程哲學跟過參數化之間有一條意外貼合的對應線——也有一處根本的不對應,那一處正是本章的主題。
二、謎題一的排查:訓練為什麼成得了
先把一個用語釘好,不然後面每句話都會被誤讀。本章跟著領域慣例,把「訓練損失達到最低可能值」的解都叫全域極小——通常這代表把訓練資料全部擬合。這是寬鬆用法:它不問「是不是唯一最低點」,只問「有沒有低到底」。你馬上會看到,在過參數化的網路裡,這種解根本不是一個點,而是一整個巨大的家族,所以「唯一」從一開始就不是對的問法。
接著排查。訓練幾乎總是成功,總有個原因。把候選解釋當嫌疑人一個個過堂,是整理這批文獻最清楚的辦法——下面的判定各自對應可重現的實驗,其中最關鍵的一組,你自己現在就能跑。
假設一座桁架橋上裝了 8 個應變感測器,每小時存一筆 8 維快照。取 40 筆快照,但標籤不用任何真實量測——用丟銅板隨機指定 0 或 1,跟輸入毫無關係。然後用一個兩層網路去擬合它,而且刻意把嫌疑人一個個支開:全批次梯度下降(沒有隨機性)、不加任何正則項、標籤裡沒有任何可學的結構:
import numpy as np
rng = np.random.default_rng(0)
# 假設一座桁架橋上裝了 8 個應變感測器,每小時存一筆 8 維快照。
# 取 40 筆快照,標籤用丟銅板隨機指定——與量測內容毫無關係。
I, D_in, D_h = 40, 8, 50
X = rng.normal(0, 1, (I, D_in))
y = rng.integers(0, 2, I).astype(float) # 隨機標籤
W1 = rng.normal(0, np.sqrt(2 / D_in), (D_h, D_in))
b1 = np.zeros(D_h)
v = rng.normal(0, np.sqrt(2 / D_h), D_h)
b0 = 0.0
n_param = W1.size + b1.size + v.size + 1
print(f"參數 {n_param} 個,標籤 {I} 筆")
for step in range(4001):
z = X @ W1.T + b1 # 預活化
h = np.maximum(0, z) # ReLU
p = 1 / (1 + np.exp(-(h @ v + b0))) # 輸出機率
L = -np.mean(y * np.log(p + 1e-12) + (1 - y) * np.log(1 - p + 1e-12))
g = (p - y) / I # 全批次:無任何隨機性
gv, gb0 = h.T @ g, g.sum()
gh = np.outer(g, v) * (z > 0)
gW1, gb1 = gh.T @ X, gh.sum(axis=0)
W1 -= 0.5 * gW1; b1 -= 0.5 * gb1
v -= 0.5 * gv; b0 -= 0.5 * gb0
if step % 800 == 0:
err = int(((p > 0.5) != y).sum())
print(f"step {step:4d} loss={L:.4f} 錯分 {err}/40")實跑輸出:參數 501 個、標籤 40 筆;第 0 步損失 0.8513、錯分 19/40,到第 800 步損失已是 0.0024、錯分 0/40,之後一路降到 0.0003。一個沒有隨機性、沒有正則化的流程,把 40 個純粹亂給的標籤背得一字不差。這一段小程式同時削弱了三個嫌疑人:
訓練演算法的隨機性【已削弱】。 第 6 章講過批次雜訊能把參數從鞍點附近推開,聽起來像成功的關鍵。但上面用的是全批次——完全確定性的流程照樣擬合成功;把批次開到極大、幾乎消除隨機性的大規模實驗也得到同樣結論【觀察】。注意判定的措辭:「已削弱」削掉的是「隨機性是必要條件」這句話,不是「隨機性沒有幫助」——雜訊照樣可能加速訓練、影響挑到哪個解(第四節回頭談)。排除一個嫌疑人的不在場證明,跟證明他從沒幫過忙,是兩回事。這個邏輯區分適用於下面每一條。
顯式正則化【已削弱】。 上面一行懲罰項都沒加。第 9 章說過平方懲罰的係數是相對權重、不是開關;這裡更進一步——擬合本身根本不需要它。至於演算法自帶的隱式偏好(第 9 章的隱式正則化),它確實排除不掉,但有一個方向上的矛盾值得記下:理論分析顯示這種隱式懲罰的強度隨學習率上升,可是沒有人觀察到「學習率越大、訓練越容易成功」這回事——隱式正則化大概參與了挑解,但拿它解釋「為什麼訓練得起來」對不上帳【觀察】。
資料本身的良善結構【已削弱】。 標籤是丟銅板來的,輸入是純雜訊,網路照樣背下來了。把真實資料動過手腳再餵給大網路的著名實驗系列得到同樣結論(出處見章末原書對照)。所以「真實世界的資料剛好特別好學」不能是訓練成功的必要條件——連不好學的它都學得動。
剩下的嫌疑人各有不同下場。初始化【部分成立】:第 7 章整章講的就是初始尺度配錯時梯度會指數爆炸或消失,那個層面的精細選擇確實必要;但在避開數值災難之上再把初始尺度放大,實驗顯示多半只是拖慢收斂,不改變「最後擬合得成」的結局【觀察】(作業二會請你在小例子上驗這件事,你會看到玩具實驗跟這句話的關係沒那麼單純)。活化函數的形狀【有影響】:只在一小段輸入範圍內有變化的活化函數很難訓練——近乎常數的區段給不出梯度,第 7 章「死掉的 ReLU」是同一個機制的極端案例。深度本身【未決】:把爆炸與消失這些數值問題排除之後,深度到底讓損失地景變好走還是變難走,沒有決定性證據;「越深收斂越快」的觀察存在,但解讀不只一種。
排到最後,板子上只剩一個嫌疑人站得住:過參數化本身。它的直覺是這樣的:參數遠多於資料時,把訓練損失壓到底的解不是孤立的點,而是一整個連續的巨大家族【觀察】——第 3 章早就給過線索:光是把 \(D\) 個隱藏單元重新編號就有 \(D!\) 種排法,全部給出同一個函數,這還沒算上連續的縮放自由度。家族大到某個程度,就出現一個誘人的圖像:不管你站在參數空間的哪裡,幾乎總有某個方向還能往下走——維度多到讓「四面八方全是上坡」這件事變得極難發生【假說】。理論這邊也有呼應:在參數充分多的極限下,可以證明所有駐點都是全域極小【理論】;網路夠寬時,壞的局部極小罕見、局部極小的損失隨深寬增加逼近全域極小【理論】。但誠實的話必須跟著說:這些定理要求的寬度遠超任何實務網路,理論目前還接不住實證,兩邊隔著一條沒人跨過去的溝。另外還有一個提醒別把話說滿的反例:參數不多於資料時,訓練偶爾也能成功【觀察】,一種解讀是訓練樣本之間本有冗餘、有效的資料量比字面少【假說】。
比喻: 桁架橋有一類設計叫靜不定(statically indeterminate)結構:桿件數超過靜力平衡所需。這種橋在施工時有一個好脾氣的性質——某根桿件的尺寸差了一點、某個節點的角度偏了一點,力會自動重新分配到其餘桿件上,整體照樣成立;桿件配得剛剛好的靜定結構就沒這個餘裕,每一根都錯不得。過參數化的網路像前者:四十筆資料、五百零一個參數,某個參數卡在不利的值,總有別的參數能繞路把損失繼續往下扛——「幾乎總有方向可下降」的直覺就是這個畫面。但這個比喻在最要緊的一點上失準:桿件拆掉一根之後力怎麼重新分配,靜力學算得出來、答案唯一,工程師是知道為什麼才敢這樣設計;「總有方向可下降」在深度網路上只是實證觀察加上假設離譜的定理,沒有人能對真實規模的網路證明它。工程的冗餘有理論撐腰,深度學習的冗餘沒有——這個反差不是比喻的瑕疵,它就是本章存在的理由。
三、把地景實際量一量:兌現第 6 章的債
第 2 章留過一個問題:走下坡停住的地方是不是全域最低、這件事重不重要。第 6 章把「局部極小與鞍點究竟造成多大麻煩」明文推遲到本章。這一節就是來還這兩筆債的——用的不是推導,是實測:把訓練完的網路擺上檯面,對它的損失地景做各種切片與統計,看看那片沒人畫過地圖的高維地形實際長什麼樣。
先數清楚「同一個谷底有多少種長相」。把訓練損失壓到底的解至少有三類系統性的複製來源,每一類都掛回你學過的章節【觀察】:隱藏單元重新編號的置換對稱(第 3 章的 \(D!\) 種排法);活化函數前後成對縮放的對稱——第 3 章示範過,把進入 ReLU 的權重乘上 \(\alpha\)、出來的權重除以 \(\alpha\),函數一個字都不變;帶正規化層的網路還多一層冗餘——統計量被重新標定後,前一層的尺度怎麼調都會被抵消(第 11 章批次正規化的直接後果)。除了這些「函數完全相同」的複製,還有一族更鬆的等價解:在每個訓練資料點上行為一致、在資料點之間各走各路【觀察】——過參數化讓「穿過同樣四十個點」的曲線有無窮多條。第 2 章那個問題的前半段到這裡有了答案:停住的地方是不是「那個」全域最低,這個問法本身就錯了,因為最低處是一整片家族;該問的是你停的地方好不好,而那是第四節的事。
再看駐點的品質。對訓練過程中經過的駐點做統計,有一個乾淨的規律:損失越低的駐點,周圍往下彎的方向占比越少【觀察】。「彎」在這裡指的是:站在梯度為零的點上,沿某個方向看損失面是向上凹還是向下凹——向下凹代表那個方向還有得降。這個規律撐起一個圖像:低損失處的駐點幾乎都是真極小,高損失處的駐點幾乎都是鞍點【假說】。更進一步,有人主張在夠大的網路上壞的局部極小可能根本不存在【假說】——注意是「可能沒有」,不是「證明沒有」,證據是間接的:全批次、固定小學習率、隨機標籤這種最容易卡住的組合,損失照樣降到零。
於是第 6 章那筆債可以還了。鞍點的實務殺傷力,最誠實的總結是:會拖慢、會騙人、但不構成死路。 拖慢——鞍點附近平坦,梯度小、步子小,參數會在那裡磨蹭很多步;騙人——第 6 章的「假收斂」,損失曲線躺平讓你誤判訓練結束;但死路——實證上罕見,上面那個「最容易卡的組合都卡不死」的觀察就是證據。第 6 章教你「收斂了不代表到底了」,本章補上另一半:實務上你停下來的地方,多半真的是低損失家族的一員,只是你永遠拿不到保證書。
軌跡本身還藏著更意外的性質。下面這個實驗你可以自己跑:訓練同一個小網路兩次(只換初始值),然後對地景做兩種直線切片。假設量測的是一座人行橋——注意是人行橋,不載車——荷載位置 \(x\) 從橋頭(0)走到橋尾(1),量跨中撓度 \(y\)(公釐),拿 26 筆量測訓練一個 tanh 小網路:
import numpy as np
rng = np.random.default_rng(0)
# 假設量測一座人行橋:荷載位置 x(0=橋頭、1=橋尾)→ 跨中撓度 y(公釐)
x = np.linspace(0.02, 0.98, 26)
y = 4.0 * x * (1 - x) + 0.25 * np.sin(7.9 * x) + rng.normal(0, 0.03, x.size)
D_h = 24 # 參數共 3*24+1 = 73 個
def loss(phi):
w, b = phi[:D_h], phi[D_h:2*D_h]
v, b0 = phi[2*D_h:3*D_h], phi[3*D_h]
h = np.tanh(np.outer(x, w) + b)
return float(np.mean((h @ v + b0 - y) ** 2))
def train(seed, steps=20000, lr=0.05):
r = np.random.default_rng(seed)
phi = r.normal(0, 0.5, 3 * D_h + 1)
start = phi.copy()
for _ in range(steps):
w, b = phi[:D_h], phi[D_h:2*D_h]
v, b0 = phi[2*D_h:3*D_h], phi[3*D_h]
z = np.outer(x, w) + b
h = np.tanh(z)
e = 2 * (h @ v + b0 - y) / x.size # 殘差項
gh = np.outer(e, v) * (1 - h ** 2) # 反傳過 tanh
g = np.concatenate([gh.T @ x, gh.sum(0), h.T @ e, [e.sum()]])
phi -= lr * g
return start, phi
startA, endA = train(seed=1)
_, endB = train(seed=2)
print(f"解 A 損失={loss(endA):.5f} 解 B 損失={loss(endB):.5f}")
ts = np.linspace(0, 1, 11)
sliceA = [loss((1 - t) * startA + t * endA) for t in ts] # 起點→解 A
sliceAB = [loss((1 - t) * endA + t * endB) for t in ts] # 解 A→解 B
print("起點→解A:", " ".join(f"{v:.3f}" for v in sliceA))
print("解A→解B :", " ".join(f"{v:.3f}" for v in sliceAB))切片走的是參數空間裡的直線:
逐項拆解:\(\boldsymbol\phi_{\text{甲}}\) 與 \(\boldsymbol\phi_{\text{乙}}\) 是兩組完整的參數向量(73 個數字一整包);\(t\) 是走的比例,0 代表整包停在甲、1 代表整包走到乙、0.5 代表每個參數各取兩邊的平均;把每個 \(t\) 對應的參數丟回損失函數 \(\mathcal{L}\)(整批平均損失,記法同第 5、6 章),就得到這條直線上的損失剖面。
實跑輸出:解 A 與解 B 的損失都在 0.003 附近——兩次訓練找到的解一樣好,這跟第 6 章說的日常經驗一致:換一組隨機種子重跑,停下來的損失往往落在差不多的水準【觀察】。但兩條切片的形狀天差地遠。起點到解 A 的直線上,損失是 1.801 → 1.441 → 1.111 → 0.826 → 0.591 → 0.401 → 0.252 → 0.141 → 0.064 → 0.018 → 0.003——一路下降,連一個小凸起都沒有【觀察】。解 A 到解 B 的直線上,損失是 0.003 → 0.114 → 0.389 → 0.726 → 1.013 → 1.149 → 1.071 → 0.790 → 0.413 → 0.110 → 0.003——中間立著一道高牆,峰頂 1.149 是兩端的近四百倍。
第一條切片是文獻裡反覆重現的觀察:從初始點到最終解的直線上,損失常常近乎單調下降【觀察】。第一次看到的人幾乎都會冒出同一個念頭:「這地景該不會其實是凸的吧?」打住——這是本章最危險的一步過度推論。 一條弦上單調下降,跟整個面是凸的,是兩件不同的事;作業一會請你親手造出一個明明白白非凸、卻能找出單調下降弦的反例。正確的讀法保守得多:真實訓練走的那一帶地形,比最壞情況的想像溫和【觀察】。
第二條切片的高牆則告訴你:不同訓練找到的解不在同一個坑裡——至少直線過不去。但故事還有下半段:實驗發現,只要允許繞彎,兩個獨立解之間幾乎總找得到一條全程低損失的弧線【觀察】。這引出一個更大的猜想:所有好解可能連成一整片相連的低損失流形(manifold)【假說】——「流形」聽起來嚇人,白話就是「一片連續相連的低地」,而不是一個個孤立的坑。網路越大,這個圖像越像真的;還有證據顯示相連的結構在訓練早期就定型,後期的分岔不破壞連通【觀察】。回頭看,「換種子重跑結果都差不多」跟這個圖像互相印證:你每次降落的不是同一個點,但可能是同一片低地。
軌跡的第二個意外:把訓練硬限制在一個隨機挑的低維子空間裡——比如 73 個參數只准在某個隨機方向組成的 10 維平面上動——常常照樣訓練得動【觀察】。一個任務所需的最小子空間維度叫它的內在維度(intrinsic dimension);量出來的內在維度往往比參數總數小好幾個數量級,而且不特別挑方向,隨機的就行。自然訓練的軌跡本身也集中在低維子空間裡【觀察】。這些都在暗示同一件事:那片高維地景裡,跟訓練真正相關的結構可能低維得出奇——但「暗示」就只是暗示,怎麼把這些線索拼成一個解釋,目前沒有共識【未決】。
這一節收在一個奇妙的巧合上。統計曲率與權重長度的關係時發現:把權重向量的範數(norm,也就是它的長度,各分量平方和開根號)控制在一個不大不小的區間時,損失面的彎曲異常偏正、訓練出來的模型泛化也較好——文獻叫它金髮姑娘區帶(Goldilocks zone),取「不多不少剛剛好」之意【觀察】。而第 7 章的 He 初始化——權重變異數取 2 除以輸入維度——恰好把初始點放進這個區間【觀察】。當初推導它只是為了讓訊號逐層方差不爆不縮,沒有人設計過「順便落在好區帶」這件事。是巧合還是深層機制,沒人知道【未決】。
四、謎題二:泛化為什麼成得了
現在換學習理論這邊的帳本。已知的事實先擺齊:過參數化不但沒有毀掉泛化,常常改善它——第 8 章的雙下降曲線右半段【觀察】。第 8 章給過的候選解釋是平滑插值假說:完美擬合的解有無窮多個,訓練流程似乎偏好其中在資料點之間補得平滑的那些——第 8 章已明說這是推測,本章維持同一口徑【假說】。另有一個從權重範數切入的視角:參數量與資料量相當時,擬合逼著範數被擠大,模型張牙舞爪;容量再往上加,同樣的擬合可以用更小的範數達成,函數反而變溫和【假說】——它跟雙下降尖峰的位置對得上,但同樣沒有定案。
第二批事實更有意思:怎麼訓練會影響泛化【觀察】。大學習率傾向泛化較好;小批次傾向泛化較好;隨機梯度下降常勝過全批次;批次大小與學習率的比值跟泛化程度顯著相關。這批觀察跟第 9 章的隱式正則化嚴絲合縫地對上——那一章整理過,最佳化演算法自帶兩條偏好:有限步長偏好平坦的位置、隨機取批次偏好各批次意見一致的位置。步長越大、批次越小,這兩條偏好越強——而實驗說泛化越好。全課前後呼應最漂亮的一處,就在這裡。
兩條線索都指向同一個嫌疑概念:平坦極小假說(flat minima hypothesis)【假說】。直覺這樣講:訓練損失面是用手上這批資料畫出來的;測試資料來自同一個分布、卻不是同一批,所以測試的損失面像是訓練損失面被微微錯位過的版本。站在一個寬闊平坦的谷底,整張地圖平移一小段,你腳下的高度幾乎不變;站在一條尖銳的窄縫底,同樣的平移可能把你留在半山腰。平坦的解對這種錯位寬容,所以泛化好——直覺很動人,證據卻兩邊都有,而且本章要求你把反方聽得跟正方一樣大聲。
支持側:平坦度與泛化在大量實驗裡確實相關【觀察】;把訓練後段多個時點的權重平均起來,得到的解往往同時更平坦、測試表現也更好【觀察】。反對側:把標籤隨機化重新訓練——這種模型的泛化必然歸零——量到的極小卻沒有相應變尖,也就是說光憑尖銳度預測不了泛化【觀察】;更狠的一擊是:尖銳度的度量本身可以被憑空改動。這件事不用引文獻,你自己跑:
import numpy as np
rng = np.random.default_rng(0)
# 同一座人行橋的撓度資料,這次分訓練與測試兩批
def make(n, seed):
r = np.random.default_rng(seed)
x = r.uniform(0.02, 0.98, n)
y = 4.0 * x * (1 - x) + 0.25 * np.sin(7.9 * x) + r.normal(0, 0.03, n)
return x, y
x_tr, y_tr = make(26, seed=3)
x_te, y_te = make(200, seed=4)
D_h = 24
W = rng.normal(0, np.sqrt(2), D_h) # 1 維輸入的 He 初始化
b = np.zeros(D_h)
v = rng.normal(0, np.sqrt(2 / D_h), D_h)
b0 = 0.0
def mse(W, b, v, b0, x, y):
h = np.maximum(0, np.outer(x, W) + b) # ReLU
return float(np.mean((h @ v + b0 - y) ** 2))
for _ in range(20000): # 全批次訓練
z = np.outer(x_tr, W) + b
h = np.maximum(0, z)
e = 2 * (h @ v + b0 - y_tr) / x_tr.size
gh = np.outer(e, v) * (z > 0)
W -= 0.05 * (gh.T @ x_tr); b -= 0.05 * gh.sum(0)
v -= 0.05 * (h.T @ e); b0 -= 0.05 * e.sum()
def sharpness(W, b, v, b0, radius=0.05, n_dir=200):
"""平坦度代理:往隨機方向踏出固定半徑,平均損失上升多少"""
base = mse(W, b, v, b0, x_tr, y_tr)
r = np.random.default_rng(7)
ups = []
for _ in range(n_dir):
d = r.normal(0, 1, 3 * D_h + 1)
d = radius * d / np.linalg.norm(d)
ups.append(mse(W + d[:D_h], b + d[D_h:2*D_h],
v + d[2*D_h:3*D_h], b0 + d[3*D_h],
x_tr, y_tr) - base)
return float(np.mean(ups))
alpha = 10.0 # 重新參數化:函數一個字都沒變
W2, b2, v2, b02 = alpha * W, alpha * b, v / alpha, b0
h1 = np.maximum(0, np.outer(x_te, W) + b) @ v + b0
h2 = np.maximum(0, np.outer(x_te, W2) + b2) @ v2 + b02
print(f"兩組參數的輸出最大差距:{np.max(np.abs(h1 - h2)):.1e}")
print(f"原參數 訓練={mse(W,b,v,b0,x_tr,y_tr):.5f} 測試={mse(W,b,v,b0,x_te,y_te):.5f} 尖銳度={sharpness(W,b,v,b0):.5f}")
print(f"縮放之後 訓練={mse(W2,b2,v2,b02,x_tr,y_tr):.5f} 測試={mse(W2,b2,v2,b02,x_te,y_te):.5f} 尖銳度={sharpness(W2,b2,v2,b02):.5f}")這裡量尖銳度的方式是:
逐項拆解:\(\mathbf{u}_k\) 是第 \(k\) 個隨機挑的單位方向(長度為 1 的向量);\(r\) 是固定的踏出半徑,這裡取 0.05;\(\mathcal{L}[\boldsymbol\phi + r\,\mathbf{u}_k]\) 是往那個方向踏出去之後的訓練損失;減掉原地的損失 \(\mathcal{L}[\boldsymbol\phi]\) 就是「踏一步升多高」;對 \(K = 200\) 個方向取平均。平均升得越多,代表這個解坐落的谷越尖。
戲法藏在縮放那一行。ReLU 有一個代數性質:
逐項拆解:\(z\) 是進入 ReLU 前的預活化,\(\alpha\) 是任何正數;把正數提出 \(\max\) 不改變結果(\(\max(0, \alpha z) = \alpha \max(0, z)\)),再被外面的 \(1/\alpha\) 消掉。所以把第一層權重與偏置乘上 \(\alpha = 10\)、第二層權重除以 10,函數逐點不變——第 3 章講過同一件事,這裡把它用成武器。
實跑輸出:兩組參數的輸出最大差距 1.1e-15(浮點誤差等級的零);原參數的訓練損失 0.00151、測試損失 0.00247、尖銳度 0.00041;縮放之後訓練與測試損失一字不差,尖銳度卻變成 0.01347——同一個函數,尖銳度暴漲三十多倍。尖銳度變了,泛化能變嗎?不可能——函數都沒變,測試誤差是同一個數。這就是反對側的殺著:這類尖銳度度量量的是參數座標系的性質,不全是函數的性質,拿它當泛化的原因,因果鏈在第一環就斷了。平坦與泛化的相關【觀察】是真的,但相關不是因果——平坦極小假說到今天還掛著「假說」的牌子,這個實驗是主要原因之一。
比喻: 橋樑節點有兩種設計哲學。一種給每個接合預留寬容差:構件長度差幾公釐、角度偏一點,裝得上也扛得住;另一種把容差收到毫米級,圖面完美時效率最高,但任何一點施工誤差都直接吃掉安全係數。平坦極小與尖銳極小的差別就像這兩種節點——「誤差」在這裡是訓練資料與測試資料之間那點錯位。但比喻在兩處失準。其一:節點容差是工程師算出來、寫進圖面的規格;平坦極小沒有人設計,它是步長與批次雜訊的副產品,事後才被量到。其二:容差是可以拿卡尺量的物理量,怎麼量都是那個數;「平坦度」剛剛示範過,換一套參數座標就變出三十倍——量尺本身會騙人的時候,用它下的結論都得打折。
泛化的另一大來源是架構的歸納偏好【觀察+假說】:架構跟資料性質匹配時,泛化大幅改善。這你已經學了一整個學期——第 10 章把影像的結構寫進模型、第 12 章處理次序、第 13 章在關係網上學習,每一章都是「把對的偏好蓋進結構」的實例,這裡不重講。只補一個旁證:未經訓練、權重停在隨機初始值的卷積結構,本身就展現出對影像友善的偏好【觀察】——偏好真的長在結構裡,不是訓練教出來的。
兩條支線用一段帶過。其一是頓悟(grokking)現象:訓練誤差歸零很久之後,測試表現才突然跳上來【觀察】;一種解釋是初始權重範數太大、被正則化緩慢壓回上一節的金髮姑娘區帶,泛化跟著醒過來【假說】——若成立,它跟「範數落點決定好壞」是同一個故事的兩集。其二是泛化的邊界,這句限定比任何漂亮結果都重要:以上一切「泛化好」都是對同分布資料說的【觀察】。離開訓練資料所在的那片低維結構,模型的行為沒有任何保證;對抗例(adversarial example)就是明證——對輸入加一點人察覺不到的微小擾動,就能翻轉模型的判斷【觀察】。一種說法是模型利用了訓練分布裡真實存在、但人類感官不在意的小幅度訊號,擾動正好踩在那些訊號上【假說】。無論解釋為何,「泛化之謎」謎的是分布之內的成功;分布之外,本來就沒有魔法。
五、謎題三:冗餘拆得掉,卻省不得
最後一個謎題把前兩個綁在一起:既然過參數化是訓練與泛化的共同主嫌,那這些多出來的參數是必要的嗎?能不能少?
先擺硬事實:到目前為止,沒有任何頂尖表現來自參數遠少於資料量的模型【觀察】。但這件事有兩種讀法——「小模型本質上裝不下好解」,或者「好解存在,只是訓練演算法找不到」——現有證據無法區分這兩種讀法【未決】。這句「無法區分」不是本章偷懶,它就是目前的知識邊界,接下來的每個實驗都在這條邊界上打轉。
最直接的探測是剪枝(pruning):把訓練完的網路裡幅度最小的權重設為零,微調剩下的,還可以一輪一輪迭代下去。回到那座裝了 8 個感測器的橋,這次用 60 筆快照訓練一個 576 個權重的網路,然後開拆:
import numpy as np
rng = np.random.default_rng(0)
# 假設 60 筆橋樑監測快照(8 個感測器)→ 預測跨中撓度
I, D_in, D_h = 60, 8, 64
X = rng.normal(0, 1, (I, D_in))
w_hid = rng.normal(0, 1, D_in) # 造資料用的隱藏規則
y = np.sin(X @ w_hid) + 0.3 * (X[:, 0] * X[:, 1]) + rng.normal(0, 0.02, I)
def mse(W1, b1, v, b0):
h = np.maximum(0, X @ W1.T + b1)
return float(np.mean((h @ v + b0 - y) ** 2))
def fit(W1, b1, v, b0, steps, mW=None, mv=None):
"""全批次訓練;mW/mv 是剪枝遮罩,被剪掉的權重永遠留在零"""
for _ in range(steps):
z = X @ W1.T + b1
h = np.maximum(0, z)
e = 2 * (h @ v + b0 - y) / I
gh = np.outer(e, v) * (z > 0)
W1 -= 0.05 * (gh.T @ X); b1 -= 0.05 * gh.sum(0)
v -= 0.05 * (h.T @ e); b0 -= 0.05 * e.sum()
if mW is not None:
W1 *= mW; v *= mv
return W1, b1, v, b0
W1 = rng.normal(0, np.sqrt(2 / D_in), (D_h, D_in))
b1 = np.zeros(D_h)
v = rng.normal(0, np.sqrt(2 / D_h), D_h)
W1, b1, v, b0 = fit(W1, b1, v, 0.0, 30000)
n_w = W1.size + v.size
print(f"可剪權重 {n_w} 個,資料 {I} 筆,訓練後損失 {mse(W1, b1, v, b0):.5f}")
mW, mv = np.ones_like(W1), np.ones_like(v) # 迭代剪枝:每輪剪掉剩餘的兩成
for rnd in range(10):
flat = np.concatenate([np.abs(W1[mW > 0]).ravel(), np.abs(v[mv > 0])])
thr = np.sort(flat)[int(flat.size * 0.2)]
mW, mv = mW * (np.abs(W1) >= thr), mv * (np.abs(v) >= thr)
W1, b1, v, b0 = fit(W1 * mW, b1, v * mv, b0, 6000, mW, mv)
kept = int(mW.sum() + mv.sum())
print(f"第 {rnd+1:2d} 輪:剩 {kept:3d} 個權重({kept/n_w*100:2.0f}%)"
f" 微調後損失={mse(W1, b1, v, b0):.5f}")實跑輸出:訓練後損失 0.00000;前四輪一路剪到剩 461、369、296、237 個權重,微調後損失全部維持 0.00000——近六成的權重拆掉了,損失文風不動;第五輪起開始付代價(剩 190 個時 0.00430),之後逐輪惡化,剪到剩 64 個(11%)時損失已是 0.34563。
三個讀法,一個比一個深。第一,訓練完的網路確實冗餘:一大半權重拆了白拆【觀察】。有人因此把剪枝看成一種架構搜尋:大網路先把各種子結構都養著,剪枝只是事後把有用的那個挑出來【假說】。第二,注意剪不動的底線——維持零損失的最小規模是 237 個權重,仍是 60 筆資料的四倍:壓完之後的模型還是過參數化的。這不是玩具的毛病,是文獻裡壓縮工作的共同結論【觀察】。第三個讀法最微妙,值得放大:「事後拆得掉」推不出「一開始就能省」。 彩券假說(lottery ticket hypothesis)的實驗把這一點釘得更死【假說】:先訓練大網路、剪掉小幅度權重、把倖存的權重倒回它們最初的初始值、再從那裡重新訓練——這個小子網路能追上大網路的表現;但對照組把同一個子網路換一組新的隨機初始值,就練不回來了。倖存結構配上倖存初始值才是那張中獎彩券,而你只有先買下整本彩券簿——訓練整個大網路——才找得到它。
比喻: 一座靜不定桁架橋建成之後,工程師確實可以拆掉部分冗餘桿件,橋照樣立著——力會重新分配到剩下的桿件上。但沒有一個工程師會從這裡推出「那當初就用最少桿件蓋吧」:施工過程中,半成品的橋要扛自重、扛風、扛吊裝的衝擊,那些「用不到」的桿件正是在建造過程裡扛住各種中間狀態的。訓練彷彿也是這樣:多出來的參數在最佳化的過程裡撐著那條「總有方向可下降」的路,路走完之後才變得可拆。但這個比喻照例要收在失準處,而且這次失準得很徹底:桿件在施工各階段扛什麼力,結構分析算得出來,「先冗餘、後拆除」在工程裡是被理論完整覆蓋的標準操作;參數在訓練過程裡到底「撐」了什麼,沒有人算得出來——「訓練需要冗餘」目前只是一個由剪枝與彩券實驗間接勾勒的輪廓【假說】,連怎麼把它寫成一個可檢驗的命題都還在摸索。
另一條壓縮路線是知識蒸餾(knowledge distillation):讓小網路學習大網路的輸出行為——不只學正確標籤,連大網路對每個輸入吐出的完整機率分布一起學,像照著一座已建成的橋另造一座輕量版【觀察】。蒸餾常能把模型壓得更小,但同樣沒有做出「欠參數化而頂尖」的模型。理論這邊還補了一個方向相反的彩蛋:有分析估計,要在資料點之間平滑地插值,所需參數量遠高於僅僅穿過資料點【理論】——順著它,有人主張現有的大模型不是太大,而是還不夠過參數化【假說】。這個主張對不對沒人知道,但它至少提醒你:「參數多得荒謬」這個直覺,本身可能就是用錯了量尺。
冗餘的另一個維度是深。表現與深度長期正相關【觀察】;可是拿較淺、較寬的網路去逼近深網路的表現,差距有時追得很近【觀察】;第 11 章還量過,殘差網路裡真正出力的是中短路徑——「深」帶來的計算鏈長度,跟實際用到的不是同一回事【觀察】。深度為什麼有利?三種候選解釋並排放著,互不排斥也互不認輸【未決】:歸納偏好說——深架構自帶的約束恰好是對真實資料友善的偏好,旁證是蒸餾到卷積結構的學生網路優於蒸餾到全連接的【假說】;可訓練性說——淺而寬的好解存在、只是訓練找不到,旁證是把深教師蒸餾到淺學生常常失敗【假說】;可表達性說——深網路能表示某些淺網路裝不下的函數(第 4 章的深度效率),但這一說自帶反例:那些理論上的病態函數,實務上未必擬合得動,真實世界的函數也未必病態【假說+反例】。第 11 章承諾過「殘差為什麼有效的幾種說法排除不了彼此,第 20 章會回頭處理這一類問題」——現在你看到了,本章能做的處理就是把證據排整齊,然後承認排除不了。這不是敷衍,這是這個題目目前真實的樣子。
課程走到倒數第二章,用一段誠實的話收尾。這一章掛了幾十個標記,數一數就會發現【觀察】最多、【假說】次之、【理論】最少而且個個帶著「假設離實務很遠」的但書——這個分布本身就是答案:深度學習是一個實證跑在理論前面的領域,還沒有一套理論能預測哪個模型訓練得起來、哪個泛化得了,工程實踐靠的是反覆示範出來的經驗規律。橋樑工程師把安全係數配到 2、配到 3,背後有材料力學整套理論告訴他為什麼夠;深度學習把「安全係數」配到資料量的許多倍,實驗說有效,理論還在路上。你在這門課學到的每一個機制都是真的,但把它們黏在一起的那個「為什麼」,有一大半還空著——空著的地方,就是這個領域還在等人做的事。最後一章我們換一個方向問問題:這套還沒被完全理解的技術用在人身上時,該由誰負責。
§03原書對照
原書第 20 章的體例與前十九章完全不同:它不交付一套成熟的機制,而是把「深度學習為什麼行得通」這個未解的問題正面攤開。作者在章首直言,儘管書名就叫理解深度學習,領域對它的理解其實仍然有限(p.402)——這種坦白在教科書裡罕見,也是這一章最值得一讀的理由。
pp.402–403 先把「意外」立起來:一邊是非凸最佳化在最壞情況下的計算困難,一邊是擬合完訓練集的模型照理沒有義務在資料點之間表現得體。這兩頁附了幾筆量化估計,包括可能輸入組態相對於資料量的懸殊比例、一個中型網路能切出的線性區域數與它的剩餘自由度;p.403 還討論了兩個著名大型模型究竟算不算過參數化的爭議,結論是連這件事都沒有定論。
pp.403–407 逐一排查訓練容易的候選解釋。p.404 轉載了把影像換成雜訊、把標籤打亂之後網路照樣擬合的著名實驗,同頁腳註聲明該章對「全域極小」一詞採寬鬆用法;p.405 以全批次梯度下降硬背亂給標籤的實驗排除了「隨機性是必要條件」的說法,同頁還引了一句形容簡併解處境的妙語,原文值得翻去看;pp.405–406 整理過參數化保證收斂的多個理論結果,並直言其假設與實務相距甚遠;pp.406–407 檢視活化函數與初始化的角色,p.407 介紹彩券假說的原始實驗與其構想。
pp.407–411 轉向損失地景的實測性質:p.408 盤點讓全域極小成為一整個家族的幾類對稱性,同頁也指出過參數化下另有一族只在資料點上行為一致、資料點之間各行其是的等價解;pp.408–409 是關於訓練軌跡的兩個出人意料的觀察(起點到終點的直線切片、限制在隨機低維子空間內訓練照樣成功);pp.409–410 談獨立找到的解之間的連通路徑與單一低損失流形的猜想,並附兩張把這件事畫得很清楚的切片圖;pp.410–411 用駐點的負曲率統計與權重範數的金髮姑娘區帶收束這條線,順帶記下常用初始化恰好落在那個區帶裡的巧合。
pp.411–415 檢視泛化的來源:批次大小與學習率之比(p.411)、平坦極小假說連同它的幾種度量方式、靠重新參數化就能把平坦度改掉的警告、以及一個乾淨的反例(pp.412–413)、架構的歸納偏好(p.413)、權重範數對頓悟現象的解釋(pp.413–414),以及離開資料流形之後的對抗例(pp.414–415,配圖令人過目難忘)。
pp.415–418 問參數能不能少:剪枝一節在 pp.415–417,p.416 有剪枝前後的網路對照圖;知識蒸餾在 pp.416–417;pp.417–418 給出平滑內插所需參數的理論下界,並整理出「壓縮後的模型仍然過參數化」的結論。pp.418–419 問網路要不要深,比較了幾種候選解釋各自的證據,其中包括未訓練的卷積結構本身就能充當先驗的巧妙旁證,以及把深教師蒸餾到淺學生的失敗紀錄。
pp.419–420 的總結誠實得罕見:領域仍由實證示範驅動,還沒有一套能預測成敗的理論,作者並逐條承認了目前明確的未知。p.420 附三道習題,分別練輸入空間的量級估算、兩種隨機化的擬合速度差異、以及從全批次實驗能不能推出凸性;章內邊欄另標了四份可互動的線上筆記本。原書第 20 章對應印刷頁 pp.402–420。
§04作業和解答
作業一:單調下降的弦,證明不了凸
本章第三節看到「起點到解的直線上損失一路下降」,並警告不要由此推出「損失面是凸的」。請親手造一個反例。考慮自造的雙參數損失 \(f(a, b) = (a^2 - 1)^2 + 0.5\,b^2\)。(a)指出它所有的極小點,並說明這個函數為什麼不是凸的(提示:凸函數的任兩點連線上,函數值不得高於兩端點的線性內插;找一對點打破它)。(b)取起點 \((0.2,\ 1.4)\) 與終點 \((1,\ 0)\),在連線上取 11 個等距點算出函數值,驗證它是否單調下降。(c)綜合(a)(b),寫一句話說明「單調下降的弦」與「凸性」之間的邏輯關係。
解答 SOLUTION
(a)極小點有兩個:\((1, 0)\) 與 \((-1, 0)\),函數值都是 0。取這兩個極小點連線的中點 \((0, 0)\):\(f(0,0) = (0-1)^2 + 0 = 1\),而兩端點的函數值都是 0、線性內插也是 0。中點的值 1 高於內插值 0,直接違反凸函數的定義——這個面在兩個谷之間隆起一座丘,非凸無疑。
(b)實跑 11 個等距點的函數值:1.902 → 1.643 → 1.385 → 1.130 → 0.885 → 0.655 → 0.446 → 0.267 → 0.126 → 0.033 → 0.000,嚴格單調下降(程式逐對比較回傳 True)。
(c)凸性是對所有弦的承諾,單調下降只是某一條弦的性質。一條(甚至很多條)弦上表現良好,跟整個面是凸的之間隔著一個量詞的距離——「存在」推不出「全稱」。第三節那個觀察的正確結論只有一句:訓練實際走過的那一帶地形比最壞情況溫和;至於整片地景,(a) 小題那種雙谷結構完全可能同時存在——事實上第三節「解 A 到解 B」切片的高牆,就是它存在的直接證據。
作業二:把嫌疑人請回來——隨機性與初始尺度
本章第二節的隨機標籤實驗用了全批次梯度下降。(a)把它改成小批次版本:批次大小 5,每個世代(epoch,掃過全部資料一遍)先隨機打亂資料順序再逐批更新,其餘不動。記錄兩個版本各自在第幾個世代(全批次版一步就是一個世代)首次達到零錯分。(b)根據(a)的結果,判斷下列兩句話各自被支持還是被推翻:「隨機性是擬合成功的必要條件」「隨機性對擬合沒有幫助」。(c)回到全批次原版,把 W1 與 v 的初始值都乘上 6,觀察收斂變快還是變慢。本章正文說大規模實驗顯示「放大初始尺度多半只是拖慢、不改結局」——你的小實驗跟這句話一致嗎?該怎麼解讀不一致之處?
解答 SOLUTION
(a)實跑結果:全批次版在第 17 步(=第 17 個世代)首次零錯分;小批次版在第 6 個世代首次零錯分。兩者最後都把損失壓到 0.0001 以下。
(b)兩句都被推翻。全批次版成功擬合,證明隨機性不是必要條件——這是正文【已削弱】判定的複現。但小批次版用更少的世代達標(6 對 17),至少在這個例子裡隨機性有幫助。這正是第二節反覆強調的邏輯:排除「必要」與否認「有幫助」是兩個不同強度的主張,一個實驗可以同時支持前者、反對後者。
(c)實跑結果出人意料:初始尺度乘 6 之後,首次零錯分落在第 20 步(原版 17 步),幾乎沒差;若看「損失降到 0.01 以下」的步數,放大版反而更快(20 步對 277 步)——因為更大的權重讓輸出更快變得極端,對數損失一旦分類正確就掉得飛快。這不能拿來反駁正文那句話:正文講的是深層網路,初始尺度的影響會隨層數複合放大(第 7 章的爆炸與消失機制),兩層的玩具網路根本測不到那個效應。這一題真正要你帶走的是方法論:玩具實驗與大規模觀察不一致時,先檢查玩具缺了哪個機制,而不是急著宣布誰對誰錯。
作業三:剪出來的小網路,跟生來就小的網路
本章第五節的迭代剪枝在剩 152 個權重時損失 0.04389。(a)預測:架構相同、但隱藏寬度縮到 17(權重 \(9 \times 17 = 153\) 個,數量幾乎相同)的稠密小網路,從頭訓練 30,000 步,最終訓練損失會比 0.04389 好還是差?寫下你的理由再跑。(b)實跑驗證(試三個不同的初始化種子)。(c)再把寬度縮到 2、4、6(權重 18、36、54 個,開始逼近甚至低於資料量 60 筆),各跑三個種子。(d)綜合這些結果,說明它們對「小模型本質上不行」與「訓練演算法找不到小模型的好解」這兩種讀法各說了什麼。
解答 SOLUTION
(a)合理的預測兩個方向都有人選。支持「更差」的直覺:剪枝版好歹繼承了大網路找到的解。支持「更好」的直覺:剪枝版的稀疏樣式是被凍住的——哪些連線存在是剪的時候定死的,微調動不了;稠密小網路的 153 個權重卻可以自由長成任何樣式。
(b)實跑:寬度 17 的稠密網路,三個種子的最終訓練損失全部是 0.00000——比剪枝版的 0.04389 好得多。第二個直覺贏了:同樣的權重數量,自由安排的贏過被凍住樣式的。這也解釋了為什麼有人把剪枝看成架構搜尋——它搜出來的樣式未必是最優的,只是大網路順路留下的。
(c)實跑:寬度 6(54 個權重+7 個偏置,參數量約等於資料量)三個種子的損失是 0.0059 / 0.0575 / 0.0596——擬合得不錯但不到零,而且明顯看種子;寬度 4 是 0.2200 / 0.1641 / 0.1648;寬度 2 是 0.3206 / 0.3514 / 0.2854,已接近「用平均值猜」的水準(本資料的變異數約 0.52)。
(d)先說(b)的教訓:寬度 17 從頭訓練成功,並不推翻領域觀察「沒有頂尖表現來自參數遠少於資料量的模型」——153 個權重對 60 筆資料仍是過參數化,它只是比 576 小,不是真的「小」。真正逼近欠參數化的(c)才碰到邊界:參數一旦壓到資料量以下,擬合明顯吃力、且對種子敏感。但請注意,這仍然區分不了兩種讀法——寬度 2 擬合失敗,可以讀成「它本質上裝不下這個函數」,也可以讀成「好解在,但梯度下降在這麼擠的參數空間裡找不到」。要區分,你得窮舉寬度 2 的所有參數組合證明好解不存在,而那正是做不到的事。本章的知識邊界,在一個 21 個參數的玩具上就摸得到——這是這一題最想讓你帶走的體感。
§05參考資料
- Understanding deep learning requires rethinking generalization(arXiv:1611.03530) — 「隨機標籤照樣擬合」的原始實驗系列,本章第二節排查框架的實證底座
- The Lottery Ticket Hypothesis(arXiv:1803.03635) — 彩券假說的原始論文,含「倒回初始值重訓」的完整實驗設計與對照組
- Qualitatively Characterizing Neural Network Optimization Problems(arXiv:1412.6544) — 「起點到解的直線切片近乎單調下降」這個觀察的出處,本章第三節切片實驗的靈感來源
- Measuring the Intrinsic Dimension of Objective Landscapes(arXiv:1804.08838) — 把訓練限制在隨機低維子空間、量出任務內在維度的原始實驗
- Loss Surfaces, Mode Connectivity, and Fast Ensembling of DNNs(arXiv:1802.10026) — 獨立解之間繞彎的低損失路徑:模式連通性的代表作之一
- Sharp Minima Can Generalize For Deep Nets(arXiv:1703.04933) — 用重新參數化把平坦度憑空改動的正式版本,本章第四節那個實驗的理論出處
- Grokking: Generalization Beyond Overfitting(arXiv:2201.02177) — 頓悟現象的命名論文:訓練誤差歸零很久之後泛化突然改善
- Understanding Deep Learning(MIT Press) — 本課課綱主題所本的原書出版頁(ISBN 9780262048644,2023-12 出版)
- udlbook 官方網站(作者釋出的 PDF、投影片與習題) — 原書作者維護的免費資源站(udlbook.com 會轉址到此)