{"notes":[{"id":"classic-cnns/stochastic-depth","category":"classic-cnns","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"Stochastic Depth","subtitle":"今天這層請假","author":"Z. Yuan","paperDate":"2016-03-30","publishedOn":"2026-03-04","world":"external/stochastic-depth","paperTitle":"Deep Networks with Stochastic Depth","paperUrl":"https://arxiv.org/abs/1603.09382","bibliography":{"title":"Deep Networks with Stochastic Depth","authors":["Gao Huang","Yu Sun","Zhuang Liu","Daniel Sedra","Kilian Weinberger"],"url":"https://arxiv.org/abs/1603.09382","pdfUrl":"https://arxiv.org/pdf/1603.09382v3","codeUrl":null,"preprint":{"id":"1603.09382","submittedOn":"2016-03-30","url":"https://arxiv.org/abs/1603.09382"},"publication":null,"citation":"@misc{classiccnnsstochasticdepth2016,\n  title = {{Deep Networks with Stochastic Depth}},\n  author = {Gao Huang and Yu Sun and Zhuang Liu and Daniel Sedra and Kilian Weinberger},\n  year = {2016},\n  eprint = {1603.09382},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1603.09382}\n}\n","citationPath":"/content/papers/citations/classic-cnns/stochastic-depth.3716109ef477.bib"},"thumbnail":{"src":"/content/papers/assets/620e6ddf909f1f405e38b6055bd732ae4c4b7c208f147e00b870a56642020c02.png","width":963,"height":339},"locale":"zh-hant","path":"/content/papers/zh-hant/classic-cnns/stochastic-depth.9937daa4b790.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":2},{"id":"錯誤率和訓練時間","text":"錯誤率和訓練時間","depth":3},{"id":"一千兩百層","text":"一千兩百層","depth":3},{"id":"imagenet-上沒有贏","text":"ImageNet 上沒有贏","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/resnet-v2","relation":"referenced","topic":""},{"id":"classic-cnns/densenet","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/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/densenet","category":"classic-cnns","legacyPath":"classic-cnns/1608-densenet","legacySlug":"1608-densenet","legacyPaths":[],"title":"DenseNet","subtitle":"全部連起來","author":"Z. Yuan","paperDate":"2016-08-25","publishedOn":"2024-07-02","paperTitle":"Densely Connected Convolutional Networks","paperUrl":"https://arxiv.org/abs/1608.06993","bibliography":{"title":"Densely Connected Convolutional Networks","authors":["Gao Huang","Zhuang Liu","Laurens van der Maaten","Kilian Q. Weinberger"],"url":"https://arxiv.org/abs/1608.06993","pdfUrl":"https://arxiv.org/pdf/1608.06993","codeUrl":null,"preprint":{"id":"1608.06993","submittedOn":"2016-08-25","url":"https://arxiv.org/abs/1608.06993"},"publication":{"venue":"CVPR","year":2017,"kind":"conference","url":"https://arxiv.org/abs/1608.06993"},"citation":"@misc{classiccnnsdensenet2016,\n  title = {{Densely Connected Convolutional Networks}},\n  author = {Gao Huang and Zhuang Liu and Laurens van der Maaten and Kilian Q. Weinberger},\n  year = {2016},\n  eprint = {1608.06993},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1608.06993}\n}\n","citationPath":"/content/papers/citations/classic-cnns/densenet.6f28153b67f7.bib"},"thumbnail":{"src":"/content/papers/assets/4f073a0fd1fc5b7415ca19c48934d180f9043fddc08301819a50ceb1b0ebfc69.jpg","width":1184,"height":828},"locale":"zh-hant","path":"/content/papers/zh-hant/classic-cnns/densenet.1ac5b17fc8c5.md","headings":[{"id":"定義問題","text":"定義問題","depth":2},{"id":"解決問題","text":"解決問題","depth":2},{"id":"網路架構","text":"網路架構","depth":3},{"id":"平均池化","text":"平均池化","depth":3},{"id":"growth-rate","text":"Growth Rate","depth":3},{"id":"bottleneck-layers","text":"Bottleneck Layers","depth":3},{"id":"compression","text":"Compression","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":"background","topic":"如何訓練更深的卷積網路"}]}],"text":"訓練很深的網路，有一個兩難。\n\n淺的網路，訊號前向、反向都走得順，訓練也快，但表達能力有限。深的網路表達能力強，可是梯度會消失、前面算出的特徵會被一層層的權重洗掉，訓練時間也跟著深度一起變長：152 層的 ResNet，用好幾張 GPU 在 ImageNet 上也要訓練好幾週。\n\n如果訓練時用淺的網路，測試時用深的網路呢？\n\n這聽起來自相矛盾。2016 年 3 月，康乃爾大學的 Gao Huang、Yu Sun、Daniel Sedra、Kilian Q. Weinberger 與清華大學的 Zhuang Liu 放出這篇論文，後來發表在 ECCV 2016。他們的做法是：網路照樣建得很深，但訓練時每個小批次都隨機拿掉一部分的殘差區塊，只留下捷徑。\n\n## 定義問題\n\n作者列出了很深的網路會遇到的三個問題：\n\n1. **梯度消失**：梯度往回傳的時候，一再乘上小的權重，到了前面幾層就變得很小。\n2. **前向的特徵逐漸流失**：輸入的特徵、或前面層算出的特徵，一再乘上隨機初始化的權重，到後面就被「洗掉」了，後面的層很難找到有意義的梯度方向。\n3. **訓練時間太長**：前向和反向傳播的時間都和深度成正比。\n\nResNet 和 Highway Networks 用捷徑處理前兩個問題，讓特徵和梯度可以繞過權重層。第三個問題還在：網路有多深，每一步就要算多少層。\n\n有沒有辦法讓網路在訓練時「平均起來」淺一點，測試時又保有全部的深度？\n\n\n> [!TIP]\n> \n> ResNet 的殘差區塊，可以先看我們的筆記：\n> \n> - **[[15.12] ResNet：卷積網路 100 層](/blog/papers/classic-cnns/resnet)**\n\n\n## 解決問題\n\n### 讓區塊隨機缺席\n\n作者用的就是 ResNet 原本的殘差區塊。第 $\\ell$ 個區塊的輸出是：\n\n$$\nH_\\ell = \\mathrm{ReLU}\\big(f_\\ell(H_{\\ell-1}) + \\mathrm{id}(H_{\\ell-1})\\big)\n$$\n\n$f_\\ell$ 是「卷積、BN、ReLU、卷積、BN」，$\\mathrm{id}$ 是恆等捷徑。\n\n隨機深度只多了一個伯努利隨機變數 $b_\\ell \\in \\{0, 1\\}$：\n\n$$\nH_\\ell = \\mathrm{ReLU}\\big(b_\\ell\\, f_\\ell(H_{\\ell-1}) + \\mathrm{id}(H_{\\ell-1})\\big)\n$$\n\n$b_\\ell = 1$ 時，這就是原本的殘差區塊。$b_\\ell = 0$ 時，殘差分支整個消失，剩下 $\\mathrm{ReLU}(H_{\\ell-1})$。\n\n這裡有個小細節：$H_{\\ell-1}$ 是上一個區塊最後的 ReLU 輸出，本來就不會是負的（第一個區塊的輸入，也是一組「卷積、BN、ReLU」的輸出），所以 $\\mathrm{ReLU}(H_{\\ell-1}) = H_{\\ell-1}$。缺席的區塊因此剛好是恆等映射，訊號原封不動地傳到下一個區塊。\n\n$b_\\ell = 1$ 的機率記為 $p_\\ell$，作者叫它**存活機率**。每個小批次重新抽一次，被抽中缺席的區塊，這一步完全不用算：不做前向、不做反向，也不更新權重。\n\n### 前面的層比較常出席\n\n每個區塊的存活機率要怎麼設？最簡單的是全部一樣。作者建議的是線性遞減：輸入端是 $p_0 = 1$，最後一個區塊是 $p_L$，中間照比例遞減：\n\n$$\np_\\ell = 1 - \\frac{\\ell}{L}(1 - p_L)\n$$\n\n[![上半部是一排長條，標示 1.0、0.9、0.8、0.7、0.6、0.5，藍色部分代表存活機率，由左到右逐漸變短，旁邊的小圖示說明 active 與 inactive 兩種區塊狀態。下半部是一張花的照片作為 Input，接著五個殘差區塊 f1 到 f5 與中間的 H1 到 H4；f3 和 f5 被紅色叉號劃掉，表示這一次被略過](/content/papers/assets/620e6ddf909f1f405e38b6055bd732ae4c4b7c208f147e00b870a56642020c02.png)](/content/papers/assets/620e6ddf909f1f405e38b6055bd732ae4c4b7c208f147e00b870a56642020c02.png)\n\n*原論文 Fig. 2，取自 [**v3 PDF 第 5 頁**](https://arxiv.org/pdf/1603.09382v3#page=5)。$p_0 = 1$、$p_L = 0.5$ 時的線性遞減；第一個區塊的輸入視為永遠存在的 $H_0$。*\n\n作者的理由是：前面的層抽取低階特徵，後面的層都要用，應該比較穩定地出席。後面的實驗也顯示線性遞減比固定機率好；而且結果對 $p_L$ 不太敏感，所以他們全文都用 $p_L = 0.5$。\n\n以 CIFAR 實驗常用的 110 層 ResNet 為例，它有 $L = 54$ 個殘差區塊：\n\n```python\nimport torch\n\nL, p_L = 54, 0.5                                  # ResNet-110：54 個殘差區塊\np = torch.tensor([1 - l / L * (1 - p_L) for l in range(1, L + 1)])\nprint(\"前三個區塊的存活機率：\", [f\"{v:.3f}\" for v in p[:3]], \"；最後三個：\", [f\"{v:.3f}\" for v in p[-3:]])\nprint(\"期望深度：\", round(p.sum().item(), 2), \"；公式 (3L-1)/4 =\", (3 * L - 1) / 4)\n\ntorch.manual_seed(0)\nactive = torch.bernoulli(p.expand(10000, L)).sum(dim=1)   # 抽 10000 個小批次\nprint(\"實際抽樣：平均\", round(active.mean().item(), 2), \"個區塊，最少\", int(active.min()), \"，最多\", int(active.max()))\nprint(\"可能的子網路數：2^54 =\", f\"{2 ** L:.3e}\")\n```\n\n```text\n前三個區塊的存活機率： ['0.991', '0.981', '0.972'] ；最後三個： ['0.519', '0.509', '0.500']\n期望深度： 40.25 ；公式 (3L-1)/4 = 40.25\n實際抽樣：平均 40.25 個區塊，最少 28 ，最多 51\n可能的子網路數：2^54 = 1.801e+16\n```\n\n訓練時，平均每次只用到約 40 個區塊，測試時是完整的 54 個。期望深度是 $\\sum_\\ell p_\\ell = (3L-1)/4$，大約是 $3L/4$；少算的四分之一，就是訓練時間省下的部分。每次抽到的網路深度也差很多，從 28 到 51 個區塊都有，有些更新會走過特別短的網路，梯度到前面幾層的路徑也更直接。\n\n### 測試時要乘上存活機率\n\n測試時，所有區塊都要出席，才能用上整個網路的容量。可是訓練時，$f_\\ell$ 只在比例 $p_\\ell$ 的更新裡出現，下一層的權重是照這個比例校準的。所以測試時要把每個區塊的輸出乘上它的存活機率：\n\n$$\nH_\\ell^{\\text{Test}} = \\mathrm{ReLU}\\big(p_\\ell\\, f_\\ell(H_{\\ell-1}^{\\text{Test}}; W_\\ell) + H_{\\ell-1}^{\\text{Test}}\\big)\n$$\n\n我們寫一個區塊，比較訓練和測試時的輸出。為了看得清楚，這裡的殘差函數用一個線性層，也先不加最後的 ReLU：\n\n```python\nimport torch\nimport torch.nn as nn\n\nclass StochasticDepthBlock(nn.Module):\n    def __init__(self, f, p):\n        super().__init__()\n        self.f, self.p = f, p                      # p：這個區塊的存活機率\n\n    def forward(self, x):\n        if self.training:\n            if torch.rand(()) < self.p:            # 存活：照常計算殘差\n                return x + self.f(x)\n            return x                               # 沒存活：整個區塊變成恆等映射\n        return x + self.p * self.f(x)              # 測試：乘上存活機率\n\ntorch.manual_seed(0)\nblock = StochasticDepthBlock(nn.Linear(4, 4), p=0.6)\nx = torch.randn(1, 4)\n\nblock.train()\nwith torch.no_grad():\n    outs = torch.stack([block(x) for _ in range(20000)])\nblock.eval()\nwith torch.no_grad():\n    test = block(x)\n\nprint(\"訓練時兩種輸出：\", torch.unique(outs.round(decimals=4), dim=0).shape[0], \"種\")\nprint(\"訓練輸出的平均：\", [f\"{v:.3f}\" for v in outs.mean(0).squeeze()])\nprint(\"測試時的輸出：  \", [f\"{v:.3f}\" for v in test.squeeze()])\n```\n\n```text\n訓練時兩種輸出： 2 種\n訓練輸出的平均： ['-0.479', '0.711', '-1.017', '1.223']\n測試時的輸出：   ['-0.479', '0.713', '-1.017', '1.223']\n```\n\n訓練時，這個區塊的輸出只有兩種：有殘差、沒有殘差。兩萬次的平均，和測試時乘上 $p = 0.6$ 的輸出幾乎一樣。\n\n\n> [!NOTE]\n> \n> 現在的函式庫多半把校正挪到訓練時做，和 inverted dropout 一樣：存活時把殘差除以存活機率，測試時就什麼都不用改。例如 torchvision 的 `torchvision.ops.stochastic_depth`，參數 `p` 是「被丟掉」的機率，存活時把輸入除以 $1-p$。兩種做法的期望值相同，讀程式時要留意 `p` 指的是哪一個。\n\n\n### 為什麼有效？\n\n作者給了三個理由。\n\n- **訓練變快**：被略過的區塊不用算，前向和反向傳播的時間跟著期望深度走，而不是完整深度。\n- **梯度比較強**：訓練時的網路變短，梯度要經過的層數變少，前面幾層收到的梯度比較大。\n- **隱含的集成**：54 個區塊，每個出席或缺席，一共有 $2^{54}$ 種組合。每個小批次抽一個共用權重的子網路來更新，測試時再用上面的式子把它們合成一個網路。ResNet 論文裡破紀錄的成績，正是不同深度的 ResNet 集成出來的。\n\n這個集成的說法和 dropout 很像。差別在於 dropout 讓網路變**窄**，隨機深度讓網路變**淺**。作者也提到，dropout 搭配 batch normalization 時效果常常會打折：他們在加了 BN 的 110 層 ResNet 上試了各種 dropout 比例，幾乎沒有改善；隨機深度在同樣的網路上仍然有效。\n\n## 討論\n\n### 錯誤率和訓練時間\n\n| 方法 | CIFAR-10+ | CIFAR-100+ | SVHN | ImageNet |\n| --- | ---: | ---: | ---: | ---: |\n| Highway Network | 7.60 | 32.24 | – | – |\n| Gen. Pool | 6.05 | 28.02 | 1.69 | – |\n| ResNet，固定深度 | 6.41 | 27.76 | 1.80 | 21.78 |\n| ResNet，隨機深度 | **5.25** | **24.98** | 1.75 | 21.98 |\n\n*表：摘自原論文 Table 1 的部分列，測試錯誤率（%）；「+」表示使用標準的資料增強。「固定深度」是作者自己重現 He 等人的實驗。*\n\nCIFAR-10 用的是 110 層 ResNet，訓練 500 個 epoch。固定深度的錯誤率是 6.41%，加上隨機深度降到 5.25%，相對改善 18%；訓練和網路設定完全相同，只差在訓練時隨機略過區塊。CIFAR-100 用同一個網路，從 27.76% 降到 24.98%。\n\n[![兩張訓練曲線。左邊是 CIFAR-10 上的 110 層 ResNet，右邊是 CIFAR-100。紅線是固定深度的測試錯誤率，藍線是隨機深度的測試錯誤率，另外兩條細線是兩者的訓練損失。在第 250 個 epoch 學習率下降後，藍線明顯低於紅線；左圖標出 6.41% 與 5.25%，右圖標出 27.88% 與 24.98%](/content/papers/assets/757bc4adb848efac2620e3a37c465e58ddc4a4c93e54f3b664bcea91cab64ffe.png)](/content/papers/assets/757bc4adb848efac2620e3a37c465e58ddc4a4c93e54f3b664bcea91cab64ffe.png)\n\n*原論文 Fig. 3，取自 [**v3 PDF 第 8 頁**](https://arxiv.org/pdf/1603.09382v3#page=8)。CIFAR-10（左）與 CIFAR-100（右）的測試錯誤率與訓練損失，圓點是驗證錯誤率最低的那個 epoch。*\n\n學習率第一次下降之後，固定深度的測試錯誤率大致就停住了，隨機深度還在往下走。作者也注意到，隨機深度的測試錯誤率波動比較大，推測是訓練時深度一直在變的緣故。\n\n不用資料增強時，隨機深度在 CIFAR-10 和 CIFAR-100 上也都有大約 15% 的相對改善：13.63% 降到 11.66%，44.74% 降到 37.8%。SVHN 用 152 層的網路，固定深度到第二階段就開始過擬合，錯誤率 1.80%；隨機深度是 1.75%。\n\n訓練時間的比較：\n\n| | CIFAR-10+ | CIFAR-100+ | SVHN |\n| --- | ---: | ---: | ---: |\n| 固定深度 | 20 小時 42 分 | 20 小時 51 分 | 33 小時 43 分 |\n| 隨機深度 | 15 小時 7 分 | 15 小時 20 分 | 25 小時 33 分 |\n\n*表：摘自原論文 Table 2，$p_L = 0.5$ 的線性遞減。*\n\n每一組都省下大約四分之一的時間，和前面算的期望深度一致。\n\n### 一千兩百層\n\nResNet 論文試過 1202 層的網路，結果過擬合，測試錯誤率 7.93%，比 110 層還差。作者用同樣的 1202 層網路重做這個實驗，訓練 300 個 epoch，前 10 個 epoch 用 0.01 的學習率暖身。\n\n固定深度的 1202 層網路錯誤率 6.67%，同樣比 110 層的 6.41% 差。換成隨機深度，錯誤率是 4.91%：比固定深度的 1202 層相對改善 27%，也比隨機深度的 110 層（5.25%）更好，而且沒有過擬合的跡象。作者說，這是第一次有超過一千層的網路，能比淺一點的網路進一步降低測試錯誤率。\n\n\n> [!TIP]\n> \n> 同一個月，ResNet 的作者走了另一條路，把殘差單元改成 pre-activation，1001 層的 ResNet 在 CIFAR-10 上做到 4.92%（批次大小 64 時 4.62%）：\n> \n> - **[[16.03] ResNet v2：捷徑要乾淨](/blog/papers/classic-cnns/resnet-v2)**\n\n\n### ImageNet 上沒有贏\n\nImageNet 用的是 152 層的 ResNet。固定深度訓練 90 個 epoch，錯誤率 23.06%；隨機深度在第 90 個 epoch 是 23.38%，略差一點。作者觀察到隨機深度的驗證錯誤率還在明顯下降，而它省下 25% 的計算，多訓練 30 個 epoch，總時間也和固定深度的 90 個 epoch 差不多。多訓練之後，隨機深度到 21.98%；可是固定深度也多跑了 30 個 epoch，到了 21.78%。\n\n所以在這個設定下，隨機深度沒有帶來準確率的好處。作者引用一位匿名審稿人的說法：ImageNet 的模型和 CIFAR 的模型還處在不同的狀態；ImageNet 需要的模型複雜度可能遠超過 152 層的 ResNet，隨機深度也許要等到更大的模型才會顯出效果。\n\n### 梯度真的比較強嗎？\n\n[![折線圖，橫軸是 epoch（0 到 500），縱軸是第一個卷積層的平均梯度大小（單位 10 的負 5 次方）。紅線是固定深度，藍線是隨機深度。兩條虛線標出第 250 與 375 個 epoch 的學習率下降，梯度在這兩處都大幅下降；藍線始終高於紅線，學習率下降之後差距更明顯](/content/papers/assets/6e62eb722549bcdd22e104076055f0d6e70ad5e66c660f0e827fcfa67318c9a1.png)](/content/papers/assets/6e62eb722549bcdd22e104076055f0d6e70ad5e66c660f0e827fcfa67318c9a1.png)\n\n*原論文 Fig. 7，取自 [**v3 PDF 第 12 頁**](https://arxiv.org/pdf/1603.09382v3#page=12)。CIFAR-10 上，第一個殘差區塊的第一個卷積層每個 epoch 的平均梯度大小；虛線是學習率除以 10 的時間點。*\n\n兩次大幅下降來自學習率的排程。隨機深度的梯度一直比較大，學習率下降之後差距更明顯，這支持作者「緩解梯度消失」的說法。\n\n### 存活機率要設多少？\n\n[![左圖：CIFAR-10 上 110 層 ResNet 的測試錯誤率對存活機率 p_L 的變化。實線是線性遞減，虛線是固定機率，紅色虛線是固定深度的 6.41%。線性遞減的曲線在 p_L 為 0.5 附近最低，約 5.25%，標註 1.33x 的加速；p_L 為 0.2 時仍接近固定深度，標註 1.67x；固定機率的曲線大多較高，只在 p_L 約 0.8 處低於線性遞減，在 p_L 為 0.5 處標註 2x。右圖：熱力圖，縱軸是 p_L（1.0 到 0.5），橫軸是網路深度（20 到 110 層），格子裡是測試錯誤率；20 層時 p_L 在 0.9 到 0.7 之間比固定深度好，再小就變差，110 層時 p_L 為 0.5 最好，最低的值大致沿著對角線分布](/content/papers/assets/1f923643ee1fd74e75ef508bccb935e721a1b51f610ca3dcbac82168dc0573ad.png)](/content/papers/assets/1f923643ee1fd74e75ef508bccb935e721a1b51f610ca3dcbac82168dc0573ad.png)\n\n*原論文 Fig. 8，取自 [**v3 PDF 第 13 頁**](https://arxiv.org/pdf/1603.09382v3#page=13)。左：110 層 ResNet 在不同 $p_L$ 下的 CIFAR-10 測試錯誤率；右：不同 $p_L$ 與網路深度的測試錯誤率，$p_L = 1$ 那一列就是固定深度。*\n\n$p_L$ 是這個方法唯一的超參數。從左圖可以看到：\n\n1. 只要 $p_L$ 設得合理，兩種規則都比固定深度好。\n2. 在大多數的 $p_L$ 下，線性遞減都比固定機率好。\n3. 線性遞減對 $p_L$ 不太敏感，$p_L$ 在 0.4 到 0.8 之間都有不錯的結果。\n4. 就算 $p_L = 0.2$，線性遞減的錯誤率也和固定深度相當，訓練時間卻少了 40%。\n\n右邊的熱力圖加入了深度。20 層的網路，只略過一點（$p_L$ 在 0.9 到 0.7）時比固定深度好，略過再多就變差：$p_L = 0.5$ 時錯誤率從 8.31% 升到 9.39%。110 層的網路則是 $p_L = 0.5$ 最好。表現最好的格子大致沿著對角線：網路越深，越能承受更積極的略過。網路要夠深，隨機深度才會明顯勝過固定深度；淺一點的網路，略過得保守一點也還有幫助。\n\n## 結論\n\n隨機深度是一個訓練方法，不改測試時的網路：訓練時隨機略過殘差區塊，期望深度變成約四分之三，測試時再用存活機率把所有區塊合起來。實驗上，CIFAR 與 SVHN 的錯誤率都下降，訓練時間少了約四分之一，1202 層的網路也不再過擬合。ImageNet 上的 152 層 ResNet 則沒有看到準確率的好處。\n\n在一些程式庫裡，它以 DropPath 的名字出現。本文的 Gao Huang、Zhuang Liu 與 Kilian Q. Weinberger 幾個月後提出 DenseNet，論文開頭就引用了隨機深度：既然隨機略過層也能訓練，殘差網路裡很多層的貢獻其實很小。\n\n\n> [!TIP]\n> \n> DenseNet 可以看我們的筆記：\n> \n> - **[[16.08] DenseNet：全部連起來](/blog/papers/classic-cnns/densenet)**\n\n\n隨機深度用起來很簡單：訓練時，每個殘差分支乘上一個隨機的 0 或 1；測試時，換成存活機率。現在的程式庫多半改成訓練時除以存活機率，像 torchvision 的 `stochastic_depth`，測試時就什麼都不用改。\n\n作者當年猜，也許要等到更大的模型，隨機深度才會在 ImageNet 上看到好處。後來 [ConvNeXt](/blog/papers/classic-cnns/convnext)、[DINOv2](/blog/papers/contrastive-learning/dinov2) 這些大模型的訓練配方裡，確實都放了它。\n","imageSizes":{"/content/papers/assets/620e6ddf909f1f405e38b6055bd732ae4c4b7c208f147e00b870a56642020c02.png":{"width":963,"height":339},"/content/papers/assets/757bc4adb848efac2620e3a37c465e58ddc4a4c93e54f3b664bcea91cab64ffe.png":{"width":965,"height":372},"/content/papers/assets/6e62eb722549bcdd22e104076055f0d6e70ad5e66c660f0e827fcfa67318c9a1.png":{"width":756,"height":345},"/content/papers/assets/1f923643ee1fd74e75ef508bccb935e721a1b51f610ca3dcbac82168dc0573ad.png":{"width":973,"height":422}}}
