反向传播、CNN与ResNet:计算机视觉核心知识点全解析

📅 2026/8/27 4:56:00
反向传播、CNN与ResNet:计算机视觉核心知识点全解析
很多同学入门计算机视觉时都经历过这样一个阶段从开源仓库下载了完整的图像分类项目用现成的预训练权重跑通了 demo准确率还挺高可一旦把自己的业务图片丢进去效果立刻崩掉。想调参不知道从哪入手想改成自己的任务又看不懂网络定义里的每一行代码在干什么。问题出在哪出在很多教程把“学会调用模型”当成了“学会深度学习”。模型层的复制粘贴替代不了底层原理的理解。计算机视觉最核心的技术主线其实只有一条神经网络通过前向传播做预测通过反向传播学参数CNN 在神经网络基础上用卷积和池化解决图像特征提取问题ResNet 则在 CNN 基础上用残差学习解决了更深的网络难以训练的问题。三步走完就是从理论到工程的关键路径。这篇文章不打算堆砌花哨的网络结构而是把这条主线彻底讲透。读完你会搞清楚反向传播到底在算什么卷积层为什么比全连接层更适合图像ResNet 的恒等映射为什么能解决梯度消失和网络退化文章会提供 numpy 手写反向传播、PyTorch 搭建 CNN 与 ResNet 残差块的完整代码方便你边读边练。本文涉及的知识点基本覆盖了计算机视觉入门阶段最关键的几个核心概念值得收藏备用。1. 为什么要把反向传播、CNN 和 ResNet 放在一起学很多初学者的学习路径是割裂的先学“反向传播的公式推导”再学“CNN 的网络结构”最后看一篇“ResNet 论文解读”。结果每个知识点都似懂非懂遇到实际问题时依然无法串联起来。从技术演进的角度看这三个知识点不是三个并列章节而是一条连续的升级线技术要解决的核心问题反向传播神经网络的参数如何自动学习CNN如何用少量参数高效提取图像特征ResNet网络加深到一定程度后如何还能被稳定训练先有反向传播神经网络才真正“可学习”面对图像数据全连接网络参数量太大且无视空间结构于是 CNN 登场CNN 越深效果越好但深到一定程度后梯度消失、退化问题凸显于是 ResNet 登场。每一次升级都对应一个真实且具体的工程痛点。理解了痛点你就不会再问“为什么要加这一层”“为什么这里要用 1x1 卷积”这类问题。这篇文章适合以下几类读者刚入门深度学习跑过分类 demo但对底层原理不清晰的初学者。想转计算机视觉方向正在补核心基础的非 CV 方向开发。已经在用 PyTorch 做项目但需要系统梳理“神经网络如何训练、CNN 如何设计、ResNet 为什么有效”的工程师。如果你处在“代码能跑但心里没底”的阶段这篇文章的性价比会非常高。2. 神经网络的核心从感知机到前向传播2.1 感知机与神经元的基本计算神经网络的最小单位是“神经元”。最早的模型叫感知机它的计算方式非常朴素把输入做加权求和再加上偏置然后通过一个激活函数输出。单个神经元的输出可以写成z w1*x1 w2*x2 ... wn*xn b a f(z)其中w是权重b是偏置f是激活函数。权重决定“每个输入对结果的影响程度”偏置决定“神经元被激活的难易程度”。训练神经网络的核心任务就是找到一组最优的w和b让预测结果逼近真实标签。单个感知机只能解决线性可分问题能力有限。把大量神经元组织成“层”并且堆叠多层就形成了多层感知机。每一层接收上一层的输出经过线性变换和激活函数后再传给下一层。2.2 激活函数为什么不可或缺如果网络只有线性变换那么多层线性变换最终可以合并成一次线性变换。也就是说没有激活函数无论网络多深表达能力都和单层线性模型等价。激活函数的本质是给网络引入非线性。常用于分类任务的激活函数有Sigmoid将输入压缩到 0 到 1 之间公式为 σ(z) 1 / (1 e^(-z))适合二分类输出但两端导数趋近于 0容易梯度消失。Tanh将输入压缩到 -1 到 1 之间比 Sigmoid 均值更接近 0但仍存在饱和区。ReLUmax(0, z)计算简单正区间导数恒为 1能有效缓解梯度消失是目前 CNN 中最常用的激活函数。从工程角度看ReLU 的巨大优势是“导数稳定”。它在正区间导数恒为 1多个梯度相乘时不会因为激活函数导数过小而快速衰减。这一点在后面理解 ResNet 时还会反复出现。2.3 前向传播的矩阵表达实际工程中不会写 for 循环逐个神经元计算而是用矩阵运算批量完成。一个两层的全连接网络前向传播可以写成Z1 X W1 b1 A1 σ(Z1) Z2 A1 W2 b2 A2 σ(Z2)输入矩阵X的形状是[N, D]N是样本数D是特征数。W1和W2是两层的权重矩阵b1和b2是偏置。A1是隐藏层的输出A2是最终输出。这里的计算过程就是“前向传播”。前向传播本身只是完成了一次预测真正让模型从随机初始化变成有效模型的是接下来的反向传播。3. 反向传播算法让网络真正“学会”的发动机3.1 损失函数与梯度下降要让网络学会正确分类首先需要一个衡量“预测到底有多差”的指标这个指标就是损失函数。分类任务常用交叉熵损失回归任务常用均方误差损失。有了损失值之后问题变成如何通过调整w和b让损失值不断变小答案就是梯度下降。梯度的方向是函数值上升最快的方向所以参数沿着梯度的反方向更新就能让损失下降θ θ - η * ∂L/∂θ其中η是学习率。学习率太大参数更新过猛损失可能震荡甚至发散学习率太小网络收敛缓慢。调参时最先检查的往往就是这一项。3.2 链式法则与两层网络推导损失函数是网络输出的函数而网络输出又依赖于每一层的权重。想求“损失对深层参数的梯度”必须依赖微积分里的链式法则。这就是反向传播算法的数学基础。以一个两层网络为例z1 W1 x b1 a1 σ(z1) z2 W2 a1 b2 a2 σ(z2) L 0.5 * ||y - a2||^2其中x是输入y是标签L是损失。要更新输出层权重W2需要计算∂L/∂W2用链式法则展开∂L/∂W2 (∂L/∂a2) * (∂a2/∂z2) * (∂z2/∂W2)定义误差信号δ2 (a2 - y) * σ(z2)那么∂L/∂W2 δ2 * a1^T ∂L/∂b2 δ2继续往更浅的一层传播得到隐藏层的误差信号δ1 (W2^T * δ2) * σ(z1) ∂L/∂W1 δ1 * x^T ∂L/∂b1 δ1这就是反向传播的核心过程先做一次前向传播算出每层的输出再根据损失从输出层逐层往回计算梯度并更新参数。为什么要叫“反向”因为误差信号从输出层开始逐层向输入层方向传播。3.3 用 numpy 手动实现一次反向传播理论知识看再多都不如手写一个最小实现来得直观。下面用 numpy 实现一个 2-4-1 结构的两层网络解决 XOR 异或问题。XOR 是非线性可分问题单层感知机无法解决但两层网络可以。import numpy as np np.random.seed(42) # 网络结构2 - 4 - 1 w1 np.random.randn(2, 4) * 0.5 b1 np.zeros((1, 4)) w2 np.random.randn(4, 1) * 0.5 b2 np.zeros((1, 1)) # XOR 数据集 X np.array([[0, 0], [0, 1], [1, 0], [1, 1]], dtypenp.float32) y np.array([[0], [1], [1], [0]], dtypenp.float32) def sigmoid(z): return 1.0 / (1.0 np.exp(-z)) learning_rate 0.5 for epoch in range(10000): # 前向传播 z1 X w1 b1 a1 sigmoid(z1) z2 a1 w2 b2 a2 sigmoid(z2) loss np.mean((a2 - y) ** 2) # 反向传播 d_a2 2 * (a2 - y) / len(X) d_z2 d_a2 * a2 * (1 - a2) d_w2 a1.T d_z2 d_b2 np.sum(d_z2, axis0, keepdimsTrue) d_a1 d_z2 w2.T d_z1 d_a1 * a1 * (1 - a1) d_w1 X.T d_z1 d_b1 np.sum(d_z1, axis0, keepdimsTrue) # 参数更新 w2 - learning_rate * d_w2 b2 - learning_rate * d_b2 w1 - learning_rate * d_w1 b1 - learning_rate * d_b1 if epoch % 1000 0: print(fEpoch {epoch:4d}, Loss: {loss:.6f}) print(训练后的预测结果应接近 0,1,1,0) print(np.round(a2, 4))运行这段代码会看到 Loss 随着迭代次数增加而下降。训练结束后预测结果会接近 XOR 的目标输出。关键逻辑在于d_z2是输出层误差信号d_z1是隐藏层误差信号而隐藏层误差信号正是由输出层误差信号乘以w2.T反向传递回来的。这就是“反向”二字的由来。4. 卷积神经网络面向图像的结构设计4.1 全连接层处理图像的三大难题把全连接网络直接用于图像会立刻遇到三个问题第一参数量爆炸。一张 32x32 的彩色图片展开后是 3072 维。如果全连接网络第一个隐藏层有 128 个神经元仅这一层就需要约 39 万个参数。如果是更大的图片参数量会迅速膨胀到无法训练。第二破坏空间结构。图像中相邻像素有强相关性边缘、纹理、颜色变化都体现在局部区域。把像素打平成向量后局部信息被彻底打散网络很难学到“物体是由局部特征组合而成”的规律。第三难以保持平移不变性。同一只猫在图片中位置移动一点全连接网络需要重新学习才能识别因为它对“每个像素位置”单独建模。4.2 卷积层局部感受野与参数共享CNN 的解决方案是用卷积层替代全连接层。卷积层有两个核心设计局部连接和参数共享。局部连接是指每个输出神经元只与输入的一小块区域相连这一小块区域就是“感受野”。比如 3x3 卷积核输出位置的每个值只由输入中对应位置附近 3x3 区域的像素计算而来。参数共享是指同一个卷积核以滑窗方式遍历整张图像所有位置共享同一组权重。这意味着无论物体出现在图像的左上角还是右下角同一个卷积核都能检测出同一种特征。一个具体实例能直观说明参数量的差距。输入是 32x32x3 的图像如果卷积层使用 32 个 3x3 卷积核参数量为3 * 3 * 3 * 32 32 896而同等情况下全连接层的参数量高达几十万。CNN 之所以能处理图像正是因为这“一减一