ResNet-18 的意义在哪里?——从普通 CNN 到残差网络的系统性比较
“你花了三天训练一个50层CNN,结果准确率还不如10层的?不是代码错了,而是深层网络自己‘学废了’。”
一、从普通 CNN 说起:为什么“加深网络”并不等于“提升性能”
在卷积神经网络发展的早期,一个非常自然、几乎不需要解释的想法是:通过不断堆叠卷积层,让网络变得更深,从而获得更强的表达能力。这一思路在很长一段时间内都被事实所验证。
从 LeNet 到 AlexNet,再到 VGG,模型深度的增加确实带来了性能的持续提升。以 VGG 为代表的工作,通过统一使用 3×3 卷积核,将网络深度系统性地扩展到 16 层甚至 19 层,并在ImageNet 等大规模数据集上取得了显著效果。这一阶段,“更深 = 更强”几乎成为共识。
但问题也正是在这里开始出现的。当研究者尝试沿着 VGG 的思路继续加深网络时,现象却变得反直觉:网络在前向传播上完全正常,参数量和计算量虽然增加,但仍在可接受范围内,真正的困难出现在训练阶段。当深度达到一定程度后,即使在训练集上,误差也不再下降,甚至出现退化。
这说明,问题并不在于模型容量是否足够,而在于深层网络的优化本身出现了结构性障碍。
二、普通 CNN 与 ResNet 的根本差异:它们在“学什么”上不同
要理解 ResNet 的意义,必须先搞清楚它和普通 CNN 的本质区别,而这个区别并不在“层数”,而在每一层被要求完成的任务不同。
在普通 CNN 中,每一层都被隐含地要求学习一个“新的表示”。这些表示层层叠加,逐步构成最终的特征空间。这种设计背后有一个不言自明的假设:每一层都必须对结果产生正向贡献。一旦某几层学不到有价值的特征,它们不仅帮不上忙,反而会成为优化过程中的负担。
ResNet 对这一假设做了根本性的放松。它并没有要求每一层“必须有用”,而是通过残差结构引入了一种更现实的选择:这一层可以学习对输入的修正,也可以选择什么都不做。具体来说,网络不再直接学习完整映射,而是学习相对于输入的差值,最终输出由输入与残差相加得到。
这一改变看似简单,却直接改变了深层网络的优化形态。恒等映射不再是“需要努力学出来的结果”,而成为结构上的默认行为。网络深度的增加,也就不再必然意味着训练难度的指数级上升。
这里有一个非常关键、但经常被一笔带过的比较点:为什么“什么都不做”在普通 CNN 中反而这么难?
在普通 CNN 里,要学成一个严格的恒等映射,需要多层参数在数值上精确配合,这在高维非线性空间中几乎是一个不稳定的极端解。而在 ResNet 中,恒等映射由结构直接提供,根本不依赖参数学习。这正是 ResNet 能够“堆深而不崩”的根本原因。
三、ResNet-18 与更深 ResNet 的比较:为什么不是越深越好?
需要强调的是,ResNet 并不是一个具体模型,而是一个网络家族。ResNet-18、34、50、101 之间的差异,并不只是“层数更多或更少”,而是结构复杂度和工程代价的不同权衡。不同版本的残差块和深度在计算量、参数量和适用场景上各有差异,如下表所示:
| 模型 | 残差块类型 | 网络深度 | 参数量 | 特点 |
|---|---|---|---|---|
| ResNet-18 | BasicBlock | 18 | ≈11M | 结构简单、训练稳定、适合中小数据集 |
| ResNet-34 | BasicBlock | 34 | ≈21M | 更深,计算量增加,仍适合中等任务 |
| ResNet-50 | Bottleneck | 50 | ≈25M | 引入 Bottleneck,提高参数效率,适合大数据 |
| ResNet-101 | Bottleneck | 101 | ≈44M | 适合大规模数据集,训练更耗时 |
ResNet-18 和 ResNet-34 使用的是最基础的 BasicBlock,结构直观、路径清晰;ResNet-50 及以上则引入 Bottleneck 结构,通过 1×1 卷积提高参数效率,适合更大规模的数据和算力环境。从工程角度看,ResNet-18 的优势并不在于性能上限,而在于它的稳定性、可控性和调试友好性。
在数据量有限或计算资源受限的场景下,更深的网络未必能带来收益,反而可能更容易过拟合,或者增加训练与部署成本。因此,在实践中,ResNet-18 常被用作基准模型或任务验证的第一选择,它的表现往往能较为真实地反映任务本身的难度。
四、ResNet-18 与 VGG 的直接对比:结构差异带来的实际影响
以 VGG-16 和 ResNet-18 为例,可以更直观地看到残差连接带来的差异:
| 对比维度 | VGG-16 | ResNet-18 |
|---|---|---|
| 网络思想 | 纯层堆叠 | 残差连接 |
| 参数量 | ≈138M | ≈11M |
| 层数 | 16 | 18 |
| 训练稳定性 | 深层易退化 | 稳定 |
| 泛化能力 | 高度依赖正则化 | 表现均衡 |
| 适用场景 | 大数据训练 | 中小数据集 & 基线任务 |
可以看到,ResNet-18 并不是靠“更深”或“更大”取胜,而是通过结构设计提高训练效率和参数利用率,显著改善了深层网络的可训练性和稳定性。
如果从工程视角做一次更直观的比较,VGG-16 和 ResNet-18 的差异非常具有代表性。VGG-16 依赖纯粹的层堆叠来提升表达能力,参数量高达一亿级别,而 ResNet-18 通过残差连接显著降低了冗余参数,整体参数量只有千万级。
这种结构差异带来的影响是实实在在的:ResNet-18 在训练稳定性上明显优于 VGG,泛化能力也不再高度依赖强正则化或复杂的训练技巧。它并不是靠“更深”或“更大”取胜,而是通过结构设计,提高了参数利用率和优化效率。
五、ResNet-18 在实际应用中的位置
在真实项目中,ResNet-18 更多承担的是“基础模型”的角色。它往往不是最终追求极致性能的选择,但却是判断一个任务是否可行的可靠起点。如果 ResNet-18 在某个任务上表现不佳,问题通常出现在数据质量、标签噪声或任务本身的可分性上,而很少是网络结构的瓶颈。
正因为如此,ResNet-18 才会在工程实践和教学中被反复使用:它足够简单,又包含了现代深度网络最核心的结构思想。
动手试试:用 ResNet-18 对一张图片进行分类(完整可运行示例)
下面是一个端到端、开箱即用的 Python 示例,展示如何使用 PyTorch 调用预训练的 ResNet-18 模型,对本地图片进行图像分类。你只需替换图片路径,即可看到 AI 的“视觉理解”结果。
✅ 本示例已在 Jupyter Notebook + Windows 11 + Python 3.12 环境下验证通过。
运行环境要求
| 组件 | 版本/说明 |
|---|---|
| Python | ≥ 3.8(推荐 3.10–3.12) |
| PyTorch | ≥ 2.0(本文使用 2.4.0) |
| TorchVision | ≥ 0.15(与 PyTorch 匹配) |
💡 首次运行会自动下载模型权重(约 44MB)和标签文件,请确保网络畅通。
# ==============================
# ResNet-18 图像分类示例(PyTorch 最佳实践)
# ==============================
import torch
from PIL import Image
import requests
from torchvision import models
from torchvision.models import ResNet18_Weights
# 1. 加载预训练模型(使用官方推荐权重)
weights = ResNet18_Weights.DEFAULT
model = models.resnet18(weights=weights)
model.eval() # 切换到评估模式
# 2. 使用与训练时完全一致的预处理流程
preprocess = weights.transforms() # 自动包含 Resize, Crop, Normalize
# 3. 加载并预处理本地图片(注意路径写法!)
img_path = r"dog.jpg" # ←替换成你的图片路径
input_img = Image.open(img_path).convert("RGB")
input_tensor = preprocess(input_img)
input_batch = input_tensor.unsqueeze(0) # 添加 batch 维度
# 4. 自动选择设备(GPU/CPU)
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model.to(device)
input_batch = input_batch.to(device)
# 5. 执行推理(关闭梯度以提升速度)
with torch.no_grad():
output = model(input_batch)
# 6. 解析预测结果
_, predicted_idx = torch.max(output, 1)
# 7. 加载 ImageNet 人类可读标签
labels_url = "https://raw.githubusercontent.com/anishathalye/imagenet-simple-labels/master/imagenet-simple-labels.json"
imagenet_labels = requests.get(labels_url).json()
# 8. 输出结果
print(f"✅ Predicted class: {imagenet_labels[predicted_idx.item()]}")
测试图片:

🛠 使用步骤
- 将上述代码粘贴到 Jupyter Notebook 的一个 Cell 中;
- 修改
img_path为你电脑中某张图片的绝对路径(建议使用清晰的物体、动物或场景图); - 运行 Cell,等待几秒(首次会下载模型),即可看到输出:
✅ Predicted class: Pembroke Welsh Corgi
译:Pembroke Welsh Corgi(彭布罗克威尔士柯基犬;彭布罗克柯基犬;威尔斯科基犬)

⚠️ 常见问题 & 避坑指南
| 问题 | 原因 | 解决方案 |
|---|---|---|
SyntaxError: 'unicodeescape' codec can't decode... |
路径中的 \ 被当作转义符 |
在路径前加 r,如 r"C:\path\to\img.jpg" |
NameError: name 'requests' is not defined |
未导入 requests |
确保代码开头有 import requests |
出现 pretrained 警告 |
使用了旧版 API | 请使用 weights=ResNet18_Weights.DEFAULT(本代码已采用) |
| 预测结果不准 | 图片太小/模糊/非自然图像 | 使用清晰、主体明确的照片(如 ImageNet 风格) |
💡 为什么这个例子值得你跑一遍?
- 它是工业级视觉系统的最小原型:从手机相册智能分类到自动驾驶感知,底层逻辑与此高度一致;
- 它展示了 ResNet-18 的工程价值:轻量(仅 11M 参数)、稳定、易于部署;
- 它帮你验证本地环境是否配置正确——如果能跑通,说明你的 PyTorch 安装成功!
🌟 小挑战:试试用不同图片(猫、汽车、杯子)测试,看看 ResNet-18 能否准确识别?欢迎在评论区分享你的结果!
六、ResNet-18 的价值,并不在“18 层”
如果一定要总结 ResNet-18 的意义,它并不在于“18 层”这个数字,而在于它清晰地展示了一件事:通过合理的结构设计,深度网络可以在不断加深的同时,仍然保持良好的可训练性。ResNet-18 是残差思想最直接、最不被复杂技巧掩盖的版本,也因此成为理解后续各种深度网络结构的最佳起点。
更多推荐


所有评论(0)