{"notes":[{"id":"classic-cnns/resnet-v2","category":"classic-cnns","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"ResNet v2","subtitle":"捷徑要乾淨","author":"Z. Yuan","paperDate":"2016-03-16","publishedOn":"2026-02-14","world":"external/resnet-v2","paperTitle":"Identity Mappings in Deep Residual Networks","paperUrl":"https://arxiv.org/abs/1603.05027","bibliography":{"title":"Identity Mappings in Deep Residual Networks","authors":["Kaiming He","Xiangyu Zhang","Shaoqing Ren","Jian Sun"],"url":"https://arxiv.org/abs/1603.05027","pdfUrl":"https://arxiv.org/pdf/1603.05027v3","codeUrl":null,"preprint":{"id":"1603.05027","submittedOn":"2016-03-16","url":"https://arxiv.org/abs/1603.05027"},"publication":null,"citation":"@misc{classiccnnsresnetv22016,\n  title = {{Identity Mappings in Deep Residual Networks}},\n  author = {Kaiming He and Xiangyu Zhang and Shaoqing Ren and Jian Sun},\n  year = {2016},\n  eprint = {1603.05027},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1603.05027}\n}\n","citationPath":"/content/papers/citations/classic-cnns/resnet-v2.3d311a21e308.bib"},"thumbnail":{"src":"/content/papers/assets/7eda4acdde3019e92c5b44f59917b1e493a5b11b5b8a63280d03b15787934ef5.png","width":967,"height":469},"locale":"zh-hant","path":"/content/papers/zh-hant/classic-cnns/resnet-v2.63e5bb8d2aec.md","headings":[{"id":"定義問題","text":"定義問題","depth":2},{"id":"解決問題","text":"解決問題","depth":2},{"id":"兩個恆等映射","text":"兩個恆等映射","depth":3},{"id":"捷徑上多一點東西會怎樣","text":"捷徑上多一點東西會怎樣？","depth":3},{"id":"相加之後的-relu-該放哪","text":"相加之後的 ReLU 該放哪？","depth":3},{"id":"換個角度看pre-activation","text":"換個角度看：pre-activation","depth":3},{"id":"討論","text":"討論","depth":2},{"id":"越深差距越大","text":"越深，差距越大","depth":3},{"id":"和其他方法比","text":"和其他方法比","depth":3},{"id":"結論","text":"結論","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/resnet","relation":"referenced","topic":""},{"id":"classic-cnns/highway-networks","relation":"referenced","topic":""},{"id":"classic-cnns/inception-v4","relation":"referenced","topic":""}]},{"id":"classic-cnns/resnet","category":"classic-cnns","legacyPath":"classic-cnns/1512-resnet","legacySlug":"1512-resnet","legacyPaths":[],"title":"ResNet","subtitle":"卷積網路 100 層","author":"Z. Yuan","paperDate":"2015-12-10","publishedOn":"2024-08-08","paperTitle":"Deep Residual Learning for Image Recognition","paperUrl":"https://arxiv.org/abs/1512.03385","bibliography":{"title":"Deep Residual Learning for Image Recognition","authors":["Kaiming He","Xiangyu Zhang","Shaoqing Ren","Jian Sun"],"url":"https://arxiv.org/abs/1512.03385","pdfUrl":"https://arxiv.org/pdf/1512.03385","codeUrl":null,"preprint":{"id":"1512.03385","submittedOn":"2015-12-10","url":"https://arxiv.org/abs/1512.03385"},"publication":{"venue":"CVPR","year":2016,"kind":"conference","url":"https://doi.org/10.1109/cvpr.2016.90"},"citation":"@misc{classiccnnsresnet2015,\n  title = {{Deep Residual Learning for Image Recognition}},\n  author = {Kaiming He and Xiangyu Zhang and Shaoqing Ren and Jian Sun},\n  year = {2015},\n  eprint = {1512.03385},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1512.03385}\n}\n","citationPath":"/content/papers/citations/classic-cnns/resnet.cf4014e8baae.bib"},"thumbnail":{"src":"/content/papers/assets/b8fe87fe757249ea6d7bb667fef3196754b9f80e28bf842a69b540ca94585d08.jpg","width":1224,"height":408},"locale":"zh-hant","path":"/content/papers/zh-hant/classic-cnns/resnet.859f62e9e37d.md","headings":[{"id":"定義問題","text":"定義問題","depth":2},{"id":"解決問題","text":"解決問題","depth":2},{"id":"什麼是殘差","text":"什麼是殘差？","depth":3},{"id":"殘差學習","text":"殘差學習","depth":3},{"id":"殘差模塊","text":"殘差模塊","depth":3},{"id":"網路架構","text":"網路架構","depth":3},{"id":"參數配置","text":"參數配置","depth":3},{"id":"討論","text":"討論","depth":2},{"id":"resnet-18-vs-resnet-34","text":"ResNet-18 vs ResNet-34","depth":3},{"id":"更深的瓶頸架構","text":"更深的瓶頸架構","depth":3},{"id":"在-imagenet-上的表現","text":"在 ImageNet 上的表現","depth":3},{"id":"結論","text":"結論","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/vgg","relation":"background","topic":"如何訓練更深的卷積網路"},{"id":"classic-cnns/densenet","relation":"next","topic":"如何訓練更深的卷積網路"}]},{"id":"classic-cnns/highway-networks","category":"classic-cnns","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"Highway Networks","subtitle":"殘差的前夜","author":"Z. Yuan","paperDate":"2015-05-03","publishedOn":"2025-11-03","world":"external/highway-networks","paperTitle":"Highway Networks","paperUrl":"https://arxiv.org/abs/1505.00387","bibliography":{"title":"Highway Networks","authors":["Rupesh Kumar Srivastava","Klaus Greff","Jürgen Schmidhuber"],"url":"https://arxiv.org/abs/1505.00387","pdfUrl":"https://arxiv.org/pdf/1505.00387v2","codeUrl":null,"preprint":{"id":"1505.00387","submittedOn":"2015-05-03","url":"https://arxiv.org/abs/1505.00387"},"publication":null,"citation":"@misc{classiccnnshighwaynetworks2015,\n  title = {{Highway Networks}},\n  author = {Rupesh Kumar Srivastava and Klaus Greff and Jürgen Schmidhuber},\n  year = {2015},\n  eprint = {1505.00387},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1505.00387}\n}\n","citationPath":"/content/papers/citations/classic-cnns/highway-networks.f7d3ef9547ef.bib"},"thumbnail":{"src":"/content/papers/assets/2cef37bd2a2388f57a76965431810cb86f976db701ba1647b75c81c9a59ac779.png","width":1344,"height":360},"locale":"zh-hant","path":"/content/papers/zh-hant/classic-cnns/highway-networks.29bb1472915e.md","headings":[{"id":"定義問題","text":"定義問題","depth":2},{"id":"解決問題","text":"解決問題","depth":2},{"id":"加兩道閘門","text":"加兩道閘門","depth":3},{"id":"一開始先偏向直接通過","text":"一開始先偏向「直接通過」","depth":3},{"id":"討論","text":"討論","depth":2},{"id":"越深越好訓練嗎","text":"越深越好訓練嗎？","depth":3},{"id":"好訓練那準確率呢","text":"好訓練，那準確率呢？","depth":3},{"id":"閘門學到了什麼","text":"閘門學到了什麼？","depth":3},{"id":"結論","text":"結論","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/resnet","relation":"referenced","topic":""}]},{"id":"classic-cnns/inception-v4","category":"classic-cnns","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"Inception-v4","subtitle":"快很多，準一點","author":"Z. Yuan","paperDate":"2016-02-23","publishedOn":"2026-01-27","world":"external/inception-v4","paperTitle":"Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning","paperUrl":"https://arxiv.org/abs/1602.07261","bibliography":{"title":"Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning","authors":["Christian Szegedy","Sergey Ioffe","Vincent Vanhoucke","Alex Alemi"],"url":"https://arxiv.org/abs/1602.07261","pdfUrl":"https://arxiv.org/pdf/1602.07261v2","codeUrl":null,"preprint":{"id":"1602.07261","submittedOn":"2016-02-23","url":"https://arxiv.org/abs/1602.07261"},"publication":null,"citation":"@misc{classiccnnsinceptionv42016,\n  title = {{Inception-v4, Inception-ResNet and the Impact of Residual Connections on Learning}},\n  author = {Christian Szegedy and Sergey Ioffe and Vincent Vanhoucke and Alex Alemi},\n  year = {2016},\n  eprint = {1602.07261},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1602.07261}\n}\n","citationPath":"/content/papers/citations/classic-cnns/inception-v4.ed8e0294ae0b.bib"},"thumbnail":{"src":"/content/papers/assets/cc8335c4ba4672514d3dd5e9953719d52b4f8fdd0af994c76722874543fcb864.png","width":666,"height":656},"locale":"zh-hant","path":"/content/papers/zh-hant/classic-cnns/inception-v4.a69e9457230b.md","headings":[{"id":"定義問題","text":"定義問題","depth":2},{"id":"解決問題","text":"解決問題","depth":2},{"id":"卸下包袱inception-v4","text":"卸下包袱：Inception-v4","depth":3},{"id":"進場的那一段","text":"進場的那一段","depth":3},{"id":"把殘差接進-inception","text":"把殘差接進 Inception","depth":3},{"id":"縮小殘差穩住訓練","text":"縮小殘差，穩住訓練","depth":3},{"id":"訓練設定","text":"訓練設定","depth":3},{"id":"討論","text":"討論","depth":2},{"id":"殘差讓訓練快很多","text":"殘差讓訓練快很多","depth":3},{"id":"單一模型的成績","text":"單一模型的成績","depth":3},{"id":"集成","text":"集成","depth":3},{"id":"殘差連接是必需的嗎","text":"殘差連接是「必需」的嗎？","depth":3},{"id":"結論","text":"結論","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/resnet","relation":"referenced","topic":""},{"id":"classic-cnns/inception-v3","relation":"referenced","topic":""},{"id":"classic-cnns/resnet-v2","relation":"referenced","topic":""}]}],"text":"ResNet 讓 152 層的網路訓練得動，拿下 ILSVRC 2015。可是在 CIFAR-10 上，原論文的 1202 層 ResNet 錯誤率是 7.93%，反而比 110 層的 6.61% 差。\n\n殘差連接能讓網路變深，可是深到一千層，又出現了新的問題。\n\n2016 年 3 月，原班人馬 Kaiming He、Xiangyu Zhang、Shaoqing Ren 與 Jian Sun 放出這篇論文，後來發表在 ECCV 2016。這次他們回頭寫出殘差單元的傳遞公式，從公式裡找出訊號要怎麼走才最順，再照著改殘差單元。改完之後，1001 層的 ResNet 在 CIFAR-10 上做到 4.62% 的錯誤率。\n\n這個新版本，後來常被叫做 ResNet v2，或 pre-activation ResNet。\n\n\n> [!TIP]\n> \n> ResNet 原本的設計，可以先看我們的筆記：\n> \n> - **[[15.12] ResNet：卷積網路 100 層](/blog/papers/classic-cnns/resnet)**\n\n\n## 定義問題\n\n先把原本的殘差單元寫成一般的形式。第 $l$ 個單元的輸入是 $x_l$：\n\n$$\ny_l = h(x_l) + \\mathcal{F}(x_l, \\mathcal{W}_l), \\qquad x_{l+1} = f(y_l)\n$$\n\n$\\mathcal{F}$ 是殘差函數，例如兩層 $3\\times3$ 卷積；$h$ 是捷徑上的運算；$f$ 是相加之後的運算。原本的 ResNet 裡，$h(x_l) = x_l$ 是恆等映射，$f$ 是 ReLU。\n\n[![左邊兩個殘差單元的示意圖。(a) original：x_l 一路往下，右側分支依序是 weight、BN、ReLU、weight、BN，和捷徑相加後再經過 ReLU 得到 x_l+1。(b) proposed：右側分支依序是 BN、ReLU、weight、BN、ReLU、weight，相加之後直接得到 x_l+1。兩者的捷徑都畫成一條灰色的粗箭頭。右邊是 CIFAR-10 上 1001 層 ResNet 的訓練曲線：黃色是 original（錯誤率 7.61%），藍色是 proposed（錯誤率 4.92%）；虛線是訓練損失，實線是測試錯誤率，藍線的訓練損失在一開始就降得快很多](/content/papers/assets/7eda4acdde3019e92c5b44f59917b1e493a5b11b5b8a63280d03b15787934ef5.png)](/content/papers/assets/7eda4acdde3019e92c5b44f59917b1e493a5b11b5b8a63280d03b15787934ef5.png)\n\n*原論文 Figure 1，取自 [**v3 PDF 第 2 頁**](https://arxiv.org/pdf/1603.05027v3#page=2)。左：(a) 原本的殘差單元，(b) 本文提出的殘差單元；灰色箭頭是資訊最容易傳遞的路徑。右：CIFAR-10 上 1001 層 ResNet 的訓練曲線，虛線是訓練損失（左軸），實線是測試錯誤率（右軸）。*\n\n右邊的曲線把問題擺在眼前：同樣 1001 層，原本的設計在訓練初期損失降得很慢，最後的測試錯誤率是 7.61%；改過的設計一開始就降得很快，最後是 4.92%。\n\n左邊兩個單元用的元件完全一樣，差別只在順序：原本的 ReLU 放在相加之後，壓在捷徑上；新的設計把 BN 和 ReLU 都搬到權重層前面，相加之後什麼都不做。灰色的捷徑因此從頭到尾都沒有經過任何運算。\n\n為什麼這件事重要？作者的論證，要從把 $h$ 和 $f$ 都當成恆等映射開始。\n\n## 解決問題\n\n### 兩個恆等映射\n\n如果 $f$ 也是恆等映射，$x_{l+1} = y_l$，上面的式子就變成：\n\n$$\nx_{l+1} = x_l + \\mathcal{F}(x_l, \\mathcal{W}_l)\n$$\n\n一路展開到更深的第 $L$ 個單元：\n\n$$\nx_L = x_l + \\sum_{i=l}^{L-1} \\mathcal{F}(x_i, \\mathcal{W}_i)\n$$\n\n這個式子說的是：任何一個深層的特徵 $x_L$，都等於某個淺層的特徵 $x_l$，加上中間所有殘差函數的輸出。對照一般的網路，$x_L$ 是一連串矩陣乘法的結果，大約是 $\\prod_i W_i\\, x_0$（忽略 BN 和 ReLU）。一個是加起來，一個是乘起來。\n\n反向傳播時也一樣。設損失是 $\\mathcal{E}$，由連鎖律：\n\n$$\n\\frac{\\partial \\mathcal{E}}{\\partial x_l}\n= \\frac{\\partial \\mathcal{E}}{\\partial x_L}\\frac{\\partial x_L}{\\partial x_l}\n= \\frac{\\partial \\mathcal{E}}{\\partial x_L}\\left(1 + \\frac{\\partial}{\\partial x_l}\\sum_{i=l}^{L-1}\\mathcal{F}(x_i, \\mathcal{W}_i)\\right)\n$$\n\n括號裡的 1，讓 $\\partial\\mathcal{E}/\\partial x_L$ 不經過任何權重層，直接送到淺層的 $x_l$。另一項要經過權重層，但它不太可能對一個批次裡的每個樣本都剛好是 $-1$，把整個括號抵消掉。所以就算權重很小，梯度也不會消失。\n\n這兩個漂亮的性質，都建立在兩個條件上：捷徑 $h$ 是恆等映射，相加之後的 $f$ 也是恆等映射。換成圖上的說法，就是灰色箭頭上除了相加，不能有任何運算。\n\n作者接下來分兩部分檢查：先動捷徑 $h$，再動相加之後的 $f$。\n\n### 捷徑上多一點東西會怎樣？\n\n最簡單的破壞方式，是讓捷徑乘上一個常數 $\\lambda_l$：$h(x_l) = \\lambda_l x_l$。照同樣的方法展開，反向傳播的式子變成：\n\n$$\n\\frac{\\partial \\mathcal{E}}{\\partial x_l}\n= \\frac{\\partial \\mathcal{E}}{\\partial x_L}\\left(\\prod_{i=l}^{L-1}\\lambda_i + \\frac{\\partial}{\\partial x_l}\\sum_{i=l}^{L-1}\\hat{\\mathcal{F}}(x_i, \\mathcal{W}_i)\\right)\n$$\n\n$\\hat{\\mathcal{F}}$ 把那些常數吸收進去了。原本的 1，變成了一串 $\\lambda$ 的連乘。網路很深時，只要每個 $\\lambda$ 都大於 1，這一項會指數爆炸；都小於 1，它會指數消失，梯度只能改走權重層。\n\nResNet-110 有 54 個殘差單元。我們把殘差函數設得很小，只看捷徑的效果：\n\n```python\nimport torch\n\ntorch.manual_seed(0)\nD, units = 64, 54                                       # ResNet-110 有 54 個殘差單元\nWs = [torch.randn(D, D) * 0.01 for _ in range(units)]   # 刻意讓殘差函數很小\n\nfor lam in (1.0, 0.9, 0.5, 1.1):\n    x0 = torch.randn(D, requires_grad=True)\n    x = x0\n    for W in Ws:\n        x = lam * x + torch.relu(x) @ W                 # 捷徑乘上 λ\n    x.sum().backward()\n    print(f\"λ = {lam}：回到第一層的梯度約 {x0.grad.abs().mean().item():.3g}，λ^54 = {lam ** units:.3g}\")\n```\n\n```text\nλ = 1.0：回到第一層的梯度約 0.954，λ^54 = 1\nλ = 0.9：回到第一層的梯度約 0.00322，λ^54 = 0.00338\nλ = 0.5：回到第一層的梯度約 5.67e-17，λ^54 = 5.55e-17\nλ = 1.1：回到第一層的梯度約 162，λ^54 = 172\n```\n\n梯度幾乎就是 $\\lambda^{54}$。$\\lambda = 0.9$ 看起來只打了九折，經過 54 個單元之後只剩千分之三；$\\lambda = 0.5$ 則小到 $10^{-17}$。換成閘門或 $1\\times1$ 卷積這類更複雜的捷徑，連乘的就變成每個捷徑的導數，一樣可能卡住訊號。\n\n作者接著在 CIFAR-10 的 ResNet-110 上實際比較了幾種捷徑：\n\n[![六個殘差單元的示意圖，右側分支都是 3x3 conv、ReLU、3x3 conv，差別在捷徑上：(a) original 沒有任何運算；(b) constant scaling 在捷徑和分支上各乘 0.5；(c) exclusive gating 用 1x1 conv 加 sigmoid 算出閘門，分支乘上閘門值、捷徑乘上 1 減閘門值；(d) shortcut-only gating 只在捷徑上乘 1 減閘門值；(e) conv shortcut 捷徑上是 1x1 conv；(f) dropout shortcut 捷徑上是 dropout。每個單元相加之後都接 ReLU](/content/papers/assets/7710a267ec379977c4b41b07fbb2532dd44111584b6c0542b7ce9e96556e4f13.png)](/content/papers/assets/7710a267ec379977c4b41b07fbb2532dd44111584b6c0542b7ce9e96556e4f13.png)\n\n*原論文 Figure 2，取自 [**v3 PDF 第 5 頁**](https://arxiv.org/pdf/1603.05027v3#page=5)。Table 1 用到的各種捷徑。為了簡化，圖上沒有畫出每個權重層後面的 BN。*\n\n| 捷徑 | 捷徑上的係數 | 分支 $\\mathcal{F}$ 上的係數 | 錯誤率 |\n| --- | --- | --- | ---: |\n| (a) 原本的恆等捷徑 | 1 | 1 | **6.61%** |\n| (b) 常數縮放 | 0 | 1 | 失敗（等於一般網路） |\n| (b) 常數縮放 | 0.5 | 1 | 失敗 |\n| (b) 常數縮放 | 0.5 | 0.5 | 12.35% |\n| (c) 互斥閘門，$b_g$ 初始為 $-6$ | $1-g(x)$ | $g(x)$ | 8.70% |\n| (c) 互斥閘門，$b_g$ 初始為 0 到 $-5$ | $1-g(x)$ | $g(x)$ | 失敗 |\n| (d) 只在捷徑上加閘門，$b_g$ 初始為 0 | $1-g(x)$ | 1 | 12.86% |\n| (d) 只在捷徑上加閘門，$b_g$ 初始為 $-6$ | $1-g(x)$ | 1 | 6.91% |\n| (e) $1\\times1$ 卷積捷徑 | $1\\times1$ 卷積 | 1 | 12.22% |\n| (f) dropout 捷徑 | dropout 0.5 | 1 | 失敗 |\n\n*表：摘自原論文 Table 1 的部分列。CIFAR-10 測試集，ResNet-110，五次訓練的中位數；錯誤率超過 20% 記為「失敗」。這組實驗相加之後仍用 ReLU。*\n\n幾個值得注意的地方：\n\n- **常數縮放 0.5**：分支不縮放時訓練不起來；分支也乘 0.5（類似閘門固定住的 Highway），可以收斂，但錯誤率 12.35%，接近基準的兩倍。\n- **互斥閘門**就是 Highway Networks 的做法。閘門的偏置初始值非常關鍵，作者在 0 到 $-10$ 之間搜尋，最好的 $-6$ 也只做到 8.70%。\n- **只在捷徑上加閘門**時，偏置初始為 $-6$ 會讓 $1-g(x)$ 接近 1，捷徑幾乎就是恆等映射，結果 6.91% 也最接近基準。\n- **$1\\times1$ 卷積捷徑**在原本 34 層的 ResNet 上表現不錯（ResNet 論文裡的選項 C），堆到 54 個單元卻變成 12.22%。作者在 ImageNet 的 ResNet-101 上也看到類似的現象。\n- **dropout 捷徑**在統計上等於把捷徑乘上期望值 0.5，和常數縮放一樣卡住訊號。\n\n\n> [!TIP]\n> \n> 互斥閘門的原型，可以看我們的筆記：\n> \n> - **[[15.05] Highway Networks：殘差的前夜](/blog/papers/classic-cnns/highway-networks)**\n\n\n閘門和 $1\\times1$ 卷積都多了參數，表達能力理論上應該更強；只在捷徑上加閘門、或用 $1\\times1$ 卷積時，解空間還包含恆等捷徑，只要學成恆等映射就行。可是它們的**訓練**錯誤率都比較高。所以變差的原因出在最佳化，和表達能力無關。\n\n### 相加之後的 ReLU 該放哪？\n\n上一組實驗裡，相加之後的 $f$ 都還是 ReLU，所以推導只是近似成立。接下來要處理 $f$。\n\n要讓 $f$ 變成恆等映射，只能重新排列 ReLU 和 BN 的位置。作者試了這幾種排法：\n\n[![五個殘差單元的示意圖，元件相同、順序不同。(a) original：weight、BN、ReLU、weight、BN，相加後 ReLU。(b) BN after addition：weight、BN、ReLU、weight，相加後 BN 再 ReLU。(c) ReLU before addition：weight、BN、ReLU、weight、BN、ReLU，再相加。(d) ReLU-only pre-activation：ReLU、weight、BN、ReLU、weight、BN，再相加。(e) full pre-activation：BN、ReLU、weight、BN、ReLU、weight，再相加](/content/papers/assets/f032506b6dda998779a8abf2fee9cbf44371ac4a2c4ebf8c93d834286bbb7501.png)](/content/papers/assets/f032506b6dda998779a8abf2fee9cbf44371ac4a2c4ebf8c93d834286bbb7501.png)\n\n*原論文 Figure 4，取自 [**v3 PDF 第 8 頁**](https://arxiv.org/pdf/1603.05027v3#page=8)。Table 2 用到的各種激活位置；所有單元的元件都一樣，只有順序不同。*\n\n| 排法 | ResNet-110 | ResNet-164 |\n| --- | ---: | ---: |\n| (a) 原本的殘差單元 | 6.61% | 5.93% |\n| (b) BN 放在相加之後 | 8.17% | 6.50% |\n| (c) ReLU 放在相加之前 | 7.84% | 6.14% |\n| (d) 只有 ReLU 前移 | 6.71% | 5.91% |\n| (e) 完整的 pre-activation | **6.37%** | **5.46%** |\n\n*表：摘自原論文 Table 2。CIFAR-10 測試集錯誤率。ResNet-164 用的是瓶頸結構（$1\\times1$、$3\\times3$、$1\\times1$），計算量和兩層 $3\\times3$ 的單元相近。*\n\n**(b) BN 放在相加之後**是反方向的實驗：讓 $f$ 包含 BN 和 ReLU。結果明顯變差。BN 現在會改變捷徑上的訊號，訓練初期的損失很難降下來。\n\n**(c) ReLU 放在相加之前**是讓 $f$ 變成恆等映射最直接的做法，結果也變差了。問題在於，ReLU 放在分支的最後，殘差函數的輸出就永遠不會是負的。直覺上，「殘差」應該可正可負；只能是正的，訊號就會一路單調增加。我們看看兩種排法疊十個單元之後的樣子：\n\n```python\nimport torch\nimport torch.nn as nn\n\ntorch.manual_seed(0)\nc = 16\n\ndef relu_before_add():          # Fig. 4(c)：ReLU 移到相加之前\n    return nn.Sequential(nn.Conv2d(c, c, 3, padding=1), nn.BatchNorm2d(c), nn.ReLU(),\n                         nn.Conv2d(c, c, 3, padding=1), nn.BatchNorm2d(c), nn.ReLU())\n\ndef full_preact():              # Fig. 4(e)：BN、ReLU 都放在權重層前面\n    return nn.Sequential(nn.BatchNorm2d(c), nn.ReLU(), nn.Conv2d(c, c, 3, padding=1),\n                         nn.BatchNorm2d(c), nn.ReLU(), nn.Conv2d(c, c, 3, padding=1))\n\nx0 = torch.randn(8, c, 16, 16)\nfor name, make in [(\"ReLU 在相加前\", relu_before_add), (\"完整 pre-activation\", full_preact)]:\n    x, lows, means = x0, [], []\n    for unit in range(10):\n        r = make()(x)\n        lows.append(r.min().item())\n        x = x + r\n        means.append(x.mean().item())\n    print(f\"{name}：殘差的最小值 {min(lows):.2f}；輸出平均值 {means[0]:.2f} → {means[4]:.2f} → {means[9]:.2f}\")\n```\n\n```text\nReLU 在相加前：殘差的最小值 0.00；輸出平均值 0.38 → 1.97 → 3.96\n完整 pre-activation：殘差的最小值 -2.33；輸出平均值 -0.01 → 0.07 → 0.09\n```\n\nReLU 放在相加前，殘差最小就是 0，每加一個單元，平均值就往上墊高一截；pre-activation 的殘差有正有負，平均值停在 0 附近。\n\n### 換個角度看：pre-activation\n\n剩下兩種排法，來自一個觀念上的轉換。\n\n原本的設計裡，相加之後的激活 $f$ 會同時影響下一個單元的兩條路：\n\n$$\ny_{l+1} = f(y_l) + \\mathcal{F}(f(y_l), \\mathcal{W}_{l+1})\n$$\n\n如果讓這個激活只作用在殘差分支上，捷徑不經過它：\n\n$$\ny_{l+1} = y_l + \\mathcal{F}(\\hat{f}(y_l), \\mathcal{W}_{l+1})\n$$\n\n換個符號，就是 $x_{l+1} = x_l + \\mathcal{F}(\\hat{f}(x_l), \\mathcal{W}_l)$。相加之後什麼都沒有，$f$ 變成了恆等映射；原本「上一個單元的輸出激活」，變成了「下一個單元的輸入激活」。\n\n[![三欄示意圖。(a) 原本的殘差單元，相加之後有 act.，這個 act. 同時影響下一個單元的捷徑與分支。(b) 把相加之後的 act. 只放在通往權重的分支上（紅框標出），捷徑繞過它。(c) 重新切分單元的邊界之後，等價於每個單元在 weight 之前先做 act. 的 pre-activation 殘差單元，相加之後沒有任何運算](/content/papers/assets/1a7a520a803ed65de475f2ee4bc5ade9b1833de9aefd758c5ef57153e5d087d2.png)](/content/papers/assets/1a7a520a803ed65de475f2ee4bc5ade9b1833de9aefd758c5ef57153e5d087d2.png)\n\n*原論文 Figure 5，取自 [**v3 PDF 第 10 頁**](https://arxiv.org/pdf/1603.05027v3#page=10)。把相加之後的激活只用在權重分支上，等價於建立一個 pre-activation 殘差單元。*\n\n圖上的 (b) 到 (c) 只是把單元的邊界重新切一次。作者也點出，這種前後之分只在有相加的分支結構裡才有意義；一般的 $N$ 層網路有 $N-1$ 個激活，叫它前激活或後激活都一樣。\n\n照這個想法，Figure 4 的 (d) 只把 ReLU 移到前面，結果和原本的設計差不多；作者推測，這個 ReLU 沒有和 BN 搭在一起，得不到 BN 的好處。(e) 把 BN 和 ReLU 都移到權重層前面，成績明顯變好。這就是本文提出的單元。\n\n## 討論\n\n### 越深，差距越大\n\n| 資料集 | 網路 | 原本的單元 | pre-activation |\n| --- | --- | ---: | ---: |\n| CIFAR-10 | ResNet-110（每個單元一層） | 9.90% | 8.91% |\n| CIFAR-10 | ResNet-110 | 6.61% | 6.37% |\n| CIFAR-10 | ResNet-164 | 5.93% | 5.46% |\n| CIFAR-10 | ResNet-1001 | 7.61% | **4.92%** |\n| CIFAR-100 | ResNet-164 | 25.16% | 24.33% |\n| CIFAR-100 | ResNet-1001 | 27.82% | **22.71%** |\n\n*表：摘自原論文 Table 3。ResNet-1001 是瓶頸結構，共 333 個殘差單元，每種特徵圖大小各 111 個。*\n\npre-activation 在每一組都比較好，而且網路越深，差距越大：1001 層時，CIFAR-10 從 7.61% 降到 4.92%，CIFAR-100 從 27.82% 降到 22.71%。\n\n作者認為好處來自兩方面。\n\n**第一，更容易最佳化**。這在 1001 層時最明顯（Figure 1 右）。$f$ 是 ReLU 時，負的訊號會被截掉；單元很多時，前面的公式就不再是好的近似。164 層的網路受的影響小得多：訓練初期曲線稍微受挫，很快就恢復。作者監看了網路的反應，發現訓練一陣子之後，權重會調整到讓 $y_l$ 大多大於 0，ReLU 很少截到東西；$x_l$ 經過上一個 ReLU 本來就非負，只有 $\\mathcal{F}$ 是很大的負值時，$y_l$ 才會小於 0。到了一千層，截斷就頻繁得多。\n\n**第二，減少過擬合**。pre-activation 版本收斂時的訓練損失略高，測試錯誤率卻更低。作者推測這是 BN 的正則化效果：原本的單元裡，BN 正規化過的訊號馬上和捷徑相加，送進下一個權重層的其實是沒有正規化的訊號；pre-activation 版本裡，每個權重層的輸入都先經過 BN。\n\n### 和其他方法比\n\n在 CIFAR 上，作者的 ResNet-1001 在 CIFAR-10 做到 4.92%（五次中位數），批次大小改成 64 時是 4.62%；CIFAR-100 是 22.71%。他們特別說明，這些結果沒有特別調整寬度或濾波器大小，也沒用 dropout 這類對小資料集很有效的正則化，靠的只有「更深」。\n\nImageNet 上，作者先注意到一個評估細節：原本的 ResNet 訓練時把短邊縮放到 256 到 480 之間，測試時卻在短邊 256 的影像上取 $224\\times224$ 的裁切，這對 ResNet 不利。所以這次改成在短邊 320 的影像上取一個 $320\\times320$ 的裁切；ResNet 是全卷積的，可以直接吃更大的輸入，這個大小也接近 Inception-v3 的 299。\n\n| 方法 | 資料增強 | Top-1 錯誤率 | Top-5 錯誤率 |\n| --- | --- | ---: | ---: |\n| ResNet-152，原本的單元 | 縮放 | 21.3% | 5.5% |\n| ResNet-152，pre-activation | 縮放 | 21.1% | 5.5% |\n| ResNet-200，原本的單元 | 縮放 | 21.8% | 6.0% |\n| ResNet-200，pre-activation | 縮放 | 20.7% | 5.3% |\n| ResNet-200，pre-activation | 縮放＋長寬比 | **20.1%** | **4.8%** |\n| Inception-v3 | 縮放＋長寬比 | 21.2% | 5.6% |\n\n*表：摘自原論文 Table 5。ILSVRC 2012 驗證集，單一裁切；ResNet 以 $224\\times224$ 訓練、$320\\times320$ 測試，Inception-v3 訓練與測試都是 $299\\times299$。*\n\nResNet-152 換成 pre-activation，只從 21.3% 進步到 21.1%，因為它本來就沒有明顯的泛化問題。ResNet-200 不一樣：原本的單元錯誤率 21.8%，比 ResNet-152 還差，可是它的訓練錯誤率比 ResNet-152 低，也就是過擬合了。換成 pre-activation 之後是 20.7%，比兩個 ResNet-152 都好。\n\n作者也在 ImageNet 的 ResNet-101 上跑完了「BN 放在相加之後」的版本：單一裁切錯誤率 24.6%／7.5%，比原本的 23.6%／7.1% 差，和 CIFAR 上的結果一致。\n\n\n> [!TIP]\n> \n> 作者在文中也提到同一時期的 Inception-ResNet-v2，並預期這些發現對它同樣有幫助：\n> \n> - **[[16.02] Inception-v4：快很多，準一點](/blog/papers/classic-cnns/inception-v4)**\n\n\n計算量方面，模型的複雜度和深度成正比，1001 層大約是 100 層的十倍。CIFAR 上的 ResNet-1001 用兩張 GPU 訓練約 27 小時；ImageNet 上的 ResNet-200 用八張 GPU 訓練約三週。\n\n## 結論\n\n這篇論文的結論可以縮成一句話：讓捷徑保持乾淨。捷徑上不要乘常數、不要加閘門、不要放卷積或 dropout；相加之後也不要再接 ReLU 或 BN。這樣，訊號在前向和反向傳播時，都能從任何一個單元直接走到另一個單元。\n\n實作上，這篇的改動很小：把殘差分支裡 BN、ReLU 的位置往前挪，相加之後什麼都不做。要訓練很深的 ResNet，或模型已經開始過擬合，可以優先試試 pre-activation 版本；淺一點的網路，兩種差別不大。\n\n「捷徑上什麼都別放」這個原則，幾年後在 Transformer 的 LayerNorm 上又被討論了一次，有興趣可以接著看 [Pre-LN](/blog/papers/transformers/pre-ln) 那篇。\n","imageSizes":{"/content/papers/assets/7eda4acdde3019e92c5b44f59917b1e493a5b11b5b8a63280d03b15787934ef5.png":{"width":967,"height":469},"/content/papers/assets/7710a267ec379977c4b41b07fbb2532dd44111584b6c0542b7ce9e96556e4f13.png":{"width":690,"height":659},"/content/papers/assets/f032506b6dda998779a8abf2fee9cbf44371ac4a2c4ebf8c93d834286bbb7501.png":{"width":965,"height":466},"/content/papers/assets/1a7a520a803ed65de475f2ee4bc5ade9b1833de9aefd758c5ef57153e5d087d2.png":{"width":967,"height":546}}}
