拓冰建站拓冰建站
首页 / 资讯中心 / 正文

从反向传播到ResNet:计算机视觉学习主线与核心原理

计算机视觉入门最容易被卡住的地方不是环境配置而是从反向传播、神经网络、CNN一路到ResNet这条主线没有串起来。很多人一开始就去看ResNet的结构图结果回头发现卷积、池化、梯度下降都没搞清楚。反过来如果先把前向传播和反向传播吃透再看CNN会轻松很多再看ResNet就只是一个加了快捷连接的CNN。如果你正想进入计算机视觉方向或者已经在用现成框架跑模型、但总觉得基础不牢下面这份内容会比较对胃口。最值得关注的不是记住几个模型名字而是理解“为什么要这样设计”。我会按一条完整的学习路线把神经网络、反向传播、CNN和ResNet的核心原理拆开讲同时补上训练和排查中容易踩的坑。1. 先理顺主线神经网络、反向传播、CNN与ResNet分别解决什么问题1.1 计算机视觉任务本质是“像素到语义”图像分类、目标检测、图像分割这些计算机视觉任务输入都是图片输出却不同。分类网络输出一个标签检测网络输出多个框和类别分割网络输出逐像素的类别结果。形式不同本质一致把成千上万个像素值转换成人类能理解的语义信息。难点在于图像数据没有固定规则。同一个物体换个角度、光照、遮挡像素值都会大变。传统图像处理靠人工设计特征比如颜色直方图、边缘检测算子能解决一部分简单场景但泛化能力有限。神经网络的方式是让模型自己从数据里学出特征层级底层学边缘、颜色中层学纹理、局部形状高层学物体部件和类别语义。1.2 反向传播是“训练机制”CNN和ResNet是“网络结构”我接触过不少刚入门的人最容易混淆的点是反向传播和网络结构是两回事。CNN、ResNet这类名词描述的是数据如何向前传播比如卷积层怎么扫过图像、残差块怎么跨层连接。反向传播描述的是训练时梯度如何从损失函数向回传播从而更新每一层参数。所以学习顺序不能乱。你可以在一个简单的全连接网络上把反向传播搞明白再把全连接替换成卷积层理解CNN。最后在深层CNN里加入残差连接得到ResNet。如果一上来就啃ResNet论文会同时面对卷积、BatchNorm、残差结构、梯度传播和训练策略多个新概念很难一次吸收。1.3 整条主线是“参数越来越多训练越来越难结构不断修正”从单个神经元到多层感知机从CNN到ResNet核心变化是模型容量变大。模型容量大才能拟合复杂图像分布但容量大也意味着训练难容易出现梯度消失、梯度爆炸、优化不收敛、训练数据不足等问题。ResNet的出现本质就是给“让深层网络变得可训练”提供了一个稳定的结构手段。学习时可以把每个模块当成一个“问题答案”来记神经网络用参数化映射拟合数据。反向传播高效求梯度、更新参数。卷积层用局部连接和权值共享降低参数量。残差块用恒等映射让深层网络退化问题得到缓解。这样学下来结构图才不是死记而是可以推导出来的。2. 从神经元到前向传播先搞懂数据在神经网络里怎么流动2.1 神经元本质是“线性变换加非线性激活”神经网络的基本单元是神经元。一个神经元接收多个输入先做线性加权再加上偏置然后经过一个激活函数输出。用公式写就是z W · x ba f(z)其中x是输入向量W是权重矩阵b是偏置f是激活函数。全连接层就是很多神经元排在一起把输入映射到输出。前向传播就是把数据从输入层一层一层算到输出层。这个过程本身不难难的是理解每个参数的作用权重表示“某个输入对结果的影响程度”偏置表示“输入为零时输出偏向”。在图像任务里输入通常是三维张量长、宽、通道数全连接层会把三维张量压平成一维向量再计算。以MNIST手写数字为例一张图是28×28灰度图通道数为1展开后是784个像素值。如果第一个隐藏层有128个神经元那么这一层权重矩阵大小是784×128偏置是128。这个规模还不算大但已经能看到全连接层的参数会随输入尺寸和隐藏神经元数量快速增长。到了256×256的彩色图片展开后是196608个像素如果用全连接直接接到1000类第一层参数量就会是上亿级别。这也正是后面要引入卷积网络的原因。2.2 激活函数必须是非线性的否则网络再深也等于线性变换如果只有线性变换多层网络可以压缩成单层因为线性变换复合仍是线性。为了让网络能拟合非线性关系每个神经元后面要跟一个非线性激活函数。常见激活函数比较激活函数公式特点常见问题Sigmoid1/(1exp(-x))输出0到1适合概率型输出容易饱和梯度很小输出均值非零Tanh(exp(x)-exp(-x))/(exp(x)exp(-x))输出-1到1零均值饱和区梯度仍接近0ReLUmax(0, x)计算简单正区间梯度恒为1负数区间梯度为0可能导致“死神经元”现在CNN里ReLU及其变体用得最广原因很简单正区间梯度不衰减反向传播时不容易出现梯度消失而且计算成本低。但要注意ReLU不是没有缺点。如果学习率太高很多权重可能把输入推到负区间出现神经元死亡输出一直为0对应梯度永远为0。2.3 前向传播最后要接损失函数结果才能评估网络最后一层的输出要和标签对比。分类任务通常在最后接Softmax把输出转成概率分布再用交叉熵计算损失。回归任务会直接使用均方误差MSE。损失值是一个标量表示当前预测和真实标签的差距。判断模型好坏不能只看前向输出。我一般会先打印一个batch的预测概率确认概率分布在类别上有区分度再去看loss。如果loss一直是某个固定值不下降很可能是损失函数、标签编码或模型输出维度不匹配。比如分类网络输出类别数是10标签却是字符串就会在算loss时直接报错。3. 反向传播神经网络训练时最关键的“求导回传”3.1 反向传播是链式法则的高效实现训练神经网络的目的是让损失函数变小。损失函数是所有权重参数的复合函数想更新每一个权重需要知道该权重对损失的影响程度也就是偏导数。对深层网络逐层直接求导计算量非常大。反向传播则从输出层往回走把梯度逐层传播每一层的梯度可以复用后面的计算结果。链式法则是反向传播的数学基础。用简单的话说如果L依赖aa依赖zz依赖W那么∂L/∂W ∂L/∂a * ∂a/∂z * ∂z/∂W。反向传播在回传过程中会保存中间层的导数避免重复计算。3.2 梯度下降与学习率更新不是越大越好拿到梯度后参数更新通常用梯度下降W W - 学习率 * 梯度这里学习率是训练里最需要调的超参数。学习率太大参数会在最优点附近震荡loss容易发散学习率太小训练进度慢半天降不下去。实际训练时我建议先用一个中等学习率跑几个epoch观察loss曲线再看是增大还是减小。当前主流优化器如SGD with Momentum、Adam都是在这个基础上加惯性、自适应步长但核心思想没变。不要因为用了Adam就觉得学习率可以随便设。Adam对学习率更鲁棒但初始学习率仍然会影响最终效果。另外梯度下降有不同的batch模式full batch、mini-batch、online。实际训练里常用mini-batch一次算多个样本的平均梯度在稳定性和效率之间取平衡。batch size也会影响噪声batch太小梯度波动大batch太大一个epoch更新次数少需要配合学习率一起调整。3.3 深层网络最容易遇到梯度消失和梯度爆炸反向传播要经过很多层每乘一次小于1的数梯度会指数级减小最后前面层的梯度接近于0这就是梯度消失。反过来如果每层梯度大于1多层相乘会指数级增大梯度爆炸。两者都会让训练失败。这就是ResNet里shortcut connection出现的重要背景之一。它让梯度能“抄近路”直接回传到前面的层不经过卷积层里的连续非线性变换从而缓解梯度消失。但要注意ResNet不是唯一解决梯度问题的手段更好的初始化、BatchNorm、残差连接和合理的优化器选择都有帮助。3.4 想真正理解反向传播建议先在小网络上手动推导一遍我不建议只背公式。可以拿一个两层小网络输入一个样本手动做一次前向传播算loss然后按链式法则从输出层往输入层逐层算梯度。算完再和框架打印出来的梯度对比。流程固定的情况下数字对得上才算真正掌握。实际项目里不需要手动写反向传播框架会自动完成。但理解梯度流向后看到“loss不降”或“梯度为nan”时至少知道该看哪一层、是不是层数太深导致问题。排查梯度问题时可以按层打印梯度的均值和标准差观察梯度是不是从某一层开始骤降。4. 卷积神经网络为什么图像任务不用全连接网络4.1 全连接处理图像有两个硬伤前面提到全连接参数爆炸。除此之外全连接还忽略了图像的空间结构。一张图片里相邻像素相关性强远处的像素关联弱。全连接把每个像素当成独立特征不考虑局部关系还容易过拟合。卷积网络的思路是“局部连接权值共享”。一个卷积核只观察输入的一个小窗口比如3×3、5×5且同一个卷积核在图像不同位置重复使用。这样参数不会随图变大而线性爆炸模型也天然保留了局部空间关系。4.2 卷积核、步长、填充和输出尺寸卷积操作可以理解成用一个固定大小的窗口在输入上滑动窗口里的像素和卷积核权重逐个相乘再求和得到一个输出像素。滑动步长stride控制窗口每次移动多少格填充padding在输入周围补零用来控制输出尺寸避免边缘信息被丢弃。输出尺寸计算公式通常是输出尺寸 (输入尺寸 - 卷积核大小 2 * 填充) / 步长 1比如输入是224×224卷积核是3×3步长为1填充为1输出尺寸还是224×224。设置padding时一个常见规则是让输出尺寸尽量保持通常搭配padding (kernel_size - 1)//2。除了卷积核通道也是关键。输入图片如果是彩色图通道数为3。卷积层一次会用多个卷积核每个卷积核输出一个通道所以输出通道数往往就是卷积核数量。一个卷积核的参数是K×K×输入通道数因此卷积层参数量不是简单按输出图像尺寸算而是输出通道数 × K×K×输入通道数。4.3 池化层的作用压缩尺寸增强鲁棒性卷积之后通常接池化层比如最大池化、平均池化。池化在一个小窗口内取最大值或平均值目的是降低特征图尺寸扩大感受野同时保留主要特征。它没有需要学习的参数计算简单。池化不是必须的。现代网络更倾向于用带步长的卷积来降采样但初学阶段最大池化仍然是最好的抓手。看到特征图尺寸从224变成112再到56就知道网络在逐步把空间信息压缩、把通道语义信息提炼。感受野是理解CNN的一个关键概念。某层输出中的一个像素对应原图多大的区域叫感受野。底层卷积感受野小看到的是边缘高层卷积通过层层叠加感受野变大能看到物体局部甚至整体。这也是CNN能学出层次化特征的原因。4.4 从LeNet到VGGCNN结构反复在做“层更深、结构更规整”经典CNN结构沿革可以帮助理解ResNet的定位。LeNet-5是早期用于手写数字识别的卷积网络只有几层AlexNet把深度加到了多层使用ReLU和GPU训练VGG提出统一使用小卷积核比如3×3通过不断堆叠增加深度。每一代都在探索“把网络变深效果能不能更好”。但研究者很快发现单纯堆层不是一直有效。网络很深时训练误差反而可能上升这就是下一章要讲的退化问题。ResNet就是在VGG这类规整结构上加一条残差连接使深层网络训练变得可行。5. ResNet的核心恒等映射为什么能让网络变深5.1 网络变深后的“退化问题”不是过拟合直觉上网络越深表达能力越强效果应该越好。但实验显示当层数增加到一定程度训练集的loss可能不降反升。这不是过拟合因为训练集本身都拟合不好。深层网络优化困难甚至不如浅层网络容易逼近目标函数。退化问题的核心是“恒等映射难以学习”。假设一个浅层网络已经效果不错加了很多层之后新增层理想情况下应该学会恒等映射也就是输入是什么输出就是什么不破坏已有信息。但只靠卷积和非线性层去拟合恒等映射并不容易反向传播时也会因为层数太多导致梯度不稳定。5.2 残差块让网络至少不变得更差ResNet的做法是引入快捷连接也叫shortcut connection。残差块里输入x除了经过若干卷积层得到F(x)还直接通过一条捷径加到输出上输出 F(x) x这样一来新层不需要从零学一个复杂映射只需要学“输入和最终输出之间的残差”F(x)。如果残差任务接近0网络就可以退化成近似恒等映射。短期看这保证深层网络至少不比浅层网络差更关键的是反向传播时梯度可以直接从shortcut回传避免经过卷积层时被连续衰减。5.3 残差连接为什么能缓解梯度消失但别神化它用公式看输出 F(x) x求梯度时对x的梯度会多出一项1。这意味着即使F(x)内部梯度很小x仍然能获得来自后一层的梯度梯度不会完全消失。这是ResNet能训练到很深的原因之一。但不要神化残差连接。它解决的是网络结构导致的优化退化问题不代表它可以替代合理的初始化、学习率调整和数据归一化。我见过有人把ResNet当作万能药结果BatchNorm没加、学习率过大训练照样崩。ResNet是让深层网络“更容易训练”的结构设计不是保证一定收敛的开关。5.4 常见ResNet变体ResNet-18、34、50怎么选ResNet有很多层数版本。ResNet-18和ResNet-34结构比较接近使用基础残差块适合小数据集和快速实验ResNet-50使用Bottleneck残差块先降维再升维减少计算量适合大数据集、迁移学习和相对更深的特征提取。变体残差块类型典型使用场景资源占用ResNet-18BasicBlock小型数据集、学习实验低ResNet-34BasicBlock中等数据集、基础baseline中低ResNet-50BottleneckImageNet级别、迁移学习中高ResNet-101/152Bottleneck追求更高精度、资源充足高选择时不要只看精度。先确认自己GPU显存、训练时间和数据集规模。如果只是入门ResNet-18完全够用跑通后再换ResNet-50对比特征表示能力。使用预训练模型时也要注意不同ResNet版本最后的全连接层输出维度分类类别数不一致时需要替换。6. 实际落地从最小训练流程到问题排查6.1 用极简流程把理论落到代码里训练一个卷积网络流程通常是固定的读取数据、定义模型、定义损失函数与优化器、循环训练、输出指标。以PyTorch风格写的极简流程大致如下重点是理解流程不要依赖具体API版本# 伪代码/极简示例核心是流程 model ResNet18(num_classes10) loss_fn CrossEntropyLoss() optimizer SGD(model.parameters(), lr0.01, momentum0.9) for epoch in range(epochs): for images, labels in train_loader: outputs model(images) loss loss_fn(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step()这里loss.backward()就是反向传播。optimizer.step()根据梯度更新权重。看起来很短但实际训练时每一行都有潜在问题数据Loader有没有归一化、模型是否在train模式、BatchNorm层统计量更新是否正常、学习率是否合适。6.2 训练过程中如何判断网络是否正常不要只看最终准确率。训练时我习惯先看前几个batchloss是否在下降。输出概率是否有区分度。梯度是否出现nan或全部为0。验证集指标和训练集指标差距。如果loss在下降但验证集不涨可能是过拟合或数据分布问题如果loss根本不下降先怀疑模型结构、学习率和数据预处理如果loss直接变成nan先看学习率是否太大、输入是否有异常值、标签是否越界。6.3 常见问题排查顺序遇到训练不出效果我一般会按这个顺序排查顺序检查项具体操作1输入数据确认图片尺寸、归一化、标签编码2模型输出确认输出维度与类别数一致3损失函数确认分类用交叉熵、回归用MSE4学习率从0.01或0.001开始观察loss5梯度状态打印梯度的均值和范数确认无nan6网络结构先让小网络能拟合一个小batch注意很多“不收敛”问题根源不是模型不够强而是数据预处理、学习率和输出维度先出了问题。在这个排查过程中残差网络也不特殊。如果ResNet训练不收敛先确认shortcut的维度匹配是否正确尤其是跨层进行下采样、改变通道数的地方比如输入尺寸从56×56变成28×28时shortcut是否用了1×1卷积。6.4 使用预训练模型时最容易忽略的细节现在很多场景不用从零训练ResNet而是直接加载在ImageNet上预训练的权重做微调。这样做可以明显减少训练时间也能提升小数据集效果。但有几点要注意数据预处理要和预训练保持一致比如归一化使用的均值和标准差。最后的全连接层类别数要替换成自己的任务类别数。训练时如果只微调后面几层前面层可以先冻结如果数据量充足也可以全部微调。BatchNorm在训练模式和评估模式行为不同加载模型后一定要调用model.train()或model.eval()否则统计量不一致结果会突变。我建议就算用预训练模型也要先用一个batch验证前向和反向传播都能正常跑通再开始完整训练。很多框架报错都是因为shape不匹配或模式设置错误跟模型能力没关系。7. 给入门者的学习顺序和扩展方向7.1 先手推一个小网络再写代码我见过最有效的入门方式是这样的先拿一个2层全连接网络样本数取4个手动算前向传播再算反向传播更新一次权重和代码输出对比。这一步不需要GPU也不需要框架只需要纸笔和耐心。第一次算通之后再打开PyTorch或TensorFlow把同样流程用代码跑一遍成就感会高很多。这一步的核心不是执行计算而是建立“梯度从损失函数流向每一层参数”的直觉。之后不管看CNN、ResNet还是Transformer都会以这个为基础。7.2 用一个小型CNN跑MNIST或CIFAR-10建议先搭建一个简单CNN比如卷积池化全连接在MNIST上训练。MNIST图像小CPU也能跑几分钟就能看到loss下降。判断标准很简单训练集准确率能不能到99%测试集准确率能不能到97%以上。这个阶段不需要追求SOTA重点是熟悉训练循环、数据加载和网络结构修改。跑通之后换到CIFAR-10。图片是彩色图任务更复杂模型需要稍微深一点这时更容易体会到通道数、卷积核数量、padding对效果的影响。7.3 再复现ResNet但不能只复现结构当你能熟练写CNN后再去看ResNet论文和源码。先读BasicBlock的实现理解F(x)x里两个卷积的通道变化再看整个网络如何通过不同layer控制尺寸和通道。复现时不要直接拷贝预训练模型而是试着从零搭建一个ResNet-18在CIFAR-10上训练观察它是否比同深度的普通CNN更容易收敛。复现ResNet时特别容易踩到维度匹配问题。BasicBlock里第一个卷积不改变通道数第二个卷积也不变shortcut直接相加但当输入到下一个block时特征图尺寸和通道数变化shortcut就需要一个1×1卷积调整维度。很多初学者在这里报错其实不是原理不懂而是没有弄清shortcut的两种模式。可以打印每一层输出shape对比论文里的结构表。也可以做一组对比实验普通CNN堆到18层和ResNet-18比训练loss收敛曲线。这个对比会让你直观看到残差连接带来的差异比读十遍论文都有用。7.4 后面再扩展什么ResNet不是终点。理解ResNet后可以去了解ResNeXt、DenseNet、EfficientNet、BatchNorm原理以及为什么后来视觉领域更多人转向Vision Transformer。但每个进阶概念都建议用同一个套路先看它解决什么问题再复现再对比实验。当你看到视觉领域经常讨论Transformer时也不用觉得它和CNN完全割裂。Transformer放弃了卷积的局部归纳偏置通过自注意力捕获全局依赖但训练和使用思路仍然是前向传播、反向传播、损失函数、优化器这一套。学习过程中遇到报错或效果不理想先回到数据、结构、损失、学习率、梯度这五个维度排查。不要一上来就换最新模型也别觉得加残差就万事大吉。真正扎实的计算机视觉基础是能把一条训练链路从前向、反向、网络结构到优化策略完整串起来而不是记住某张结构图。
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门