{"notes":[{"id":"classic-cnns/inception-v3","category":"classic-cnns","legacyPath":"","legacySlug":"","legacyPaths":[],"title":"Inception-v3","subtitle":"大卷积核退场","author":"Z. Yuan","paperDate":"2015-12-02","publishedOn":"2025-12-16","world":"external/inception-v3","paperTitle":"Rethinking the Inception Architecture for Computer Vision","paperUrl":"https://arxiv.org/abs/1512.00567","bibliography":{"title":"Rethinking the Inception Architecture for Computer Vision","authors":["Christian Szegedy","Vincent Vanhoucke","Sergey Ioffe","Jonathon Shlens","Zbigniew Wojna"],"url":"https://arxiv.org/abs/1512.00567","pdfUrl":"https://arxiv.org/pdf/1512.00567v3","codeUrl":null,"preprint":{"id":"1512.00567","submittedOn":"2015-12-02","url":"https://arxiv.org/abs/1512.00567"},"publication":null,"citation":"@misc{classiccnnsinceptionv32015,\n  title = {{Rethinking the Inception Architecture for Computer Vision}},\n  author = {Christian Szegedy and Vincent Vanhoucke and Sergey Ioffe and Jonathon Shlens and Zbigniew Wojna},\n  year = {2015},\n  eprint = {1512.00567},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1512.00567}\n}\n","citationPath":"/content/papers/citations/classic-cnns/inception-v3.5636c0bddf2d.bib"},"thumbnail":{"src":"/content/papers/assets/c87d3d6fa9ea76d954eba2570f702150eca32d62c7cdb3d724075a4be9a63080.png","width":419,"height":358},"locale":"zh-hans","path":"/content/papers/zh-hans/classic-cnns/inception-v3.847c152f5969.md","headings":[{"id":"定义问题","text":"定义问题","depth":2},{"id":"解决问题","text":"解决问题","depth":2},{"id":"把-55-拆成两层-33","text":"把 5×5 拆成两层 3×3","depth":3},{"id":"再拆成-1n-与-n1","text":"再拆成 1×n 与 n×1","depth":3},{"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":"一项一项加上去","text":"一项一项加上去","depth":3},{"id":"分辨率低一点差多少","text":"分辨率低一点，差多少？","depth":3},{"id":"和其他模型比较","text":"和其他模型比较","depth":3},{"id":"结论","text":"结论","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/inception-v1","relation":"referenced","topic":""},{"id":"normalization/batchnorm","relation":"referenced","topic":""},{"id":"classic-cnns/convnext","relation":"referenced","topic":""}]},{"id":"classic-cnns/inception-v1","category":"classic-cnns","legacyPath":"classic-cnns/1409-inception-v1","legacySlug":"1409-inception-v1","legacyPaths":[],"title":"GoogLeNet","subtitle":"或叫做 Inception-V1","author":"Z. Yuan","paperDate":"2014-09-17","publishedOn":"2024-09-22","paperTitle":"Going Deeper with Convolutions","paperUrl":"https://arxiv.org/abs/1409.4842","bibliography":{"title":"Going Deeper with Convolutions","authors":["Christian Szegedy","Wei Liu","Yangqing Jia","Pierre Sermanet","Scott Reed","Dragomir Anguelov","Dumitru Erhan","Vincent Vanhoucke","Andrew Rabinovich"],"url":"https://arxiv.org/abs/1409.4842","pdfUrl":"https://arxiv.org/pdf/1409.4842","codeUrl":null,"preprint":{"id":"1409.4842","submittedOn":"2014-09-17","url":"https://arxiv.org/abs/1409.4842"},"publication":{"venue":"CVPR","year":2015,"kind":"conference","url":"https://doi.org/10.1109/cvpr.2015.7298594"},"citation":"@misc{classiccnnsinceptionv12014,\n  title = {{Going Deeper with Convolutions}},\n  author = {Christian Szegedy and Wei Liu and Yangqing Jia and Pierre Sermanet and Scott Reed and Dragomir Anguelov and Dumitru Erhan and Vincent Vanhoucke and Andrew Rabinovich},\n  year = {2014},\n  eprint = {1409.4842},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1409.4842}\n}\n","citationPath":"/content/papers/citations/classic-cnns/inception-v1.3d20e0e32bcd.bib"},"thumbnail":{"src":"/content/papers/assets/254b970b1374c24267b60c2d684338760e9ba8b10dad761a5fa15f1bb8bcf6ef.jpg","width":1330,"height":394},"locale":"zh-hans","path":"/content/papers/zh-hans/classic-cnns/inception-v1.7c8c2ff19589.md","headings":[{"id":"解决问题","text":"解决问题","depth":2},{"id":"inception-模块","text":"Inception 模块","depth":3},{"id":"参数配置","text":"参数配置","depth":3},{"id":"模型架构","text":"模型架构","depth":3},{"id":"讨论","text":"讨论","depth":2},{"id":"在-ilsvrc-2014-上的表现","text":"在 ILSVRC 2014 上的表现","depth":3},{"id":"结论","text":"结论","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"classic-cnns/resnext","relation":"comparison","topic":"分支、分组卷积与特征复用"},{"id":"classic-cnns/cspnet","relation":"comparison","topic":"分支、分组卷积与特征复用"}]},{"id":"normalization/batchnorm","category":"normalization","legacyPath":"normalization/1502-batchnorm","legacySlug":"1502-batchnorm","legacyPaths":[],"title":"BatchNorm","subtitle":"批次标准化","author":"Z. Yuan","paperDate":"2015-02-11","publishedOn":"2024-08-01","paperTitle":"Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift","paperUrl":"https://arxiv.org/abs/1502.03167","bibliography":{"title":"Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift","authors":["Sergey Ioffe","Christian Szegedy"],"url":"https://arxiv.org/abs/1502.03167","pdfUrl":"https://arxiv.org/pdf/1502.03167","codeUrl":null,"preprint":{"id":"1502.03167","submittedOn":"2015-02-11","url":"https://arxiv.org/abs/1502.03167"},"publication":null,"citation":"@misc{normalizationbatchnorm2015,\n  title = {{Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift}},\n  author = {Sergey Ioffe and Christian Szegedy},\n  year = {2015},\n  eprint = {1502.03167},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/1502.03167}\n}\n","citationPath":"/content/papers/citations/normalization/batchnorm.bfa8abb33f32.bib"},"thumbnail":{"src":"/content/papers/assets/48b236d4b897164b93764eccfe22db29e5b9bce290d864336b8f12ec127c1e4b.jpg","width":1016,"height":824},"locale":"zh-hans","path":"/content/papers/zh-hans/normalization/batchnorm.1521f6672c5f.md","headings":[{"id":"定义问题","text":"定义问题","depth":2},{"id":"解决问题","text":"解决问题","depth":2},{"id":"提高学习率","text":"提高学习率","depth":3},{"id":"不需要-dropout","text":"不需要 Dropout","depth":3},{"id":"讨论","text":"讨论","depth":2},{"id":"在-mnist-实验","text":"在 MNIST 实验","depth":3},{"id":"在-imagenet-实验","text":"在 ImageNet 实验","depth":3},{"id":"结论","text":"结论","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"normalization/layernorm","relation":"next","topic":"归一化究竟沿哪个维度算"}]},{"id":"classic-cnns/convnext","category":"classic-cnns","legacyPath":"classic-cnns/2201-convnext","legacySlug":"2201-convnext","legacyPaths":[],"title":"ConvNeXt","subtitle":"让卷积再次伟大","author":"Z. Yuan","paperDate":"2022-01-10","publishedOn":"2024-06-30","paperTitle":"A ConvNet for the 2020s","paperUrl":"https://arxiv.org/abs/2201.03545","bibliography":{"title":"A ConvNet for the 2020s","authors":["Zhuang Liu","Hanzi Mao","Chao-Yuan Wu","Christoph Feichtenhofer","Trevor Darrell","Saining Xie"],"url":"https://arxiv.org/abs/2201.03545","pdfUrl":"https://arxiv.org/pdf/2201.03545","codeUrl":"https://github.com/facebookresearch/ConvNeXt","preprint":{"id":"2201.03545","submittedOn":"2022-01-10","url":"https://arxiv.org/abs/2201.03545"},"publication":{"venue":"CVPR","year":2022,"kind":"conference","url":"https://arxiv.org/abs/2201.03545"},"citation":"@misc{classiccnnsconvnext2022,\n  title = {{A ConvNet for the 2020s}},\n  author = {Zhuang Liu and Hanzi Mao and Chao-Yuan Wu and Christoph Feichtenhofer and Trevor Darrell and Saining Xie},\n  year = {2022},\n  eprint = {2201.03545},\n  archivePrefix = {arXiv},\n  url = {https://arxiv.org/abs/2201.03545}\n}\n","citationPath":"/content/papers/citations/classic-cnns/convnext.801b4060b807.bib"},"thumbnail":{"src":"/content/papers/assets/37882616c5c72df33699003256d14bf7c58c8ea5d1e9e4fb5b1c33268c9a6923.jpg","width":1224,"height":432},"locale":"zh-hans","path":"/content/papers/zh-hans/classic-cnns/convnext.db5ced84300e.md","headings":[{"id":"定义问题","text":"定义问题","depth":2},{"id":"解决问题","text":"解决问题","depth":2},{"id":"重新设计网络架构","text":"重新设计网络架构","depth":3},{"id":"引入现代训练技术","text":"引入现代训练技术","depth":3},{"id":"宏观设计","text":"宏观设计","depth":3},{"id":"resnext-ify","text":"ResNeXt-ify","depth":3},{"id":"inverted-bottleneck","text":"Inverted Bottleneck","depth":3},{"id":"大核卷积","text":"大核卷积","depth":3},{"id":"微观设计","text":"微观设计","depth":3},{"id":"讨论","text":"讨论","depth":2},{"id":"总结模型配置","text":"总结模型配置","depth":3},{"id":"imagenet-上的性能","text":"ImageNet 上的性能","depth":3},{"id":"结论","text":"结论","depth":2}],"anchorAliases":{},"guide":null,"relatedReading":[{"id":"vision-transformers/convmixer","relation":"comparison","topic":"用卷积混合图像分块"},{"id":"vision-transformers/caformer","relation":"comparison","topic":"用卷积混合图像分块"},{"id":"reparameterization/replknet","relation":"comparison","topic":"大卷积核与简化骨架"}]}],"text":"GoogLeNet 拿下 ILSVRC 2014 分类赛冠军时，只用了大约 500 万个参数，是 AlexNet 的十二分之一。\n\n这种效率很诱人，但想改它的人很快就会碰到麻烦。GoogLeNet 的论文没有说清楚每个设计决定是怎么来的；Inception 模块的分支又多，想把模型放大，最直觉的做法是把每一组滤波器的数量都翻倍，结果计算量和参数量一起变成四倍。\n\n2015 年 12 月，Google 的 Christian Szegedy、Vincent Vanhoucke、Sergey Ioffe、Jonathon Shlens 与伦敦大学学院的 Zbigniew Wojna 发布了这篇论文，后来发表在 CVPR 2016。标题里的「Rethinking」说的就是这件事：把 Inception 拆开重新想一遍，看看哪些做法能在放大网络的同时，让多出来的计算花得值得。\n\n\n> [!TIP]\n> \n> Inception 模块的基本样子，可以先看我们的笔记：\n> \n> - **[[14.09] GoogLeNet：或叫做 Inception-V1](/blog/papers/classic-cnns/inception-v1)**\n\n\n## 定义问题\n\n作者想回答的是：计算预算有限时，网络该怎么放大？\n\n他们从大量的架构实验中整理出四条原则。作者自己说得很保守：这些原则还带有推测成分，需要更多实验来确认适用范围；建议只在拿不定主意时参考。不过，实验中明显违反这些原则的网络，质量通常会变差，修正之后又会变好。\n\n1. **避免表示瓶颈，尤其是在网络前段**。从输入到输出，特征的大小应该慢慢缩小，不要在某一层突然压得很扁。作者也提醒，维度只是信息量的粗略估计。\n2. **高维的表示更容易在局部处理**。每个位置的激活数多一些，特征更容易解耦，训练也更快。\n3. **空间上的聚合可以在低维上做**。例如做 $3\\times3$ 卷积之前，先把通道数降下来，表达能力不太会受损。作者的猜测是：相邻位置的输出高度相关，降维时信息损失不大。\n4. **宽度和深度要平衡**。两者都增加会更好；在固定的计算量下，同时增加宽度和深度，效果最好。\n\nGoogLeNet 早期的收益，很大一部分来自大量使用 $1\\times1$ 卷积降维，也就是第 3 条。作者把降维看作「分解卷积」的一个特例，接下来要找其他的分解方法。\n\n## 解决问题\n\n### 把 5×5 拆成两层 3×3\n\n大的卷积核很贵。在相同的输入、输出通道数下，$5\\times5$ 卷积的计算量是 $3\\times3$ 的 $25/9\\approx2.78$ 倍。\n\n可是大卷积核也看得更远。能不能用更少的参数，得到一样大的视野？\n\n作者换了一个角度看 $5\\times5$ 卷积：每个输出，都是一个小型的全连接网络，滑过输入上一块 $5\\times5$ 的区域。既然是视觉网络，这个小网络本身也可以利用平移不变性，改成两层：第一层是 $3\\times3$ 卷积，第二层在第一层输出的 $3\\times3$ 网格上做全连接。把这个两层的小网络滑过整张输入，就等于两层 $3\\times3$ 卷积。\n\n[![三层蓝色方格叠在一起。最下层是一块 5×5 的输入区域，中间是一个 3×3 的网格，最上层是一个输出格子；红线标出最上层的格子连接到中间整个 3×3 区域，中间每一格又连接到下方的一块 3×3 区域](/content/papers/assets/c87d3d6fa9ea76d954eba2570f702150eca32d62c7cdb3d724075a4be9a63080.png)](/content/papers/assets/c87d3d6fa9ea76d954eba2570f702150eca32d62c7cdb3d724075a4be9a63080.png)\n\n*原论文 Figure 1，取自 [**v3 PDF 第 3 页**](https://arxiv.org/pdf/1512.00567v3#page=3)。取代 $5\\times5$ 卷积的小网络：上层的一个输出看中层的 $3\\times3$，中层每一格再看输入的 $3\\times3$。*\n\n先算算省了多少。拿一张 $35\\times35$、64 个通道的特征图，输出通道数不变：\n\n```python\nimport torch\nimport torch.nn as nn\n\nx = torch.randn(1, 64, 35, 35)                 # 35×35 的特征图，64 个通道\n\nbig = nn.Conv2d(64, 64, 5, padding=2, bias=False)\nsmall = nn.Sequential(nn.Conv2d(64, 64, 3, padding=1, bias=False),\n                      nn.Conv2d(64, 64, 3, padding=1, bias=False))\n\ndef params(m):\n    return sum(p.numel() for p in m.parameters())\n\nprint(big(x).shape, small(x).shape)\nprint(\"5×5 参数：\", params(big))\nprint(\"两层 3×3 参数：\", params(small), f\"（{params(small) / params(big):.0%}）\")\n```\n\n```text\ntorch.Size([1, 64, 35, 35]) torch.Size([1, 64, 35, 35])\n5×5 参数： 102400\n两层 3×3 参数： 73728 （72%）\n```\n\n输出形状一样，参数只剩 $(9+9)/25 = 72\\%$，省下 28%。卷积网络里每个权重在每个输出位置恰好用一次，所以计算量也省下同样的比例。这里假设中间层的通道数和输入相同；论文的分析也是这样简化的。\n\n再确认一下视野。把两层 $3\\times3$ 的权重都设成 1，看中心那一个输出对输入的梯度：\n\n```python\nimport torch\nimport torch.nn as nn\n\nstack = nn.Sequential(nn.Conv2d(1, 1, 3, padding=1), nn.ReLU(),\n                      nn.Conv2d(1, 1, 3, padding=1))\nfor conv in (stack[0], stack[2]):              # 权重设成 1，让每条连线都看得见\n    nn.init.ones_(conv.weight)\n    nn.init.zeros_(conv.bias)\n\nx = torch.rand(1, 1, 9, 9, requires_grad=True)\nstack(x)[0, 0, 4, 4].backward()                # 只看中心的一个输出\n\nprint(x.grad[0, 0].int())\n```\n\n```text\ntensor([[0, 0, 0, 0, 0, 0, 0, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0, 0, 0],\n        [0, 0, 1, 2, 3, 2, 1, 0, 0],\n        [0, 0, 2, 4, 6, 4, 2, 0, 0],\n        [0, 0, 3, 6, 9, 6, 3, 0, 0],\n        [0, 0, 2, 4, 6, 4, 2, 0, 0],\n        [0, 0, 1, 2, 3, 2, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0, 0, 0]], dtype=torch.int32)\n```\n\n非零的区域恰好是 $5\\times5$。格子里的数字是「从这个输入点走到输出，有几条路径」：中心有 9 条，角落只有 1 条。两层 $3\\times3$ 看得和 $5\\times5$ 一样远，只是中间的位置被看得更重。\n\n这种替换留下两个问题。第一，表达能力会不会变差？第二，既然要分解的是 $5\\times5$ 这个线性运算，第一层是不是应该保持线性，不加 ReLU？\n\n作者做了几组对照实验，其中一组比较两个 Inception 模型：一个在分解出来的第一层用线性激活，另一个两层都用 ReLU，最后在验证集上分别停在 76.2% 和 77.2% 的 top-1 准确率。作者说，在所有对照实验里，线性版本都更差；他们的解释是多一层非线性能让网络学到更多种变化，加上 batch normalization 时尤其明显。\n\n### 再拆成 1×n 与 n×1\n\n这样看来，比 $3\\times3$ 大的卷积核都可以换成一串 $3\\times3$。那 $3\\times3$ 还能不能再拆？\n\n拆成两层 $2\\times2$，只省 11%。作者找到了更好的拆法：非对称卷积。先做 $3\\times1$，再做 $1\\times3$，视野同样是 $3\\times3$。\n\n[![一个上窄下宽的示意图：底部是 3×3 的输入区域，中间是排成一条的 3×1 格子，顶端是一个输出格子；红线标出输出先连接到中间这一条的 3 个格子，这 3 个格子再各自连接到输入的一整行](/content/papers/assets/26d9fd5f020cc9ce53cac89b03dbc710d155db812e4745d2e1c47a456faa3b1a.png)](/content/papers/assets/26d9fd5f020cc9ce53cac89b03dbc710d155db812e4745d2e1c47a456faa3b1a.png)\n\n*原论文 Figure 3，取自 [**v3 PDF 第 4 页**](https://arxiv.org/pdf/1512.00567v3#page=4)。取代 $3\\times3$ 卷积的小网络：下层是有 3 个输出的 $3\\times1$ 卷积。*\n\n用同样的方法检查：\n\n```python\nimport torch\nimport torch.nn as nn\n\npair = nn.Sequential(nn.Conv2d(1, 1, (1, 3), padding=(0, 1)),   # 1×3：只往左右看\n                     nn.Conv2d(1, 1, (3, 1), padding=(1, 0)))   # 3×1：只往上下看\nfor conv in pair:\n    nn.init.ones_(conv.weight)\n    nn.init.zeros_(conv.bias)\n\nx = torch.rand(1, 1, 7, 7, requires_grad=True)\npair(x)[0, 0, 3, 3].backward()\nprint(x.grad[0, 0].int())\n\nfor name, cost in [(\"3×3\", 9), (\"1×3 + 3×1\", 3 + 3), (\"两层 2×2\", 4 + 4),\n                   (\"7×7\", 49), (\"1×7 + 7×1\", 7 + 7)]:\n    print(f\"{name}：{cost}\")\n```\n\n```text\ntensor([[0, 0, 0, 0, 0, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n        [0, 0, 1, 1, 1, 0, 0],\n        [0, 0, 1, 1, 1, 0, 0],\n        [0, 0, 1, 1, 1, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0],\n        [0, 0, 0, 0, 0, 0, 0]], dtype=torch.int32)\n3×3：9\n1×3 + 3×1：6\n两层 2×2：8\n7×7：49\n1×7 + 7×1：14\n```\n\n下面几行是每个输出、每对输入输出通道要做的乘法次数。$1\\times3$ 加 $3\\times1$ 是 6 次，比 $3\\times3$ 少三分之一；两层 $2\\times2$ 是 8 次，只少九分之一。卷积核越大，省得越多：$7\\times7$ 要 49 次，拆成 $1\\times7$ 加 $7\\times1$ 只要 14 次。\n\n不过这招不是到处都好用。作者发现放在网络前段效果不好，放在中等大小的特征图上（边长大约 12 到 20）效果很好。实际的网络在 $17\\times17$ 的特征图上用 $1\\times7$ 接 $7\\times1$：\n\n[![Inception 模块示意图：最下方是 Base，往上分成四条分支。最左边是 1x1 后接 1xn、nx1、1xn、nx1 共四层；第二条是 1x1 后接 1xn、nx1；第三条是 Pool 后接 1x1；最右边只有 1x1。四条分支最后在 Filter Concat 合并](/content/papers/assets/d7b13cfd7a93816701d9571a2e87bd67983a5e6ffe9a7b93cbcf40e82db76a2f.png)](/content/papers/assets/d7b13cfd7a93816701d9571a2e87bd67983a5e6ffe9a7b93cbcf40e82db76a2f.png)\n\n*原论文 Figure 6，取自 [**v3 PDF 第 5 页**](https://arxiv.org/pdf/1512.00567v3#page=5)。分解 $n\\times n$ 卷积后的 Inception 模块；在 $17\\times17$ 的特征图上，作者取 $n=7$。*\n\n把它和 GoogLeNet 原本的模块对照：原本是 $1\\times1$、$3\\times3$、$5\\times5$ 与池化四条分支。这里最左边那条，相当于把两层 $7\\times7$ 各拆成一对非对称卷积；第二条则是一层 $7\\times7$ 的拆法。$35\\times35$ 那一段用的是 Figure 5 的模块，也就是把 $5\\times5$ 换成两层 $3\\times3$。\n\n到了最小的 $8\\times8$ 特征图，作者换了一种用法：\n\n[![Inception 模块示意图：最左边的分支是 1x1、3x3，之后同时分出 1x3 与 3x1 两个并行的卷积；第二条是 1x1 后同时分出 1x3 与 3x1；另外还有 Pool 接 1x1，以及单独的 1x1。所有输出在 Filter Concat 合并](/content/papers/assets/1475f4de3132dd0d1dbd081ddc453fb140796cb802987fa051a70356070b1b41.png)](/content/papers/assets/1475f4de3132dd0d1dbd081ddc453fb140796cb802987fa051a70356070b1b41.png)\n\n*原论文 Figure 7，取自 [**v3 PDF 第 5 页**](https://arxiv.org/pdf/1512.00567v3#page=5)。扩展输出滤波器的 Inception 模块，只用在最粗的 $8\\times8$ 特征图上。*\n\n注意 $1\\times3$ 和 $3\\times1$ 在这里是**并行**的，两个输出直接接到最后的合并，没有串起来。这样做让输出的通道数变多，对应第 2 条原则：在最后的特征图上产生高维的表示。作者只在 $8\\times8$ 这里用它，理由是到了这个阶段，$1\\times1$ 卷积做的局部处理，比空间上的聚合更重要。\n\n### 辅助分类器的真正作用\n\nGoogLeNet 在网络中间挂了两个辅助分类器，原本的想法是把有用的梯度送到前面几层，对抗梯度消失、加快收敛。\n\n作者重新观察后发现，事情不是这样。训练前期，有没有辅助分类器的两条曲线几乎一样；要到训练快结束时，有辅助分类器的网络才开始领先，最后停在稍高的位置。把位置较低的那个辅助分类器拿掉，最终质量也没有变差。\n\n所以 GoogLeNet 当初的假设，也就是辅助分支能帮助底层特征演化，作者认为多半不成立。他们的新解释是：辅助分类器是一种**正则化**。证据是，辅助分支加上 batch normalization 或 dropout 时，主分类器的表现会更好；在辅助分支加 batch normalization，top-1 准确率绝对值提升了 0.4%。Inception-v3 的辅助分类器接在最后一层 $17\\times17$ 的特征图上。\n\n作者也顺带提了一句：这个现象对「batch normalization 有正则化效果」的猜想，算是提供了一点微弱的支持。\n\n### 缩小特征图，又不想卡住信息\n\n卷积网络通常靠池化把特征图缩小。假设要把 $35\\times35\\times320$ 变成 $17\\times17\\times640$，有两种直接的做法：\n\n- **先卷积再池化**：先在 $35\\times35$ 上把通道从 320 增加到 640，再池化。信息没有被卡住，但最贵的卷积是在大的特征图上做的。\n- **先池化再卷积**：先池化到 $17\\times17$，再增加通道。便宜很多，但中间有一步只剩 $17\\times17\\times320$，违反了第 1 条原则。\n\n我们用一层 $3\\times3$ 卷积粗略算一下：\n\n```python\nd, k = 35, 320                               # 35×35×320，要变成 17×17×640\nh = 17\n\nconv_then_pool = d * d * k * (2 * k) * 9     # 先在 35×35 上做 320→640 的 3×3 卷积\npool_then_conv = h * h * k * (2 * k) * 9     # 先池化到 17×17，再做 320→640\nparallel = h * h * k * k * 9                 # 步幅 2 的卷积只输出 320 个通道，另一半交给池化\n\nfor name, macs in [(\"先卷积再池化\", conv_then_pool), (\"先池化再卷积\", pool_then_conv), (\"卷积与池化并行\", parallel)]:\n    print(f\"{name}：{macs / 1e6:7.1f} M 次乘加\")\n\nprint(\"先池化后，中间只剩\", h * h * k, \"个数；输入有\", d * d * k, \"个\")\n```\n\n```text\n先卷积再池化： 2257.9 M 次乘加\n先池化再卷积：  532.7 M 次乘加\n卷积与池化并行：  266.3 M 次乘加\n先池化后，中间只剩 92480 个数；输入有 392000 个\n```\n\n先卷积的做法，计算量是先池化的四倍多。\n\n作者的解法是第三行：让步幅 2 的卷积和步幅 2 的池化**并行**，各自直接把特征图缩小，再把两边的通道拼接起来：\n\n[![左右两张图。左边是模块的运算：Base 往上分成三条分支，两条是 1x1 后接步幅 2 的 3x3 卷积（其中一条在前面多一层步幅 1 的 3x3），第三条是步幅 2 的池化，最后在 Filter Concat 合并。右边从特征图大小来看：35x35x320 分成 conv 与 pool 两边，各得到 17x17x320，拼接起来成为 17x17x640](/content/papers/assets/9d6b75a1dd143d0b517f52adf42c4fe794cb400e3276a8109561db2277fb2fb6.png)](/content/papers/assets/9d6b75a1dd143d0b517f52adf42c4fe794cb400e3276a8109561db2277fb2fb6.png)\n\n*原论文 Figure 10，取自 [**v3 PDF 第 6 页**](https://arxiv.org/pdf/1512.00567v3#page=6)。左边是缩小特征图、同时增加通道的 Inception 模块；右边从特征图大小的角度看同一件事。*\n\n右边那张图最好读：$35\\times35\\times320$ 分成两路，卷积那一路输出 $17\\times17\\times320$，池化那一路也是 $17\\times17\\times320$，拼接起来就是 $17\\times17\\times640$。卷积只需要输出一半的通道，计算量又比先池化的做法少一半；而输出直接就是 640 个通道，没有经过被压扁的那一步。\n\n### 把零件组装起来\n\n作者把上面这些零件组成了一个新网络：\n\n| 类型 | 卷积核／步幅或说明 | 输入大小 |\n| --- | --- | --- |\n| conv | $3\\times3$／2 | $299\\times299\\times3$ |\n| conv | $3\\times3$／1 | $149\\times149\\times32$ |\n| conv（补零） | $3\\times3$／1 | $147\\times147\\times32$ |\n| pool | $3\\times3$／2 | $147\\times147\\times64$ |\n| conv | $3\\times3$／1 | $73\\times73\\times64$ |\n| conv | $3\\times3$／2 | $71\\times71\\times80$ |\n| conv | $3\\times3$／1 | $35\\times35\\times192$ |\n| 3 × Inception | 同 Figure 5 | $35\\times35\\times288$ |\n| 5 × Inception | 同 Figure 6 | $17\\times17\\times768$ |\n| 2 × Inception | 同 Figure 7 | $8\\times8\\times1280$ |\n| pool | $8\\times8$ | $8\\times8\\times2048$ |\n| linear | logits | $1\\times1\\times2048$ |\n| softmax | 分类器 | $1\\times1\\times1000$ |\n\n*表：摘自原论文 Table 1。每一行的输入大小，就是上一行的输出大小。*\n\n开头三层 $3\\times3$ 卷积，是把传统的 $7\\times7$ 第一层拆开的结果，和把 $5\\times5$ 换成两层 $3\\times3$ 是同一个想法。三段 Inception 之间，用 Figure 10 那类模块缩小特征图。整个网络有 42 层。\n\n你可能会好奇，输入为什么是 $299\\times299$ 这么奇怪的数字。按表上的设置算一遍：\n\n```python\ndef out(n, k, s, pad=0):\n    return (n + 2 * pad - k) // s + 1\n\nn = 299\nfor name, k, s, pad in [(\"conv 3×3/2\", 3, 2, 0), (\"conv 3×3/1\", 3, 1, 0), (\"conv 3×3/1 补零\", 3, 1, 1),\n                        (\"pool 3×3/2\", 3, 2, 0), (\"conv 3×3/1\", 3, 1, 0), (\"conv 3×3/2\", 3, 2, 0)]:\n    m = out(n, k, s, pad)\n    print(f\"{name}：{n} → {m}，余数 {(n + 2 * pad - k) % s}\")\n    n = m\n\nfor name in [\"缩小到 17×17\", \"缩小到 8×8\"]:\n    m = out(n, 3, 2)\n    print(f\"{name}：{n} → {m}，余数 {(n - 3) % 2}\")\n    n = m\n```\n\n```text\nconv 3×3/2：299 → 149，余数 0\nconv 3×3/1：149 → 147，余数 0\nconv 3×3/1 补零：147 → 147，余数 0\npool 3×3/2：147 → 73，余数 0\nconv 3×3/1：73 → 71，余数 0\nconv 3×3/2：71 → 35，余数 0\n缩小到 17×17：35 → 17，余数 0\n缩小到 8×8：17 → 8，余数 0\n```\n\n每一个步幅 2、不补零的层都恰好整除，没有任何一行像素被丢掉，最后落在表上的 $35$、$17$、$8$。论文没有解释为什么选 299，但这组数字确实让整条路径对得很整齐。\n\n### 让模型别太有把握\n\n最后一个零件和架构无关，处理的是标签。\n\n对一张训练图像 $x$，模型用 softmax 算出每个类别的概率：\n\n$$\np(k\\mid x) = \\frac{\\exp(z_k)}{\\sum_{i=1}^{K}\\exp(z_i)}\n$$\n\n$z_k$ 是 logits。真实标签的分布记为 $q(k\\mid x)$，交叉熵损失是：\n\n$$\n\\ell = -\\sum_{k=1}^{K} \\log p(k)\\, q(k)\n$$\n\n它对 logits 的梯度很简单：$\\partial\\ell/\\partial z_k = p(k) - q(k)$，大小落在 $-1$ 到 $1$ 之间。\n\n一般的训练用 one-hot 标签：正确类别 $y$ 的 $q(y)=1$，其他都是 0。要让损失降到最低，$p(y)$ 要等于 1，这在有限的 logits 下做不到，只能让 $z_y$ 比其他 logits 越来越大。\n\n作者指出这会造成两个问题。第一，模型学会对每张训练图像都给出百分之百的信心，不一定能泛化。第二，最大的 logit 和其他 logits 的差距被推得很大，梯度又有上限，模型就更难再调整。说白了，模型对自己的预测太有把握了。\n\n他们的做法是把标签分布换掉：\n\n$$\nq'(k\\mid x) = (1-\\epsilon)\\,\\delta_{k,y} + \\epsilon\\, u(k)\n$$\n\n$u(k)$ 是一个和图像无关的固定分布，作者用的是均匀分布 $u(k)=1/K$。这个做法叫 label smoothing regularization（LSR）。ImageNet 有 $K=1000$ 类，$\\epsilon=0.1$。\n\n我们直接把 logits 当作参数，看两种标签会把它推到哪里：\n\n```python\nimport torch\nimport torch.nn.functional as F\n\nK, eps, y = 1000, 0.1, 0\nhard = torch.zeros(K); hard[y] = 1\nsmooth = (1 - eps) * hard + eps / K\nprint(\"平滑后的目标：正确类别\", round(smooth[y].item(), 4), \"，其他类别\", round(smooth[1].item(), 4))\n\nfor name, q in [(\"one-hot\", hard), (\"label smoothing\", smooth)]:\n    z = torch.zeros(K, requires_grad=True)               # 直接把 logits 当作参数，看损失把它推向哪里\n    opt = torch.optim.SGD([z], lr=1.0)\n    for step in range(1, 20001):\n        loss = -(q * F.log_softmax(z, 0)).sum()\n        opt.zero_grad(); loss.backward(); opt.step()\n        if step in (100, 1000, 20000):\n            gap = (z[y] - z[1:].max()).item()\n            print(f\"{name:15s} 第 {step:5d} 步：正确类别的 logit 领先 {gap:6.3f}\")\n\nprint(\"label smoothing 的终点：ln(0.9001 / 0.0001) =\", round(torch.log(torch.tensor(0.9001 / 0.0001)).item(), 3))\n```\n\n```text\n平滑后的目标：正确类别 0.9001 ，其他类别 0.0001\none-hot         第   100 步：正确类别的 logit 领先 11.417\none-hot         第  1000 步：正确类别的 logit 领先 13.805\none-hot         第 20000 步：正确类别的 logit 领先 16.810\nlabel smoothing 第   100 步：正确类别的 logit 领先  9.105\nlabel smoothing 第  1000 步：正确类别的 logit 领先  9.105\nlabel smoothing 第 20000 步：正确类别的 logit 领先  9.105\nlabel smoothing 的终点：ln(0.9001 / 0.0001) = 9.105\n```\n\n用 one-hot 时，差距一直在增长，训练多久就推多远。换成平滑的标签，差距停在 9.105。这个数字可以直接算出来：损失最小时 $p = q'$，而在 softmax 下，两个类别的 logit 之差，等于它们概率之比的对数，也就是 $\\ln(0.9001/0.0001)$。\n\n作者还给出了另一种看法。把交叉熵展开：\n\n$$\nH(q', p) = (1-\\epsilon)\\,H(q, p) + \\epsilon\\, H(u, p)\n$$\n\n相当于在原本的损失之外，多加了一项惩罚：预测分布 $p$ 离均匀分布 $u$ 太远，就要付出代价。\n\n在 ILSVRC 2012 上，加上 LSR 让 top-1 错误率从 23.1% 降到 22.8%，top-5 从 6.3% 降到 6.1%。\n\n\n> [!NOTE]\n> \n> 四年后，Rafael Müller、Simon Kornblith 与 Geoffrey Hinton 在 NeurIPS 2019 的 [When Does Label Smoothing Help?](https://arxiv.org/abs/1906.02629) 中回头研究了这个技巧。他们发现 label smoothing 能改善模型的校准，也会让同一类训练样本在倒数第二层的表示聚得更紧；代价是 logits 里「这张图和其他类别有多像」的信息变少了，所以用 label smoothing 训练的教师模型，做知识蒸馏的效果会差很多。\n\n\n### 训练设置\n\n作者用 TensorFlow 做分布式训练，50 个副本各跑在一张 NVIDIA Kepler GPU 上，每个副本的批量大小是 32，训练 100 个 epoch。\n\n早期的实验用 momentum，最好的模型改用 RMSProp（decay 0.9、$\\epsilon=1.0$）。学习率 0.045，每两个 epoch 乘以 0.94。梯度裁剪设为 2.0，用来稳定训练；评估时使用参数的滑动平均。\n\n## 讨论\n\n### 一项一项加上去\n\n| 网络 | Top-1 错误率 | Top-5 错误率 | 计算量（十亿次运算） |\n| --- | ---: | ---: | ---: |\n| GoogLeNet | 29% | 9.2% | 1.5 |\n| BN-GoogLeNet | 26.8% | – | 1.5 |\n| BN-Inception | 25.2% | 7.8% | 2.0 |\n| Inception-v2 | 23.4% | – | 3.8 |\n| ＋ RMSProp | 23.1% | 6.3% | 3.8 |\n| ＋ Label Smoothing | 22.8% | 6.1% | 3.8 |\n| ＋ 分解 7×7 | 21.6% | 5.8% | 4.8 |\n| ＋ BN 辅助分类器 | **21.2%** | **5.6%** | 4.8 |\n\n*表：摘自原论文 Table 3。ILSVRC 2012 验证集，单次裁剪。从 Inception-v2 这一行往下，每一行都包含前面所有的改动。*\n\n这张表是累加的：每一行都在上一行的基础上多加一项。最后一行「BN 辅助分类器」指辅助分类器里的全连接层也加上了 batch normalization，而不只是卷积层。**加完所有改动的版本，作者称为 Inception-v3**。\n\n几个值得看的地方：\n\n- 光是换成新的架构（Inception-v2 那一行），top-1 错误率就从 BN-Inception 的 25.2% 降到 23.4%，但计算量也从 2.0 涨到 3.8。\n- RMSProp 和 label smoothing 都不增加计算量，各自带来 0.3 个百分点左右的 top-1 改善。\n- 把第一层 $7\\times7$ 拆成三层 $3\\times3$，计算量从 3.8 涨到 4.8，top-1 进步 1.2 个百分点，是后面几项里最大的一步。\n\n整体来看，Inception-v3 的计算量大约是 BN-Inception 的 2.4 倍、GoogLeNet 的 3.2 倍。\n\n\n> [!TIP]\n> \n> 这里的命名有点乱。这篇论文把新架构叫 Inception-v2，所有改动都加上去之后才叫 Inception-v3。可是第二年的 Inception-v4 论文回顾这个家族的历史时，把加了 batch normalization 的 BN-Inception 称为 Inception-v2。之后看到「Inception-v2」，要先确认指的是哪一个。\n> \n> BN-Inception 的来源可以看我们的笔记：\n> \n> - **[[15.02] BatchNorm：批次标准化](/blog/papers/normalization/batchnorm)**\n\n\n所有评估都用 ILSVRC 2012 验证集里没有被列入黑名单的 48,238 张图像。作者也试过用全部 50,000 张，top-5 错误率大约差 0.1 个百分点，top-1 大约差 0.2 个百分点。\n\n### 分辨率低一点，差多少？\n\n检测系统常常要对一小块图像做分类，物体又小又模糊。一般认为输入分辨率越高越好，但作者指出，这里混了两件事：第一层感受野的分辨率，以及模型本身的容量和计算量。如果只把输入缩小、模型不动，就等于用一个便宜得多的模型去解更难的问题。\n\n所以他们固定计算量，只改变输入分辨率。输入变小时，就去掉前面的步幅或池化，让后面的特征图大小保持差不多：\n\n| 感受野大小 | 调整方式 | Top-1 准确率 |\n| --- | --- | ---: |\n| $79\\times79$ | 第一层步幅 1，之后不池化 | 75.2% |\n| $151\\times151$ | 第一层步幅 1，之后最大池化 | 76.4% |\n| $299\\times299$ | 第一层步幅 2，之后最大池化 | 76.6% |\n\n*表：摘自原论文 Table 2，调整方式整理自第 9 节的实验说明。*\n\n三个网络的计算量几乎相同。分辨率低的网络训练得比较久，但最后的成绩和 $299\\times299$ 相差不大：$151\\times151$ 只差 0.2 个百分点，$79\\times79$ 差 1.4 个百分点。\n\n作者据此建议，在 R-CNN 这类检测流程里，可以考虑为小物体准备专门的、分辨率低但计算量不低的网络。\n\n### 和其他模型比较\n\n单个模型、多次裁剪的比较：\n\n| 网络 | 裁剪数 | Top-1 错误率 | Top-5 错误率 |\n| --- | ---: | ---: | ---: |\n| GoogLeNet | 144 | – | 7.89% |\n| VGG | – | 24.4% | 6.8% |\n| BN-Inception | 144 | 22% | 5.82% |\n| PReLU | – | 21.59% | 5.71% |\n| Inception-v3 | 12 | 19.47% | 4.48% |\n| **Inception-v3** | **144** | **18.77%** | **4.2%** |\n\n*表：摘自原论文 Table 4 的部分行。*\n\n多个模型集成的比较：\n\n| 网络 | 模型数 | 裁剪数 | Top-1 错误率 | Top-5 错误率 |\n| --- | ---: | ---: | ---: | ---: |\n| VGGNet | 2 | – | 23.7% | 6.8% |\n| GoogLeNet | 7 | 144 | – | 6.67% |\n| PReLU | – | – | – | 4.94% |\n| BN-Inception | 6 | 144 | 20.1% | 4.9% |\n| **Inception-v3** | **4** | **144** | **17.2%** | **3.58%** |\n\n*表：摘自原论文 Table 5。Inception-v3 的 3.58% 是测试集结果，其余来自验证集。*\n\n在结论里，作者拿 He 等人的 PReLU 网络做比较：Inception-v3 的 top-5 和 top-1 错误率相对降低了 25% 和 14%，计算量却便宜六倍，参数也少了至少五倍（作者注明是估计值）。四个模型的集成，top-5 错误率大约是 2014 年 GoogLeNet 冠军集成的一半。\n\n## 结论\n\n这篇论文读起来更像一本设计笔记。Table 3 一项一项地累加，让每个改动的贡献都看得见；四条设计原则，作者也坦白地标成还需要验证的经验法则。\n\n最后整理一下这篇留下的零件：\n\n1. **把大卷积核拆成小的**：$5\\times5$ 换成两层 $3\\times3$，$n\\times n$ 换成 $1\\times n$ 接 $n\\times1$。\n2. **缩小特征图时，让卷积和池化并行**，避免信息被卡住。\n3. **辅助分类器的作用更像正则化**。\n4. **Label smoothing**，让模型别对答案太有把握。\n\n如果只能带走一个，大概就是 label smoothing：它和架构无关，加几行代码就能用，[ConvNeXt](/blog/papers/classic-cnns/convnext) 的训练配方里也有它。下一版的 Inception 就要和 ResNet 碰面了，我们[下一篇](/blog/papers/classic-cnns/inception-v4)接着看。\n","imageSizes":{"/content/papers/assets/c87d3d6fa9ea76d954eba2570f702150eca32d62c7cdb3d724075a4be9a63080.png":{"width":419,"height":358},"/content/papers/assets/26d9fd5f020cc9ce53cac89b03dbc710d155db812e4745d2e1c47a456faa3b1a.png":{"width":293,"height":401},"/content/papers/assets/d7b13cfd7a93816701d9571a2e87bd67983a5e6ffe9a7b93cbcf40e82db76a2f.png":{"width":623,"height":824},"/content/papers/assets/1475f4de3132dd0d1dbd081ddc453fb140796cb802987fa051a70356070b1b41.png":{"width":625,"height":539},"/content/papers/assets/9d6b75a1dd143d0b517f52adf42c4fe794cb400e3276a8109561db2277fb2fb6.png":{"width":635,"height":365}}}
