这一节非常关键,因为从这里开始,深度学习进入了一个非常重要的阶段:
不是简单问“网络能不能更深”,而是问“网络更深之后,为什么还能训得动、训得好?”
前言
学完前面的 LeNet、AlexNet、VGG、NiN、GoogLeNet、Batch Normalization 之后,你会发现卷积神经网络一直在不断变强:
-
层数越来越多
-
结构越来越复杂
-
训练技巧越来越成熟
按理说,网络更深,表达能力应该更强,效果也应该更好。
但研究者后来发现了一个很奇怪的现象:
网络不是越深越好。
甚至有时候会出现这种情况:
-
一个 20 层网络效果还不错
-
一个 56 层网络反而更差
这就很反直觉。
按常理来说,更深的网络至少不该比浅层网络差,因为更深网络理论上可以学成“和浅层一样”。
可现实却不是这样。
于是,ResNet 出现了。
它要解决的核心问题就是:
如何让神经网络在不断加深的同时,仍然能够稳定训练,并且性能继续提升?
一、什么是 ResNet?
ResNet 的全称是 Residual Network,中文通常叫做 残差网络。
它是何恺明(Kaiming He)等人提出的经典深度卷积神经网络,也是深度学习历史上最有影响力的模型之一。
ResNet 最核心的创新就是:
残差连接(Residual Connection)
也常被叫做:
-
跳跃连接(Skip Connection)
-
快捷连接(Shortcut Connection)
这个设计看起来很简单,但威力非常大。
它让神经网络可以轻松堆到几十层、上百层,甚至更深。
二、ResNet 为什么重要?
ResNet 的重要性,不只是因为它效果好,而是因为它解决了“深层网络训练困难”这个关键问题。
它的重要意义主要有三点。
1. 它让网络真的可以变得很深
在 ResNet 之前,大家已经在尝试把网络加深,但深到一定程度之后,效果不升反降。
ResNet 提供了一种非常有效的解决方案,让网络能够继续往更深走。
2. 它重新定义了深层网络的设计方式
从 ResNet 开始,很多后续模型都深受“残差连接”思想影响。
后面的很多网络,哪怕结构不同,也往往会借鉴 skip connection 的设计思想。
3. 它成为现代视觉模型的重要基础
在目标检测、图像分类、分割等领域,ResNet 长期都是非常常用的 backbone(主干网络)。
所以它不只是“历史经典”,也是非常实用的基础网络。
三、深层网络到底出了什么问题?
理解 ResNet,首先要理解它到底在解决什么问题。
很多同学一开始会以为,深层网络的问题只是:
-
梯度消失
-
梯度爆炸
这些当然是问题,但 ResNet 关注的还有另一个更重要的现象:
退化问题(Degradation Problem)
什么叫退化问题?
退化问题指的是:
当网络层数继续增加时,训练误差反而变大,测试误差也变差。
注意,这里不是单纯的“过拟合”。
过拟合
是训练集效果很好,但测试集变差。
退化问题
是连训练集效果都变差了。
这说明问题不是“模型太强导致泛化差”,而是:
更深的网络本身就更难优化。
为什么这很反常?
因为理论上,更深网络至少可以做到不比浅层差。
比如一个浅层网络表现很好,那更深网络完全可以把新增的那些层学成“恒等映射”,这样输出就和浅层网络一样。
也就是说:
更深网络应该至少能复制浅层网络的效果。
但现实中它偏偏做不到,这就说明优化过程出了问题。
四、ResNet 的核心思想是什么?

五、残差连接长什么样?

直观理解
你可以把它理解成:
-
传统网络:从 0 开始重新学一个完整结果
-
ResNet:先保留原始输入,再只学习“需要改动的部分”
这就像改作文:
-
传统网络:整篇重写
-
ResNet:保留原文,只改需要修改的地方
显然,很多时候“学改动量”会比“从头重写”更容易。
六、为什么学习残差更容易?
这是 ResNet 最核心的思想。
假设最理想的映射其实就是恒等映射:
[
H(x)=x
]
那在传统网络里,模型需要自己费劲去学出一个“输出等于输入”的复杂映射。
但在 ResNet 里,只需要:
[
F(x)=0
]
也就是说,卷积分支什么都不用学,只要学成 0,整个块的输出自然就是输入本身。
这说明:
当最优解接近恒等映射时,残差学习会比直接学习目标映射容易得多。
而深层网络里,很多新增层其实并不一定需要做很复杂的变换,所以这种设计特别有效。
七、ResNet 的残差块有哪些类型?
在 ResNet 中,常见残差块主要有两种。
八、ResNet 的基本残差块结构

九、为什么残差连接能缓解深层网络训练问题?
这里是理解 ResNet 的关键。
1. 让信息更容易直接传下去
有了 shortcut,输入 (x) 可以直接绕过若干层,传到后面。
这意味着:
-
原始信息不会轻易丢失
-
后面的层不必完全依赖一层层复杂变换
所以深层网络中的信息流动会更顺畅。
2. 让梯度传播更顺畅
反向传播时,梯度也可以通过 shortcut 更直接地往前传。
这样就减少了梯度在很多层中不断衰减的风险。
所以你可以把残差连接理解成:
给前向传播和反向传播都开了一条“高速通道”。
3. 让网络更容易逼近恒等映射
如果新增层没什么必要,那残差分支只要学成 0 就行,整个块依然能正常工作。
这样一来,“加深网络”这件事本身就不会那么危险了。
十、ResNet 的整体结构是什么样的?

十一、ResNet-18 / ResNet-34 和 ResNet-50 有什么区别?

十二、为什么瓶颈块很重要?
因为如果网络很深,通道数又大,直接堆普通 3×3 卷积会非常贵。
瓶颈块的核心思想和 GoogLeNet 有点像:
用
1×1卷积做通道调整,降低计算成本。
所以它能在不牺牲太多表达能力的前提下,让更深网络变得可行。
十三、ResNet 的优点是什么?
1. 可以训练非常深的网络
这是 ResNet 最大的贡献。
2. 优化更容易
残差连接显著缓解了深层网络训练困难问题。
3. 泛化性能强
ResNet 在很多视觉任务上都表现很好。
4. 可迁移性强
它可以很方便地作为各种视觉任务的 backbone。
十四、ResNet 的局限性是什么?
虽然 ResNet 非常经典,但也不是没有问题。
1. 网络越深,计算量仍然会增加
残差连接解决了优化问题,但没有让计算“白送”。
2. 结构虽然有效,但不是唯一最优方案
后面还发展出了 DenseNet、EfficientNet、Vision Transformer 等不同方向。
3. 更深不一定永远更好
在具体任务中,还要看数据量、算力、任务复杂度等因素。
不过即便如此,ResNet 依然是深度学习历史上最成功的架构之一。
十五、PyTorch 中如何实现一个残差块?
下面先看一个简化版 BasicBlock 的写法。
import torch
from torch import nn
import torch.nn.functional as F
class Residual(nn.Module):
def __init__(self, in_channels, out_channels, use_1x1conv=False, strides=1):
super().__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1, stride=strides)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
self.bn1 = nn.BatchNorm2d(out_channels)
self.bn2 = nn.BatchNorm2d(out_channels)
if use_1x1conv:
self.conv3 = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=strides)
else:
self.conv3 = None
def forward(self, x):
y = F.relu(self.bn1(self.conv1(x)))
y = self.bn2(self.conv2(y))
if self.conv3:
x = self.conv3(x)
y += x
return F.relu(y)
这段代码里最关键的就是:
y += x
这一句就是残差连接的本质。
十六、PyTorch 中如何实现一个简化版 ResNet?
下面给你一个适合理解的简化版 ResNet 结构。
import torch
from torch import nn
import torch.nn.functional as F
class Residual(nn.Module):
def __init__(self, in_channels, out_channels, use_1x1conv=False, strides=1):
super().__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, padding=1, stride=strides)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, padding=1)
self.bn1 = nn.BatchNorm2d(out_channels)
self.bn2 = nn.BatchNorm2d(out_channels)
if use_1x1conv:
self.conv3 = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=strides)
else:
self.conv3 = None
def forward(self, x):
y = F.relu(self.bn1(self.conv1(x)))
y = self.bn2(self.conv2(y))
if self.conv3:
x = self.conv3(x)
y += x
return F.relu(y)
def resnet_block(in_channels, out_channels, num_residuals, first_block=False):
layers = []
for i in range(num_residuals):
if i == 0 and not first_block:
layers.append(Residual(in_channels, out_channels, use_1x1conv=True, strides=2))
else:
layers.append(Residual(out_channels, out_channels))
return nn.Sequential(*layers)
net = nn.Sequential(
nn.Conv2d(1, 64, kernel_size=7, stride=2, padding=3),
nn.BatchNorm2d(64),
nn.ReLU(),
nn.MaxPool2d(kernel_size=3, stride=2, padding=1),
resnet_block(64, 64, 2, first_block=True),
resnet_block(64, 128, 2),
resnet_block(128, 256, 2),
resnet_block(256, 512, 2),
nn.AdaptiveAvgPool2d((1, 1)),
nn.Flatten(),
nn.Linear(512, 10)
)
x = torch.randn(1, 1, 224, 224)
y = net(x)
print(y.shape)
输出:
torch.Size([1, 10])
十七、学习 ResNet 时最该抓住的核心点

十八、从前面几种网络一路发展到 ResNet,怎么理解?
到这里,这条经典 CNN 演化线已经很完整了。
LeNet
CNN 雏形,卷积 + 池化 + 全连接
AlexNet
让深度学习视觉爆发,引入 ReLU、Dropout、GPU 训练
VGG
用小卷积核堆叠,把深层 CNN 做得更规整
NiN
引入 1×1 卷积和全局平均池化
GoogLeNet
引入 Inception,多分支、多尺度特征提取
Batch Normalization
让深层网络训练更稳定
ResNet
通过残差连接,真正让超深网络变得可训练、可优化
所以一句话概括:
前面的网络在回答“怎么让 CNN 更强”,而 ResNet 回答的是“怎么让 CNN 变得很深之后依然能训练成功”。
十九、总结
ResNet 这一节最核心的内容,可以记成下面几点:
1. ResNet 的核心问题
解决深层网络中的退化问题。
2. ResNet 的核心思想
不直接学习目标映射,而是学习残差:
H(x)=F(x)+x
3. 残差连接的作用
-
保留原始信息
-
促进梯度传播
-
让优化更容易
4. ResNet 的结构本质
把普通卷积块替换成残差块,再进行深层堆叠。
5. ResNet 的历史意义
它让神经网络能够真正走向几十层、上百层,并深刻影响后续深度学习模型设计。
二十、结尾
ResNet 最震撼人的地方在于,它的核心创新其实非常朴素:
给网络加一条“直接通路”。
但正是这个看似简单的设计,彻底改变了深层神经网络的发展方向。
很多时候,真正伟大的创新并不是特别复杂,而是:
一下子抓住问题本质,并用最有效的方式解决它。
ResNet 就是这样一个代表。

3万+

被折叠的 条评论
为什么被折叠?



