① 依序閱讀:每節先讀說明;遇到互動元件時,先預測結果,再操作驗證。 ② 對照課本:章節旁標示課本節號,正文保留核心公式與短例,細節與證明預設收合;可展開推導,並對照原書。 ③ 檢查理解:答錯時先看回饋,再回到相關說明;標為延伸的內容可留待第二輪。 ④ 最後翻關鍵詞彙卡自測術語,並用 重點速查與來源查閱。
教科書:An Introduction to Statistical Learning with Applications in Python(ISLP);
進階參考:The Elements of Statistical Learning(ESL)。章節旁的來源標記可點到本頁書目。
本課沒有教第 10 章。它不在考試範圍, 也沒有對應的講義與 lab。放上來是因為前面九章把「線性模型 → 加彈性 → 加正則化 → 換基底 → 集成」這條線走完之後,深度學習正好是同一條線的下一步,可以銜接前面的內容。
ISLP 從模型形式介紹神經網路:把式子攤開來看,它就是 線性模型套一層非線性再線性組合一次。單層網路的預測函數長這樣:
$$f(X) = \beta_0 + \sum_{k=1}^{K} \beta_k \, g\!\left(w_{k0} + \sum_{j=1}^{p} w_{kj} X_j\right) \tag{10.1}$$把 g 換成恆等函數,整條式子會塌回線性迴歸:兩層線性組合疊起來還是線性組合。 其中 g 提供非線性,其餘部分沿用線性組合。
還有一個貫串全章的問題,§10.6 專門處理:什麼時候該用深度學習、什麼時候不該。 ISLP 的立場很明確,Hitters 那個例子就是拿來說服你的——神經網路跟線性迴歸打平, 而線性模型看得懂、講得清。他們搬出奧坎剃刀:表現差不多的時候,挑簡單的那個。
| 線性迴歸 | 神經網路 | |
|---|---|---|
| 參數怎麼來 | 閉式解,一次算完 | 梯度下降,要迭代、要調 |
| 有幾個要調的東西 | 幾乎沒有 | 層數、寬度、學習率、批次大小、dropout、epoch 數… |
| 係數能解讀嗎 | 能,還有標準誤與 p 值 | 不能,是黑盒子 |
| 什麼時候贏 | n 不大、訊號接近線性、要解釋 | n 很大、訊噪比高、輸入有空間或時間結構 |
式 10.1 裡如果把 g(z) 換成恆等函數 g(z) = z,這個「神經網路」會變成什麼?
單層網路的結構只有三步:輸入做 K 組線性組合、每一組過同一個 g、 再把 K 個結果線性組合成輸出。中間那 K 個值 ISLP 叫 activation, 寫成 A_k:
$$A_k = h_k(X) = g\!\left(w_{k0} + \sum_{j=1}^{p} w_{kj} X_j\right), \qquad f(X) = \beta_0 + \sum_{k=1}^{K} \beta_k A_k \tag{10.2}$$要估的參數是所有 w 與所有 β,總共 K(p+1) + (K+1) 個。 注意 w_{k0} 與 β₀ 這兩個截距在機器學習圈叫 bias—— ISLP 在註腳特別提醒,那跟偏差–變異取捨的「偏差」是兩回事,只是撞名。
沒有公式,它是超參數,跟第 6 章的 λ、第 8 章的樹深度同一個地位,用交叉驗證或驗證集選。
實務上也常先把 K 開大,再靠正則化(dropout、權重衰減、早停)把彈性收回來,這種做法的理由見 §10.8:過度參數化的網路配上適當的訓練與正則化,有時能比參數較少的網路表現更好;SGD 並不普遍保證最平滑或最小範數解。
跟 SVM 與嶺迴歸的理由一樣:所有輸入共用同一個學習率與同一個權重衰減,尺度差很多時,數值大的那個變數會主宰梯度,小的那個幾乎不動。
官方 lab 的 Hitters 例子在 lasso 那條路上用 StandardScaler 包進 Pipeline,神經網路那條路則是先把整個 X 標準化再切訓練測試。要注意的是:標準化的統計量只能從訓練資料算,否則就是第 5 章講過的資料洩漏。
ISLP 的示範順序很值得學:先跑線性迴歸與 lasso,再跑神經網路。
沒有基準線的話,你不會知道那個神經網路到底是好是壞。資料是 Hitters,
n = 263、p = 19,用三分之一當測試集。
np.float64(259.7152883314627)
測試集上的平均絕對誤差是 259.72。這是最陽春的基準,後面每個模型都要跟它比。
來源:Ch10-deeplearning-lab.ipynb
np.float64(235.6754837478029)
lasso 把 MAE 壓到 235.68,比最小平方好一截。注意 lam_max 那一行:它算出「剛好把所有係數壓成 0」的 λ,格點就從那裡往下取,這樣不必憑空猜範圍。
Ch10-deeplearning-lab.ipynb
PyTorch 的寫法是繼承 nn.Module,在 __init__ 裡宣告要用的層、
在 forward 裡寫資料怎麼流過去。這個網路是 19 → 50(ReLU、dropout 0.4)→ 1。
=================================================================================================================== Layer (type:depth-idx) Input Shape Output Shape Param # =================================================================================================================== HittersModel [175, 19] [175] -- ├─Flatten: 1-1 [175, 19] [175, 19] -- ├─Sequential: 1-2 [175, 19] [175, 1] -- │ └─Linear: 2-1 [175, 19] [175, 50] 1,000 │ └─ReLU: 2-2 [175, 50] [175, 50] -- │ └─Dropout: 2-3 [175, 50] [175, 50] -- │ └─Linear: 2-4 [175, 50] [175, 1] 51 =================================================================================================================== Total params: 1,051 Trainable params: 1,051 Non-trainable params: 0 Total mult-adds (Units.MEGABYTES): 0.18 =================================================================================================================== Input size (MB): 0.01 Forward/backward pass size (MB): 0.07 Params size (MB): 0.00 Estimated Total Size (MB): 0.09 ===================================================================================================================
1,000 + 51 = 1,051 個參數,訓練樣本只有 175 筆。模型包含 Dropout(0.4);這個 lab 固定訓練 50 個 epoch,沒有設定早停。單次結果不能把表現歸因於 dropout、雙下降或任何一項正則化機制。
Ch10-deeplearning-lab.ipynb
Testing DataLoader 0: 100%|███████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████████| 3/3 [00:00<00:00, 225.66it/s]
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Test metric DataLoader 0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
test_loss 107904.640625
test_mae 221.83148193359375
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[{'test_loss': 107904.640625, 'test_mae': 221.83148193359375}]test_mae = 221.83,比 lasso 的 235.68 好。但先別急著下結論——課本 Table 10.2 裡神經網路是輸的(MAE 257.4 對線性迴歸的 254.7)。同一份資料、同一個做法,換個切分與 epoch 數就換了名次,比較名次時也要交代這些設定。
Ch10-deeplearning-lab.ipynb
官方 lab 跑出線性 259.72、lasso 235.68、神經網路 221.83;課本 Table 10.2 卻是線性 254.7、lasso 252.3、神經網路 257.4。該怎麼解釋?
課本 Table 10.2 裡,三個模型依「平均絕對誤差」排出來的名次,跟依「測試 R²」排出來的名次不一樣。這怎麼可能?
多加一層之後,第二層接收第一層的輸出 A^(1),由它繼續計算。 式子還是那個式子,只是套了兩次:
$$A^{(1)}_k = g\!\left(w^{(1)}_{k0} + \sum_j w^{(1)}_{kj} X_j\right), \qquad A^{(2)}_\ell = g\!\left(w^{(2)}_{\ell 0} + \sum_k w^{(2)}_{\ell k} A^{(1)}_k\right)$$MNIST 是十類別的問題,所以輸出層要輸出十個數字再轉成機率。用的是 softmax:
$$f_m(X) = \Pr(Y = m \mid X) = \frac{e^{Z_m}}{\sum_{\ell=0}^{9} e^{Z_\ell}} \tag{10.13}$$損失函數則是負的多項式對數概似,也就是交叉熵:
$$-\sum_{i=1}^{n} \sum_{m=0}^{9} y_{im} \log f_m(x_i) \tag{10.14}$$參數量是這一節的重點。MNIST 的輸入是 28×28 = 784 個畫素, ISLP 用的架構是 784 → 256 → 128 → 10。光第一層就有 784×256 + 256 = 200,960 個參數, 三層加起來 235,146 個。對照組多元邏輯斯迴歸只需要 785×9 = 7,065 個, 差了 33 倍。
一個網路是 784 → 256 → 128 → 10 的全連接架構(每層都有偏置)。第一層有幾個參數?
一個網路有 p = 4 個輸入、第一層 2 個隱藏單元、第二層 3 個隱藏單元、單一輸出,每一層都有偏置。總共有幾個參數?
softmax 的定義是 f_m(X) = e^{{Z_m}} / Σ_ℓ e^{{Z_ℓ}}。把每一個 Z_ℓ 都加上同一個常數 c,機率會怎麼變?
=================================================================================================================== Layer (type:depth-idx) Input Shape Output Shape Param # =================================================================================================================== MNISTModel [256, 1, 28, 28] [256, 10] -- ├─Sequential: 1-1 [256, 1, 28, 28] [256, 10] -- │ └─Sequential: 2-1 [256, 1, 28, 28] [256, 256] -- │ │ └─Flatten: 3-1 [256, 1, 28, 28] [256, 784] -- │ │ └─Linear: 3-2 [256, 784] [256, 256] 200,960 │ │ └─ReLU: 3-3 [256, 256] [256, 256] -- │ │ └─Dropout: 3-4 [256, 256] [256, 256] -- │ └─Sequential: 2-2 [256, 256] [256, 128] -- │ │ └─Linear: 3-5 [256, 256] [256, 128] 32,896 │ │ └─ReLU: 3-6 [256, 128] [256, 128] -- │ │ └─Dropout: 3-7 [256, 128] [256, 128] -- │ └─Linear: 2-3 [256, 128] [256, 10] 1,290 =================================================================================================================== Total params: 235,146 Trainable params: 235,146 Non-trainable params: 0 Total mult-adds (Units.MEGABYTES): 60.20 =================================================================================================================== Input size (MB): 0.80 Forward/backward pass size (MB): 0.81 Params size (MB): 0.94 Estimated Total Size (MB): 2.55 ===================================================================================================================
兩層的 dropout 比例不一樣(0.4 與 0.3):靠近輸入的層通常丟得多一點。nn.Flatten() 把 28×28 攤成 784 的向量,這個動作把畫素的空間關係整個丟掉了,下一節的卷積網路就是為了把它找回來。
Ch10-deeplearning-lab.ipynb
/Users/jonathantaylor/git-repos/ISLP/ISLP_labs/.venv/lib/python3.12/site-packages/pytorch_lightning/utilities/_pytree.py:21: `isinstance(treespec, LeafSpec)` is deprecated, use `isinstance(treespec, TreeSpec) and treespec.is_leaf()` instead.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Test metric DataLoader 0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
test_accuracy 0.9620000123977661
test_loss 0.15120187401771545
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[{'test_loss': 0.15120187401771545, 'test_accuracy': 0.9620000123977661}]test_accuracy = 0.9620,錯誤率 3.8%。課本 Table 10.1 報的是 1.8%(dropout 版),差別在訓練得比較久。
Ch10-deeplearning-lab.ipynb
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Test metric DataLoader 0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
test_accuracy 0.916100025177002
test_loss 0.3469300866127014
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[{'test_loss': 0.3469300866127014, 'test_accuracy': 0.916100025177002}]同一個 torch 框架,把中間兩層拿掉就是多元邏輯斯迴歸,nn.Linear(784, 10) 加 softmax 而已。準確率 0.9161,錯誤率 8.4%,是兩層網路的兩倍多。這個例子裡多的那兩層是真的有用的,跟 Hitters 那個「打平」的結論不一樣。
Ch10-deeplearning-lab.ipynb
上一節把 28×28 攤平成 784 的那一刻,「這兩個畫素相鄰」的資訊就沒了。 對影像來說這很浪費:一隻貓的耳朵出現在左上角還是右下角,都應該算是耳朵。 卷積網路把這個先驗直接寫進架構,做法有兩個。
丟掉的是位置的精度,留下的是「這個特徵存不存在」。對分類來說後者才是重點——你要判斷這是不是一隻貓,不需要知道耳朵精確在第 137 個畫素。
更實際的理由是它讓後面的層看得更廣。經過一次 2×2 池化,同樣一個 3×3 濾波器在原圖上涵蓋的範圍就變成兩倍。堆疊「卷積+池化」等於一步步擴大視野:前面的層看邊緣與紋理,後面的層看得到整隻動物。官方 lab 的 CIFARModel 疊了四組,32×32 因此縮成 2×2。
算,而且 ISLP §10.3.4 就是這樣定位它的。把訓練影像隨機翻轉、平移、縮放之後標籤不變,等於在告訴模型「這些變化不該影響答案」。這是一個很強的約束,跟嶺迴歸用懲罰項限制係數是同一種事,都在縮小模型能選的函數空間。
差別在於它是用資料表達的約束。好處是很容易加進任何模型;壞處是你得知道哪些變化是無害的(影像可以左右翻,手寫數字的 6 跟 9 就不能上下翻)。
BuildingBlock 就是「卷積 → ReLU → 最大池化」三個步驟。通道數一路 3 → 32 → 64 → 128 → 256 加倍,空間尺寸則被池化一路砍半:32 → 16 → 8 → 4 → 2。解析度換通道數是 CNN 的標準節奏。
Ch10-deeplearning-lab.ipynb
/Users/jonathantaylor/git-repos/ISLP/ISLP_labs/.venv/lib/python3.12/site-packages/pytorch_lightning/utilities/_pytree.py:21: `isinstance(treespec, LeafSpec)` is deprecated, use `isinstance(treespec, TreeSpec) and treespec.is_leaf()` instead.
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Test metric DataLoader 0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
test_accuracy 0.4269999861717224
test_loss 2.45865797996521
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[{'test_loss': 2.45865797996521, 'test_accuracy': 0.4269999861717224}]0.4270。一百個類別的隨機猜測是 1%,所以 43% 其實不算差,但也遠稱不上好:CIFAR-100 每類只有 500 張訓練影像,這種規模對 CNN 太少了。下一張卡的做法才是資料不多時該走的路。
來源:Ch10-deeplearning-lab.ipynb
Image: book_images/Cape_Weaver.jpg
label prob
0 jacamar 0.297499
1 macaw 0.068107
2 lorikeet 0.051105
Image: book_images/Flamingo.jpg
label prob
0 flamingo 0.609515
1 spoonbill 0.013586
2 American_egret 0.002132
Image: book_images/Hawk_Fountain.jpg
label prob
0 kite 0.184682
1 robin 0.084021
2 great_grey_owl 0.061274
Image: book_images/Hawk_cropped.jpg
label prob
0 kite 0.453833
1 great_grey_owl 0.015914
2 jay 0.012210
Image: book_images/Lhasa_Apso.jpg
label prob
0 Lhasa 0.260317
1 Shih-Tzu 0.097196
2 Tibetan_terrier 0.032820
Image: book_images/Sleeping_Cat.jpg
label prob
0 Persian_cat 0.163070
1 tabby 0.074143
2 tiger_cat 0.042578這個模型在 ImageNet 上訓練過,完全沒看過這幾張照片。紅鶴 0.61、拉薩犬 0.26 都對;但第一張織巢鳥被猜成 jacamar(鶲䴕),而且最高機率只有 0.30。看機率不要只看排名——0.30 這種數字本身就在說「我不太確定」。
來源:Ch10-deeplearning-lab.ipynb
輸入是 32×32 的灰階影像,一個卷積層有三個 5×5 濾波器、不做邊界填補。這一層要估幾個參數?
輸入是 32×32 灰階影像,一個卷積層有三個 5×5 濾波器、不做邊界填補。「這一層的參數量」與「拿掉權重共享後的權重數」分別是多少?
資料增強(data augmentation)在訓練時對影像隨機平移、縮放、小角度旋轉或適當翻轉, 讓模型對應保留類別意義的變化。它為同一訓練影像建立附近的變體,可視為一種正則化,並未產生新的獨立受試者或獨立場景。
增強必須維持標籤合理:左右翻轉某些物體照片可行,旋轉數字 6 卻可能改成另一類。 先切分原始影像,再對訓練部分做隨機增強,避免同一原圖的不同版本分散到訓練與測試集。 評估使用明確固定的前處理;若用測試時增強,須另外說明合併預測的程序。
預訓練模型還可作移轉學習:保留已學到的卷積特徵,凍結部分權重,只用新資料訓練後幾層。 這與上面直接使用原本的 ResNet50 分類器不同;新任務需有自己的標籤、輸出層與獨立評估。
來源:ISLP §10.3.4–10.3.5,印刷 pp.411–412;官方 Lab §10.9.4 展示直接使用預訓練分類器,未宣稱執行了本站所述移轉訓練。
影像的結構是空間上的,文字與股價的結構是順序上的。 ISLP 用 IMDB 影評的正負評分類當例子,先示範最簡單的做法:詞袋。 把每篇評論表示成「字典裡每個詞出現了沒有」的長向量, 然後就當成普通的分類問題丟給 lasso 或神經網路。
詞袋完全丟掉詞序,所以「這部片一點都不好看」跟「這部片好看一點都不」是同一個向量。 詞袋在情感分類這種任務上仍可有良好表現,因為有沒有出現 terrible 這個詞,本身就是很強的訊號。
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Test metric DataLoader 0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
test_accuracy 0.8450000286102295
test_loss 1.216800332069397
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[{'test_loss': 1.216800332069397, 'test_accuracy': 0.8450000286102295}]0.8450。這是詞袋能到的水準,沒有用到任何詞序資訊。
來源:Ch10-deeplearning-lab.ipynb
要把順序找回來,就要換成遞迴神經網路。 它依序讀入 X₁, X₂, …, X_L,每讀一個就用同一組權重更新一個隱藏狀態:
$$A_\ell = g\!\left(W X_\ell + U A_{\ell-1} + b\right), \qquad O_\ell = \beta_0 + \beta^{\top} A_\ell$$W、U、b 在每個時間點都一樣。這跟 CNN 在空間上共享權重是同一個念頭, 只是換成在時間上共享。序列多長都用同一組參數。
| 時間 | 讀入 | 共用的更新 | 保留下來的資訊 |
|---|---|---|---|
| ℓ = 1 | X₁ | A₁ = g(WX₁ + UA₀ + b) | 第一個詞的脈絡 |
| ℓ = 2 | X₂ | A₂ = g(WX₂ + UA₁ + b) | X₁ 與 X₂ 的摘要 |
| … | … | 同一組 W、U、b | 狀態沿序列傳遞 |
| ℓ = L | X_L | A_L = g(WX_L + UA_{L−1} + b) | 供最後輸出使用的序列摘要 |
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
Test metric DataLoader 0
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
test_accuracy 0.8400400280952454
test_loss 0.849097490310669
────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────
[{'test_loss': 0.849097490310669, 'test_accuracy': 0.8400400280952454}]0.8400——比詞袋的 0.8450 還低一點點。ISLP 的這個結果顯示:情感分類這個任務,詞序帶來的好處沒有想像中大。nn.Embedding 那一層把每個詞的整數編號映射成 32 維的稠密向量,是這類模型的標準第一步。
Ch10-deeplearning-lab.ipynb
0.4595563133053273
落後 5 期的線性自迴歸模型測試 R² 是 0.4129,加上星期幾這個因子之後變成 0.4596。對照組是 RNN 的 0.4150與非線性自迴歸的 0.4660。四個模型全部落在 0.41 到 0.47 之間。
來源:Ch10-deeplearning-lab.ipynb
IMDB 上詞袋加兩層網路是 0.8450,LSTM 是 0.8400。下面哪一句最站得住腳?
NYSE 例子以 $v_t$ 表示當日對數交易量,$r_t$、$z_t$ 為另外兩個歷史量測。 用前 L 天預測第 t 天,則一筆輸入與目標為:
$$X_t=\begin{bmatrix}v_{t-L}&r_{t-L}&z_{t-L}\\\vdots&\vdots&\vdots\\ v_{t-1}&r_{t-1}&z_{t-1}\end{bmatrix},\qquad Y_t=v_t.$$X 的形狀是 L×3。T 天資料可建立 T−L 筆樣本;L=5、T=6,051 時為 6,046 筆。 相鄰樣本會共用部分日期,不能當成互相獨立的抽樣,更不能隨機打亂後宣稱是在預測未來。
RNN 依時間順序處理五個三維向量;線性自迴歸把同一批歷史量展平成 15 個欄位,連同截距擬合:
$$\hat v_t=\beta_0+\sum_{\ell=1}^L(\beta_{v\ell}v_{t-\ell}+\beta_{r\ell}r_{t-\ell}+\beta_{z\ell}z_{t-\ell}).$$訓練日期早於評估日期,標準化與參數估計只使用訓練部分。 逐日的一步預測可以使用已經實際觀察到的前一天測試期交易量;若要在同一天一次預測未來很多天,就不能偷用尚未觀察到的數值。 星期幾可由日曆提前知道,所以與當天未知交易量的可用性不同。
來源:ISLP §10.5.2,印刷 pp.421–424、式 10.20–10.22;官方 Lab 時間序列段使用相同落後期構造。這些是歷史資料的教學示例。
前面都在講模型長什麼樣,這一節講怎麼把參數估出來。目標函數以量化反應為例:
$$R(\theta) = \frac{1}{2} \sum_{i=1}^{n} \left(y_i - f_\theta(x_i)\right)^2 \tag{10.25}$$問題在於這個 R(θ) 不是凸函數。線性迴歸有閉式解、 邏輯斯迴歸的對數概似是凹的,但唯一有限解還需要可識別性與不存在分離等條件。神經網路通常沒有閉式解或凸性保障: 它有很多局部極小,而我們只能用梯度下降慢慢滑下去、 以找到足夠好的解為目標,但無法保證找到全域最佳解。
另一個常用的正則化手段是早停。
訓練誤差通常隨訓練下降,但 SGD 的單步或單一 epoch 不保證單調;驗證誤差可能先降後升;在轉折點停下來,
效果跟加懲罰項類似。ErrorTracker 回呼只記錄驗證曲線;官方 Hitters lab
仍跑滿 max_epochs=50,沒有 EarlyStopping 回呼或依驗證結果選 epoch。
局部極小會影響結果,但仍有幾個因素有助於找到可用的解。
第一,實務上在高維空間裡,會嚴重影響結果的局部極小相對較少:也可能遇到鞍點;在適當條件下,隨機擾動有助於離開鞍點附近。第二,學習的目標是降低測試誤差;訓練誤差的全域最小值本身不足以衡量泛化;訓練誤差的全域最小很可能就是嚴重過度擬合的那個點。
此外,訓練結果會受隨機性影響。同一份資料換一個隨機種子,跑出來的網路不一樣、測試誤差也不一樣。官方 lab 每次訓練前都呼叫 seed_everything,並在 Trainer 裡設 deterministic=True,就是為了讓結果可重現。
因為訓練與預測時的行為必須對得起來。訓練時如果丟掉 40% 的單元,下一層收到的加總平均就只剩 60%;預測時所有單元都在,加總會突然變大 1/0.6 倍,模型等於面對一個沒見過的輸入分布。
解法是訓練時把留下來的值除以 0.6,讓期望值維持不變,預測時就什麼都不用做。這叫 inverted dropout,也是 nn.Dropout 的做法。順帶一提,這就是為什麼 model.eval() 很重要——它會關掉 dropout;忘了呼叫的話預測會帶著隨機性。
把批次大小從 32 改成整個訓練集(也就是每一步都用全部資料算梯度),會發生什麼?
先看一筆輸入 $x_i$、反應 $y_i$ 與一層隱藏層。令 $z_{ik}=w_{k0}+\sum_jw_{kj}x_{ij}$、$a_{ik}=g(z_{ik})$, $f_i=\beta_0+\sum_k\beta_ka_{ik}$,單筆損失 $R_i=\tfrac12(f_i-y_i)^2$。 以 $e_i=f_i-y_i$ 記錄預測誤差;在 g 可微處,四種梯度是:
$$\frac{\partial R_i}{\partial\beta_0}=e_i,\qquad \frac{\partial R_i}{\partial\beta_k}=e_i a_{ik},$$ $$\frac{\partial R_i}{\partial w_{k0}}=e_i\beta_k g'(z_{ik}),\qquad \frac{\partial R_i}{\partial w_{kj}}=e_i\beta_k g'(z_{ik})x_{ij}.$$每個參數收到的梯度,包含輸出誤差、沿途權重、激發函數導數與輸入。 對完整資料的加總損失,將各筆梯度相加;若目標採平均損失,就再除以 n。 所有梯度都用同一個更新前的參數版本計算,最後才一起做 $\theta\leftarrow\theta-\rho\nabla R$。
輸出損失的導數為 $\partial R_i/\partial f_i=f_i-y_i=e_i$。 沿著 $\beta_k\to f_i\to R_i$ 的路徑:
$$\frac{\partial R_i}{\partial\beta_k}=\frac{\partial R_i}{\partial f_i}\frac{\partial f_i}{\partial\beta_k}=e_ia_{ik}.$$沿著 $w_{kj}\to z_{ik}\to a_{ik}\to f_i\to R_i$:
$$\frac{\partial R_i}{\partial w_{kj}} =\frac{\partial R_i}{\partial f_i}\frac{\partial f_i}{\partial a_{ik}} \frac{\partial a_{ik}}{\partial z_{ik}}\frac{\partial z_{ik}}{\partial w_{kj}} =e_i\beta_kg'(z_{ik})x_{ij}.$$截距的最後一個導數為 1,因此移除相應輸入因子便得到截距梯度。 計算時重用前向傳播儲存的 z、a 與輸出,不必對每個參數重新走完整個網路。
令 $z^{(\ell)}=W^{(\ell)}a^{(\ell-1)}+b^{(\ell)}$、$a^{(\ell)}=g_\ell(z^{(\ell)})$, 並定義 $\delta^{(\ell)}=\partial L/\partial z^{(\ell)}$。逐元素相乘記作 $\odot$,則:
$$\delta^{(\ell)}=(W^{(\ell+1)})^\top\delta^{(\ell+1)}\odot g_\ell'(z^{(\ell)}),$$ $$\frac{\partial L}{\partial W^{(\ell)}}=\delta^{(\ell)}(a^{(\ell-1)})^\top, \qquad\frac{\partial L}{\partial b^{(\ell)}}=\delta^{(\ell)}.$$以 softmax 機率 p 與 one-hot 類別 y 的交叉熵作輸出損失時,輸出層的 δ 就是 p−y。 這也是為什麼擬合要保留原始 logits:例如 PyTorch 的 CrossEntropyLoss 已包含 log-softmax,不要先做一次 softmax 再當作 logits 傳入。
$p_m=e^{z_m}/\sum_re^{z_r}$,因此 $\partial p_m/\partial z_k=p_m(\mathbf1_{m=k}-p_k)$。 對 $L=-\sum_my_m\log p_m$ 微分,並使用 $\sum_my_m=1$:
$$\frac{\partial L}{\partial z_k}=-\sum_my_m(\mathbf1_{m=k}-p_k)=p_k-y_k.$$隱藏層 δ 的公式則把每個後續單元的影響加總,再乘上本層的激發函數導數。
Ridge 懲罰把權重平方和加進目標,例如對多類別分類:
$$R(\theta;\lambda)=-\sum_i\sum_my_{im}\log p_m(x_i)+\lambda\sum_{j\in J}\theta_j^2, \qquad\lambda\ge0.$$J 是決定要懲罰的參數集合;不一定包含所有截距或輸出層權重。 受懲罰參數的梯度多出 $2\lambda\theta_j$。不同軟體的損失採加總或平均、懲罰有無 1/2,會影響 λ 的數值對應。
若定義 $R=\frac1n\sum_iR_i$,隨機抽取大小 B 的批次,以 $\frac1B\sum_{i\in\mathcal B}\nabla R_i$ 估計梯度。 一個 epoch 表示大致使用完整訓練集一次;48,000 筆資料、批次 128,約更新 375 次。 層數、層寬、學習率、批次大小、λ、dropout 比率與 epoch 數,都應用訓練/驗證資料決定,測試集留作最後評估。
來源:ISLP §10.7.1–10.7.4,印刷 pp.428–431,式 10.26–10.31;多層 δ 與 softmax 微分是依同一連鎖律展開的本站補充。 PyTorch CrossEntropyLoss 輸入規格。
圖中的 $R(\beta)=\sin\beta+\beta/10$ 滿足 $|R''(\beta)|\le1$,滑桿 0.02–1.6 在下降步長範圍內。 但它在整條實數線上沒有下界;β 趨向負無限時 R 也趨向負無限。 圖中兩個谷底的比較只限顯示區間,不能稱為整條實數線上的全域最小值。
模型更大時,測試誤差不一定只升不降;但模型大小也不能代替驗證。先建立簡單基準,再用獨立資料判斷增加複雜度是否有幫助。
從第 2 章開始,這本書一直在講同一件事:測試誤差對模型彈性是 U 形的, 因此把訓練誤差壓到 0 後,仍需檢查泛化表現。§10.8 進一步討論雙下降現象。
設定很簡單,用的還是第 7 章的自然樣條,跟神經網路無關: n = 20 筆資料來自 Y = sin(X) + ε,X 均勻分布在 [−5, 5]、ε 的標準差是 0.3。 然後擬合自由度 d 的自然樣條,讓 d 從 2 一路加到 100。
d = 20 時自由度等於樣本數,樣條剛好穿過每一個點,訓練誤差變成 0: 這就是內插門檻。d 再往上,最小平方解不再唯一(有無限多組係數都能穿過), 課本挑的是係數平方和最小的那一組,也就是最小範數解。
這跟深度學習的關係在最後一段:訓練神經網路時我們常常用遠多於樣本數的參數, 而且真的能把訓練誤差壓到 0 還表現得不錯。ISLP 的解釋是 最佳化方法的隱含偏好也會影響最後選到的內插解。例如平方損失的線性模型從零初始化,採適當步長的梯度下降收斂時可得到最小歐氏範數解;一般神經網路的 SGD 不保證得到最小範數或最平滑解。 是否泛化良好仍要由資料、模型、正則化與獨立評估判斷。
順帶把 §10.6 的建議收在這裡。ISLP 對「該不該用深度學習」的答案是: 先跑簡單模型當基準,讓深度學習去證明自己值得。 Hitters 那個例子就是示範:三個模型表現相近時,選看得懂的那個。 CIFAR 的影像具有空間結構,適合發揮 CNN 的優勢;文字分類仍要實測詞袋的線性基準。 ISLP 圖 10.11 的 IMDB 比較中,lasso 邏輯斯迴歸與兩隱藏層網路的測試準確率就相近。
下面哪一句符合 ISLP §10.8 的說明?
下面幾題取自 ISLP §10.10 的課後習題,題號都對得回課本。先自己想過再點選項; 每個選項都有解說;需要完整解答時,可查閱下面2個站。
參數計算、softmax 性質與模型結果的練習,已放在各節相應的收合延伸中。第一輪先確認你能說明各種架構保留什麼資訊,以及訓練和驗證各負責什麼。
需要核對完整公式、比較表或實作時,再展開下方速查。
考前把這一頁掃過去就好。這一章不在考試範圍,但它補充了 ISLP 的神經網路主題。
| 架構 | 適合什麼輸入 | 關鍵構造 | 權重共享嗎 | ISLP 節次 |
|---|---|---|---|---|
| 單層/多層全連接 | 沒有特殊結構的表格資料 | 隱藏層 + 激發函數 | 沒有 | §10.1–10.2 |
| 卷積網路(CNN) | 影像等有空間結構的資料 | 卷積 + 池化 | 有,在空間上 | §10.3 |
| 遞迴網路(RNN/LSTM) | 文字、時間序列等有順序的資料 | 隱藏狀態逐步更新 | 有,在時間上 | §10.5 |
| 詞袋 + 全連接 | 文件(丟掉詞序) | 出現與否的長向量 | 不適用 | §10.4 |
| 資料 | 模型 | 指標 | 數值 |
|---|---|---|---|
| Hitters | 線性迴歸 | 測試 MAE | 259.72 |
| Hitters | lasso(10 折 CV) | 測試 MAE | 235.68 |
| Hitters | 單層網路(50 單元、dropout 0.4) | 測試 MAE | 221.83 |
| MNIST | 多元邏輯斯迴歸 | 測試準確率 | 0.9161 |
| MNIST | 兩層網路(256/128) | 測試準確率 | 0.9620 |
| CIFAR-100 | 四組卷積區塊 | 測試準確率 | 0.4270 |
| IMDB | 詞袋 + 兩層網路 | 測試準確率 | 0.8450 |
| IMDB | LSTM | 測試準確率 | 0.8400 |
| NYSE | 線性 AR(落後 5 期) | 測試 R² | 0.4129 |
| NYSE | 線性 AR + 星期幾 | 測試 R² | 0.4596 |
| NYSE | RNN(12 維隱藏狀態) | 測試 R² | 0.4150 |
| NYSE | 非線性 AR | 測試 R² | 0.4660 |
這些是官方 lab 的實跑結果, 跟課本表格的數字不一樣:Table 10.1 的 MNIST 錯誤率是 1.8%(此處 3.8%), Table 10.2 的 Hitters MAE 是線性 254.7/lasso 252.3/神經網路 257.4。 差別來自切分、epoch 數與套件版本。引用時要說清楚是哪一組。
| 名稱 | 式子 | 備註 |
|---|---|---|
| 單層網路 | $f(X) = \beta_0 + \sum_k \beta_k g(w_{k0} + \sum_j w_{kj}X_j)$ | 式 10.1 |
| ReLU | $g(z) = \max(0, z)$ | 式 10.5 |
| Sigmoid | $g(z) = e^z/(1+e^z)$ | 式 10.3,就是邏輯斯函數 |
| Softmax | $f_m(X) = e^{Z_m} / \sum_\ell e^{Z_\ell}$ | 式 10.13,加常數不變 |
| 交叉熵 | $-\sum_i \sum_m y_{im} \log f_m(x_i)$ | 式 10.14,M = 2 時退回邏輯斯 |
| 平方誤差目標 | $R(\theta) = \tfrac12 \sum_i (y_i - f_\theta(x_i))^2$ | 式 10.25,一般非凸 |
| 梯度下降更新 | $\theta \leftarrow \theta - \rho \nabla R(\theta)$ | 式 10.27,ρ 是學習率 |
| 全連接層參數量 | $(a+1) \times b$ | a 個輸入接到 b 個輸出,+1 是偏置 |
| 卷積層參數量 | $(k^2 c_{in} + 1) \times c_{out}$ | 跟影像大小無關 |
model.eval(),否則 dropout 還開著、
預測會帶隨機性。固定隨機種子:非凸最佳化換個種子就換個答案,
官方 lab 用 seed_everything 加 deterministic=True。
詞彙卡整理本章講義與 ISLP 第 10 章中常用的統計或機器學習專有名詞,正面附英文名稱。 先看正面的術語,試著說出定義,再翻面核對。可以洗牌複習,也可以搭配本章例子練習解釋。