拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

神经网络与深度学习课后习题全解析:从BP推导到CNN计算

神经网络与深度学习课后习题全解析:从BP推导到CNN计算

1. 这门课的课后习题,到底在考什么

1.1 先搞懂教材与内容边界

如果你正在对着“神经网络与深度学习”这门课的课后习题发愁,大概率手头用的是邱锡鹏老师的《神经网络与深度学习》——圈内俗称“蒲公英书”,因为封面是一朵蒲公英。这本书在很多高校的研究生课和本科生高年级课上都是主教材,北交大、北邮、西电等学校都拿它当核心参考。它的习题设计很有意思,不光是让你算几个数、写几个公式,而是真的在逼你把前馈神经网络、卷积神经网络、循环神经网络、注意力机制这些内容串成一张网。

我个人的体会是,很多人拿到课后习题第一反应是“这题我怎么没见过”——其实不是没见过,是没把书里的知识点转化成解题工具。比如书中第二章“机器学习概述”几乎不直接出现在试卷上,但几乎所有计算题、推导题都以它为底层逻辑:损失函数怎么设计、泛化误差怎么拆解、过拟合怎么缓解。所以复习课后习题之前,我建议你先做一个动作:把目录抄一遍,然后用自己的话在每一章标题旁边写三行——这章解决什么问题、核心数学工具是什么、能出哪类题。这样做完,你对整本书的“考点地图”就有数了。

另外要说明的是,不同学校的课后作业和期末考试风格差异很大。有的学校重推导,比如北交大的深度学习期末试题里,经常直接让你从零推导BP算法的梯度更新公式;有的学校重应用,比如华为杯数学建模竞赛的A题会给你一个通用神经网络处理器的调度场景,让你在真实硬件约束下做任务调度;还有的学校重代码实现,比如“用MATLAB实现BP神经网络拟合曲线”这种经典实验题。所以这篇博文我不会只盯着某一类题,而是把常见的几大题型全部拆开来讲。

1.2 习题类型拆解与应对策略

我整理了一下,这门课的课后习题其实就五类,摸清类型再动手,效率完全不一样。

第一类是概念辨析题,比如“前馈神经网络和反馈神经网络的区别”“CNN为什么不用全连接前馈网络做图像分类”。这类题看起来简单,但往往需要你答出本质:前馈网络没有环状结构,信号单向传播;CNN通过局部连接和权值共享大幅减少参数量,同时保留了空间结构信息——这正好呼应了“图像处理为啥用CNN不用前馈神经网络”这个问题。第二类是数学推导题,集中在反向传播、梯度下降、Softmax交叉熵的梯度推导。第三类是计算题,比如给定一个具体网络结构让你算参数量、算某一层的输出尺寸、算感受野。第四类是编程实现题,用MATLAB或Python实现某个网络并在数据集上训练。第五类是方案设计题,给你一个场景让你设计方案,比如“基于深度学习的人脸图像情感识别,选ViT还是EfficientNetV2”。

应对策略上,我的建议是“先推导、再计算、后编程、最后设计”。因为编程题往往建立在推导和计算之上,比如你写BP算法时,如果不知道每一层的梯度公式,代码就是空中楼阁。方案设计题则是综合能力的体现,需要你平时就注意积累不同模型的适用场景。

2. 理论推导类习题:从BP到交叉熵的完整拆解

2.1 反向传播算法的推导套路

BP算法几乎是每份试卷的必考题,题型通常是“给定一个三层前馈神经网络,推导各层权重梯度的表达式”。很多同学一看到这种题就慌,其实它有一个非常固定的推导套路,你只要掌握了“链式法则+局部梯度”这套思路,三层也好、十层也好,本质都是一样的。

我们以最经典的MSE损失函数为例。假设网络结构是输入层n个神经元、隐藏层m个神经元(激活函数为sigmoid)、输出层k个神经元(激活函数为sigmoid)。对于单个训练样本,损失函数是L等于二分之一倍的预测值与真实值差的平方和。反向传播的第一步是计算输出层每个神经元的误差信号,也就是损失对输出层净输入的偏导。这个值等于损失对输出的偏导乘以激活函数的导数。损失对输出的偏导就是预测值减真实值;sigmoid的导数等于sigmoid值乘以1减sigmoid值。第二步,利用输出层的误差信号,可以更新输出层的权重:权重的梯度等于误差信号乘以隐藏层输出。第三步,将误差信号通过输出层权重反向传播到隐藏层,得到隐藏层的误差信号,再更新隐藏层权重。

我在实际推导中踩过一个坑:符号混乱。一会儿用w表示输入层到隐藏层的权重,一会儿用v表示隐藏层到输出层的权重,到了梯度公式里下标又写错。后来我总结了一个办法——画图。把网络结构图画出来,每个神经元旁边标上它的净输入、激活输出,每条边上标上权重符号。这样推导的时候,每一步你都知道自己算的是哪条边的梯度,绝对不会乱。这个习惯帮我避免了很多低级错误,强烈推荐给你。

2.2 Softmax交叉熵的梯度为何是“预测减真实”

如果你问深度学习面试里最常考的推导题是哪道,Softmax交叉熵的梯度推导绝对名列前茅。它的结论极其简洁——损失对Softmax输入logits的梯度,就等于预测概率减去one-hot真实标签。但很多教材只是把这个结论直接告诉你,不给你推导过程,导致很多人知其然不知其所以然。

推导的关键在于分情况讨论。Softmax函数把logits变成概率,交叉熵损失是负的真实标签log概率。当对第j个logit求梯度时,如果j正好是真实类别对应的那个位置,那么Softmax的求导结果是p_j乘以1减p_j,其中p_j是第j类的预测概率;如果j不是真实类别,结果是负的p_j乘以p_i。把两种情况分别代入交叉熵的链式法则,你会发现最终梯度统一写成p减y的向量形式,y是one-hot标签。这个推导过程是很多期末试卷的压轴题,建议你亲手推一遍,不要只看书上的结论。

关于这个推导,我还有一个实用的记忆技巧。从信息论角度看,交叉熵衡量的是预测分布与真实分布的差异,梯度为p减y意味着:如果模型对真实类别的预测概率p小于1,梯度就是正的,更新时会增大对应权重,让概率更接近1;反之亦然。这是一种自校正机制,理解了它,你写代码时就知道为什么Softmax层之后往往接一个交叉熵损失,而不用手动实现Softmax的导数。

2.3 推导题的常见变形与解题模板

推导题不只是BP和Softmax,还有几个常见的变形版本。比如“推导带动量项的梯度下降更新规则”“推导L2正则化对梯度的影响”“推导Dropout在训练和测试阶段的缩放关系”。这些题目本质上都是在基础推导上加一个扰动项,解题思路是一样的。

以L2正则化为例,损失函数变成原始损失加二分之λ乘以权重平方和,那么梯度就变成原始梯度加λ乘以权重。这意味着每次更新时,权重会先被乘以一个小于1的因子,再减去学习率乘以原始梯度,从而实现对权重的衰减。这种“权重衰减”和L2正则化的等价关系,在推导题里经常被拿出来考。

我做了一个推导题的通用解题模板,分享给你:第一步,写出网络前向传播的每一层计算公式;第二步,写出损失函数的具体表达式;第三步,从输出层开始,逐步用链式法则计算每一层权重和偏置的梯度;第四步,如果是问更新规则,就把梯度代入优化器的更新公式;第五步,务必检查梯度的维度是否和对应权重矩阵一致——维度不匹配是推导错误最明显的信号。这个模板我每次做题都用,基本没有失手过。

3. 计算类习题:参数计算、感受野与输出尺寸

3.1 参数量计算的黄金公式

计算题里最常出现的,就是“给定一个卷积神经网络结构,计算总参数量”。这类题看似复杂,其实只需要记住一个黄金公式:某一层(卷积层或全连接层)的参数量等于权重大小加上偏置大小。卷积层的权重大小是输出通道数乘以输入通道数乘以卷积核高度乘以卷积核宽度,偏置大小就是输出通道数;全连接层的权重大小是输入维度乘以输出维度,偏置大小是输出维度。

举个例子,经典LeNet-5的第一个卷积层,输入是1通道的32×32图像,使用6个5×5卷积核,步长为1,无填充。这一层的参数量就是6乘以1乘以5乘以5再加上6,等于156个参数。这个数值看起来很小,但如果你连到下一个卷积层,输入变成6通道,使用的卷积核仍然是5×5,输出16通道,那么这一层的参数量就是16乘以6乘以5乘以5再加上16,等于2416个参数。很多同学算错是因为忘了输入通道数是上一层的输出通道数,建议每算一层都先确认输入通道数。

3.2 输出尺寸与感受野的快速口算

除了参数量,输出尺寸和感受野也是高频考点。卷积层输出尺寸的计算公式是:输出尺寸等于输入尺寸加2倍填充减卷积核尺寸,再除以步长,最后加1。如果除不尽,很多框架默认向下取整。池化层的计算方式类似,只是没有填充这个参数。

感受野的计算稍微复杂一点,但它有一个递推公式:从最后一层往前推,第i层的感受野等于第i+1层的感受野乘以第i层的步长,再加上第i层的卷积核尺寸减1。还是用LeNet-5举例,第一个卷积层是5×5卷积核,步长1,那么第一个卷积层的输出特征图上每个点的感受野就是5×5。再经过一个2×2的最大池化,步长2,第二个卷积层的5×5卷积就会在原始图像上对应更大的感受野。具体数值你可以自己代入公式算一遍,算完比背十遍都有用。

我推荐一个口算技巧:先用“输出尺寸公式”算每一层的特征图大小,再用“感受野递推公式”从后往前推。这两套公式配合起来,几乎所有关于“这个网络为什么这么设计”的问题都能回答。比如VGG网络为什么全部用3×3卷积?因为两个3×3卷积堆叠,感受野等于5×5,但参数量只有5×5卷积的18/25,还多了一层非线性变换。

3.3 计算题的实战演练:设计一个迷你CNN

为了让你更直观地看到计算题怎么考,我设计了一个迷你CNN的例子。假设输入图像是32×32×3,第一层用8个3×3卷积核,步长1,填充1,然后是2×2最大池化,步长2。第二层用16个3×3卷积核,步长1,填充1,再经过一个2×2最大池化。最后接一个全连接层,输出10类。

先算第一层输出尺寸:32加2减3除以1再加1,等于32,通道数变为8。池化后变成16×16×8。第二层输出尺寸仍然是16×16,通道数变为16,池化后变成8×8×16。全连接层的输入维度是8乘以8乘以16等于1024,输出维度是10。参数量方面,第一层卷积是8乘以3乘以3乘以3加8等于224,第二层卷积是16乘以3乘以3乘以8加16等于1168,全连接是1024乘以10加10等于10250。这个网络的总参数量约等于1.2万。

考试的时候,这类题还会问你“如果换成5×5卷积核,参数量变化多少”,或者“如果把填充改为0,输出尺寸变成多少”。我的建议是,平时把每一步计算都写完整,不要心算,因为最后的分数是按步骤给的。

4. 编程实现类习题:MATLAB实现BP神经网络拟合曲线

4.1 为什么很多学校选MATLAB做深度学习实验

虽然工业界基本都用Python,但很多高校的“神经网络与深度学习”课程实验,仍然在用MATLAB。原因有三:一是MATLAB的矩阵运算非常直观,和数学公式几乎一一对应,非常适合用来验证反向传播算法;二是神经网络工具箱自带了很多内置函数,可以快速搭建网络;三是MATLAB在信号处理、控制等传统工科领域有深厚积累,很多非计算机专业的学生更熟悉它。所以当你看到“BP神经网络拟合曲线”这种题时,别急着抱怨“怎么不是Python”,先理解——这道题的核心不是语言,而是你能否用代码复现BP算法的训练过程。

4.2 一个完整可运行的MATLAB拟合示例

我直接给你一个可以跑通的MATLAB示例。这个例子用BP神经网络去拟合一个带噪声的正弦函数,这是最经典的拟合实验。

% 生成训练数据 x = linspace(0, 2*pi, 100)'; y = sin(x) + 0.1 * randn(size(x)); % 创建BP神经网络:输入层1个节点,隐藏层10个节点,输出层1个节点 net = feedforwardnet(10, 'trainlm'); net.layers{1}.transferFcn = 'tansig'; net.layers{2}.transferFcn = 'purelin'; net.trainParam.epochs = 1000; net.trainParam.goal = 1e-5; % 训练网络 net = train(net, x', y'); % 测试拟合效果 x_test = linspace(0, 2*pi, 200)'; y_test = net(x_test'); % 可视化 figure; plot(x, y, 'bo'); hold on; plot(x_test, y_test, 'r-', 'LineWidth', 2); legend('带噪声数据', 'BP拟合曲线');

这段代码的核心是feedforwardnet(10),它创建一个带10个隐藏层神经元的单隐层前馈网络。隐藏层用tansig(双曲正切S型函数),输出层用purelin(线性函数)。为什么输出层用线性?因为这是一个回归拟合问题,输出范围是整个实数域,如果输出层也用S型函数,会把输出限制在-1到1之间,拟合效果会很差。这个细节很多实验报告里不会写,但面试时会问。

4.3 隐藏层神经元个数和学习率怎么定

隐藏层神经元个数是BP神经网络实验里最玄学的问题。选少了,网络拟合能力不够,欠拟合;选多了,容易过拟合,训练时间也变长。我的经验是:先用经验公式估算一个初始值,再通过实验调整。常用的经验公式是隐藏层神经元个数等于输入层加输出层个数的平方根,再加一个1到10之间的常数。比如这个例子输入1个节点、输出1个节点,那么平方根是根号2约等于1.414,加5的话大约是6到7个。我实际测试下来,10个节点在这个数据量下效果不错,如果你用5个节点,拟合曲线会明显更平滑但有偏差;15个节点则可能开始出现小幅震荡。

学习率的选择也有讲究。MATLAB的trainlm用的是Levenberg-Marquardt优化算法,它自带自适应调整机制,对学习率不敏感。但如果你自己手写BP算法,学习率一般从0.01到0.1开始试。我建议你做一个简单的实验:固定其他参数,分别用0.001、0.01、0.1、0.5的学习率训练网络,画出误差下降曲线。你会发现学习率太小收敛极慢,学习率太大误差曲线剧烈震荡甚至发散。这个实验本身也是这门课很爱考的“实验报告加分项”。

4.4 手写BP算法的MATLAB实现

如果你想让实验报告更出彩,我强烈建议你手写一个简单的BP算法,不要完全依赖工具箱。原因有二:一是很多老师会抽查代码,如果连梯度怎么算都说不清,分数会受影响;二是手写一遍之后,你对前面推导题的理解会质变。我给出一个不含工具箱、纯手写的核心代码片段,基于批量梯度下降训练一个单隐层网络,用于拟合同样的正弦函数。

% 手写BP神经网络拟合正弦曲线 x = linspace(0, 2*pi, 100)'; y = sin(x) + 0.1 * randn(size(x)); % 网络参数 n_input = 1; n_hidden = 10; n_output = 1; lr = 0.05; epochs = 5000; % 初始化权重(小随机数) W1 = randn(n_hidden, n_input) * 0.5; b1 = zeros(n_hidden, 1); W2 = randn(n_output, n_hidden) * 0.5; b2 = zeros(n_output, 1); % 训练 for epoch = 1:epochs % 前向传播 z1 = W1 * x' + b1; % 10x100 a1 = tanh(z1); z2 = W2 * a1 + b2; % 1x100 a2 = z2; % 输出层无激活 % 反向传播 delta2 = a2 - y'; % 1x100 delta1 = (W2' * delta2) .* (1 - a1.^2); % 10x100 % 梯度下降更新 W2 = W2 - lr * (delta2 * a1') / length(x); b2 = b2 - lr * mean(delta2, 2); W1 = W1 - lr * (delta1 * x) / length(x); b1 = b1 - lr * mean(delta1, 2); end

这段代码里有一个很容易踩的坑:delta1那一步的(1 - a1.^2)是tanh的导数,如果你隐藏层换了sigmoid激活函数,这里必须换成a1 .* (1 - a1)。这两种激活函数的导数形式完全不同,忘记换是手写BP最常犯的错误之一。另外注意梯度的归一化,我用了/ length(x)做了平均,否则学习率稍微大一点就会发散。

4.5 实验报告里的数据可视化与结果分析

写完代码只是第一步,实验报告的分数往往取决于你的数据分析。我建议你的报告至少包含三张图:第一张是数据拟合效果图,带噪声的散点和拟合曲线叠加在一起;第二张是训练过程中的误差下降曲线,横轴是迭代次数,纵轴是均方误差;第三张是不同隐藏层神经元个数下的拟合效果对比图。这三张图往报告里一放,老师一眼就能看出你做了系统的实验分析。

还可以加一个定量指标:在测试集上计算均方根误差RMSE。比如拟合正弦函数这个例子,一个训练良好的BP网络,RMSE大约在0.1左右——这个量级和噪声标准差相当,说明模型已经捕获了数据中的主要规律,剩下的是不可约的噪声。如果你的RMSE明显大于0.1,就要检查网络结构、学习率或者数据预处理是否出了问题。我在批改实验报告时发现,很多同学只贴代码和结果图,完全不做定量分析,这其实错过了展示自己的好机会。

5. 卷积神经网络与经典模型:高频考点梳理

5.1 CNN结构题的核心考点与答题框架

卷积神经网络的题目在各类考试中占比越来越大,尤其爱考“给定结构图,回答问题”这种形式。常见的问法包括:这个网络一共有多少层可训练参数层?每一层的输出特征图尺寸是多少?感受野到第几层覆盖了输入图像的大部分区域?为什么最后一层用Softmax而不是Sigmoid?

面对这些问题,我给你一个答题框架,保证条理清晰。第一段,说清楚网络整体由哪几个部分组成——通常包括输入层、若干卷积层、若干池化层、若干全连接层和输出层。第二段,逐一分析每一层:卷积层的卷积核大小、步长、填充方式、输出通道数;池化层的类型、核大小、步长。第三段,用公式计算每一层的输出尺寸和参数量。第四段,分析这个网络的设计动机,比如“为什么要在这里加池化”“为什么最后接Dropout”。这个框架的优点是逻辑完整,不会漏掉得分点。答题时多写设计理由,不要只堆数字。

5.2 经典CNN模型对比:LeNet、AlexNet、VGG、ResNet

这一节几乎是必考内容,我建议你把经典模型的参数背熟,同时理解为什么每个模型是那个样子。LeNet-5是最早的卷积网络之一,适合手写数字识别,结构是卷积-池化-卷积-池化-全连接。AlexNet在ImageNet上取得了突破性进展,它用了ReLU激活函数、Dropout和局部响应归一化,并且用两块GPU并行训练。VGG的核心思想是用小卷积核堆叠获得大感受野,结构规整,便于工程实现。ResNet引入了残差连接,解决了深层网络难以训练的问题,让我们可以把网络做到一百多层以上。

考试常见的对比题是“VGG和ResNet的异同”“为什么ResNet能训练得这么深”。我提供一个回答思路:ResNet的残差连接使得每一层只需学习输入和输出之间的残差,如果这个残差是零,网络就能退化为恒等映射,从而保证深层网络至少不会比浅层网络更差。这种设计解决了梯度消失问题,因为残差块的梯度可以通过恒等捷径直接回传。如果能把这个原理用数学公式表达出来——输出等于映射部分加输入,那么梯度就是映射的梯度加1——回答就非常完整了。

5.3 ViT与EfficientNetV2:新模型的考点趋势

最近几年的考试和作业,越来越多地出现新模型的名字,比如“人脸图像情感识别,选ViT还是EfficientNetV2”这种开放性问题。很多同学看到这种题就懵,因为教材里根本没有。其实这种题的考点不是让你复现模型,而是考察你对模型特性的理解。

ViT,即Vision Transformer,把图像切分成patch,然后用Transformer的注意力机制建模patch之间的关系。它的优势是可以建模长距离依赖,不局限于局部感受野;劣势是数据量小时很难训练好,需要大规模预训练。EfficientNetV2是谷歌提出的一种高效卷积网络,在网络的宽度、深度、分辨率三个维度上做复合缩放,同时引入了一些训练加速技巧,如渐进式学习。它的优势是计算效率高,适合数据量中等、对推理速度有要求的场景。

如果让我选人脸情感识别,我会倾向于EfficientNetV2。原因包括:人脸情感数据集通常不算太大,EfficientNetV2不需要海量预训练数据;人脸情感识别对局部细节敏感,卷积网络的归纳偏置有帮助;部署时资源有限时更可行。但如果数据量非常大、且有充足算力做预训练,ViT也能拿到更好效果。关键是答题时不要只给结论,要把两边的权衡逻辑说清楚。

6. 期末冲刺与实验课设避坑指南

6.1 高频易错点自查清单

到了期末复习阶段,我把这几年见过的高频易错点整理成一个自查清单,每一届学生都在这些地方翻过车。第一个易错点是sigmoid和tanh导数公式混淆,sigmoid导数是a乘以1减a,tanh导数是1减a的平方。第二个易错点是softmax交叉熵的梯度推导时忘记分情况讨论,导致公式写错。第三个易错点是卷积输出尺寸计算时忘记加填充再减卷积核。第四个易错点是参数量的输入通道数写错,用了上一层的输出尺寸而不是通道数。第五个易错点是Dropout训练时要除以保留概率,测试时不用。

我个人还想加一条:学习率初始值随便设。很多人直接设0.1、0.01就觉得可以,结果模型不收敛就怀疑代码有bug,其实是学习率问题。我的建议是先用很小的学习率如0.001跑100轮,观察损失曲线,如果下降缓慢,再逐步增大;如果震荡,就减小。这种“从小开始、逐步增大”的方式比一上来就猜一个值靠谱得多。

6.2 课程设计类作业的题目选择与时间规划

如果你这门课还有一个课程设计大作业,比如“基于深度学习的图像分类系统”“基于MATLAB的BP神经网络预测股市”,选题和规划就非常关键。我的建议是,选题一定要小、要具体。比如“用ResNet-18做猫狗分类”就比“深度学习图像识别系统”好得多。因为题目越小,你能做深做透,写报告时也更容易体现工作量。

时间规划上,我建议用四段式安排。第一周做数据准备和baseline——找数据集、做预处理、跑通一个最简单的模型。第二周做核心改进——换个网络结构、调参、做数据增强。第三周做对比实验和可视化——把不同模型、不同参数的效果对比出来,画出损失曲线和准确率曲线。第四周写报告和答辩PPT。我在实际带课设时发现,凡是按照这个节奏来的同学,最后都能拿出一份像样的报告;凡是前松后紧、最后两天一夜爆肝的,报告质量普遍不行。

6.3 如何在考场/答辩现场冷静应对

最后一个建议是关于心态和临场发挥的。理论题和计算题其实都可以“演算+检查”两步走:先快速把公式写在草稿纸上,再代入数值计算,最后把结果代入原式验证。方案设计题则要记住“先框架、后细节、给理由”的原则——先写整体架构,再展开每一部分,给你的每个选择都配上一句理由,哪怕这个理由是“因为数据量小,所以选了层数较少的模型”,也比只写一个名字要好得多。

答辩时如果被老师问到了不会的问题,不要慌。我见过最多的提问是:为什么选这个激活函数?为什么这个学习率能work?你这个模型训练了多久?所以你只要在平时做实验时多留个心眼,把这些“为什么”记在小本子上,答辩基本稳了。如果你真的没做过某个实验,就诚实说“这个是我参考论文设定的,我没有单独实验验证”,比硬编一个答案靠谱得多。

返回列表