☰
深度学习学习笔记:从反向传播到实验复现的完整方法论
2026/10/15 23:11:21 网站建设 项目流程

说实话,我一开始对“深度学习学习笔记”这件事是有些抵触的。总感觉笔记是学生时代才需要的东西,工作之后写代码、调模型、看论文就够了,记不记无所谓。直到某天晚上,我改了学习率忘记记录,第二天找不到对应的实验结果,同一套网络在相同数据上重跑了三小时,我才意识到:不写笔记的深度学习,就像在泥地里走路,脚印很多,但回头根本看不见自己是怎么走过来的。

这篇笔记不是教程,更像是我把自己踩过的坑、复盘过的实验、反复想不明白又终于想明白的概念,整理成了一套可以反复翻看的记录方法。它解决的核心问题只有一个:让深度学习的学习过程变得可追溯、可复现、可迭代。适合刚接触神经网络的初学者,也适合那些已经跑通了一些模型、但总觉得知识特别碎、学了就忘的人。

我自己的体会是,深度学习入门最大的门槛不是数学,而是“以为自己懂了”的错觉。笔记就是用来戳破这种错觉的:只要你能把一句话写清楚,它才算真的进了你的脑子。

1. 为什么说深度学习入门其实是一场“反直觉”练习

1.1 入门之前,先纠正三个错误预期

我见过很多人带着三种预期开始学深度学习,最后都学得比较痛苦,我自己也一样。

第一个错误预期是:深度学习等于调库。以为只要会用框架接口,按顺序调用卷积、池化、全连接,模型就能工作。实际跑起来才发现,真正的难点全在接口之外:张量的形状怎么流动、梯度为什么消失、数据为什么要归一化、验证集loss和训练集loss忽高忽低是什么意思。框架帮你省掉了求导的纸面计算,但没办法替你做决策。调库能让你快速“跑通一个demo”,却没法让你“解决一个新问题”。

第二个错误预期是:模型越复杂越好。早期我总觉得,效果不好就是网络不够深、参数不够多,于是把小模型换大模型,把3层换成15层,结果训练时间翻了几倍,效果反而更差了。后来才明白,模型复杂度要和数据量匹配。数据只有几千条,硬上一套上百层的网络,大概率就是过拟合。深度学习里的大部分问题,都不是“模型不够强”,而是“数据不够多”“约束不够准”。

第三个错误预期是:显卡决定一切。硬件当然重要,尤其是训练大模型的时候。但对于学习阶段来说,CPU、单卡、云服务器跑一个几十万参数的小网络完全够用。真正卡住你的往往不是算力,而是排查bug的时间。很多时候模型不收敛,不是因为配置不够,而是因为某一行代码的数值范围错了。

这三件事想通之后,学习路径就会清晰很多。也正因为如此,笔记的角色就变了:它不是抄写知识点的本子,而是你理解偏差的“照妖镜”。每当你觉得自己懂了某个概念,试着用三句话写清楚它解决什么问题、核心机制是什么、代码里哪个环节对应它。写不出来,就是还没懂。

1.2 我踩过的第一个大坑:从“看懂公式”到“跑通代码”

我第一个真正花时间去复现的模型,是最简单的线性回归。当时我觉得,就一个 y = w x + b,求个梯度,有什么难的?公式我看得清清楚楚,闭着眼都能推导。结果一写代码,训练两步loss就飞了。

查了很久,问题出在学习率。我设成 0.5,对于这个数据分布来说太大了,每步更新都越过最优点,loss在两边反复横跳,永远降不下来。我手动算了一步才发现,梯度是4,w 从1变成了 -1,损失函数反而更大了。把学习率改成0.01之后,loss才缓慢下降。

这件事给我的冲击特别大。它让我意识到,“看懂公式”和“让模型真下降”之间隔着一整条河。公式是静态的,代码是动态的;公式告诉你梯度方向正确,但没人告诉你步长该迈多大。真正的理解,并不是能推导出 对w的偏导等于什么,而是当loss曲线出现异常波动时,你能迅速判断出“哦,这可能是学习率过大”。

从那次之后,我的学习笔记就多了一个固定板块:现象记录。不只是写“我学了什么”,还写“我跑的时候发生了什么”。一个复现失败的记录,远比十句正确的解释有价值。这种习惯,帮我后面排查过拟合、梯度爆炸、数据泄漏的时候少走了很多弯路。

2. 学习路线的选择:资料、框架与节奏

2.1 资料怎么选才不浪费时间

现在深度学习的学习资料多到爆炸,课程、书籍、博客、源码、论文,随便一搜就是一大堆。我踩过最明显的坑,就是一上来花了大量时间读论文。论文是给有一定基础的人看的,里面充满了缩写、假设和实验细节,入门阶段读论文,效率极低,而且很容易产生挫败感。

我的建议是,入门阶段优先选择两类资料:带完整代码的实战项目,以及把原理讲得特别形象的教程视频。带代码的项目能让你直接看到“输入是什么、输出是什么、中间每一层的形状怎么变化”,这种从抽象到具体的映射非常关键。视频教程则适合建立第一印象,尤其是反向传播、卷积原理这类抽象概念,听过一个形象比喻之后,再看文字材料会顺很多。

书籍适合作为词典使用,而不是从头读到尾。可以先翻目录,把整本书的知识地图画出来,然后挑自己当前需要用到的章节去看。比如你对过拟合没概念,就去看正则化那一章;你对梯度爆炸头疼,就去看优化算法那一章。带着问题查书,比从头通读更容易坚持。

另外一个比较反直觉的选资料原则:不要只看好评率,要看“是不是有可运行的代码”。很多资料写得很好,但没有任何可复现代码,读者看完之后还是不知道第一步怎么下手。凡是资料里提到“原理如下”,但没有对应实验验证的,我都会在笔记里标记“待验证”。验证完了,才敢把它算作真知识。

2.2 框架选型:先用高级API,再亲手造一个

关于框架,我不太建议初学者一上来就陷入“框架之争”。无论选哪一款,核心概念是共通的:张量、自动求导、优化器、数据集接口。真正重要的是搞清楚框架替你做了什么,以及没替你做什么。

最推荐的学习路径是“先上层、再底层”。第一步,直接用高级接口搭建网络,训练一个最小模型,体验完整的训练流程。这是建立整体认知最快的方式。第二步,亲手写一个极简版的两层神经网络,不求效率,只求逻辑,用基础矩阵运算完成前向传播、手动实现反向传播里的梯度计算。这一步会逼着你去搞清楚张量的形状、梯度的流动、更新参数的时机。很多人觉得手写网络没有必要,但我个人觉得,那层“框架神秘感”被戳破之后,整个深度学习的世界会瞬间通透很多。

为了方便理解,我把两条路线的优缺点整理成了对照表:

路线优点缺点适合阶段
高级接口上手快、反馈感强、能快速跑通实验抽象层级高,出错不好排查初次接触深度学习
基础实现看清内部机制,理解张量运算和梯度代码量多、效率低、容易受挫已有基本概念后
读框架源码理解工程化设计、数据流的组织方式源码庞杂,不适合入门有一定项目经验
复现论文紧跟前沿,锻炼解决问题能力门槛高、实验周期长进阶阶段

绝大多数人会卡在“高级接口跑得太顺畅,底层原理一问三不知”。这不是智商问题,是学习顺序问题。先体验,再解剖,最后重建,这个顺序比一上来就去看框架底层源码舒服得多。

2.3 学习节奏:笔记、复现、实验记录的三段式

我自己的学习节奏,长期固定成三段式:概念笔记、代码复现、实验复盘。

概念笔记指的是,针对一个知识点,写清楚三件事:它解决什么问题、它怎么解决、它有什么代价。比如“Batch Normalization”,解决的问题是中间层分布漂移,做法是在每个batch内对激活值做归一化,代价是前向/反向过程多了几步计算,以及小batch时统计量不稳定。写完之后,这个知识点就不再是名词,而是逻辑链条。

代码复现不是把示例代码跑一遍就完事,而是要尝试改动关键参数,观察结果变化。改学习率、改batch size、改网络层数,每改一个变量,都算一次独立实验。复现的目标不是“跑通”,而是“建立因果直觉”:哪个旋钮影响哪个指标。

实验复盘是很多人忽略的一步。训练结束后,把loss曲线截图、关键指标、超参数配置、当时的代码版本都记录下来,再写一段话总结“发生了什么、为什么、下次怎么改”。这看起来麻烦,但在你三周后需要对比两个模型时,就会感谢自己当初的记录习惯。我的朋友A同学经常吐槽我“写记录的时间比训练还长”,但他的实验结果丢失了几次之后,也开始老老实实写了。实验记录不是给别人看的工作汇报,是给未来自己看的回溯线索。

工具方面,我建议用支持代码块和表格的笔记软件,配合Git管理实验代码。模型文件可以不同步,但代码、配置、训练日志一定要有版本记录。硬件资源有限的时候,这一点能让你的每次训练都不白跑。

3. 核心概念的直觉化理解

3.1 反向传播:用“流水线”理解梯度

反向传播是深度学习里最劝退的概念之一,主要是因为数学式子写起来很长。如果你只是记公式,很快就会忘记;如果你理解了那条信息流动的链子,会发现它一点也不复杂。

我的个人类比是:前向传播像一条流水线,原料是输入数据,经过每道工序变成输出;反向传播则是沿着流水线往回走,把最终误差“分配”给每一个环节,告诉每一道工序“你的参数到底该承担多少责任”。

这个责任的大小,就是梯度。计算梯度的核心就是链式法则:想求某一层的梯度,需要把后面所有层的局部梯度相乘。计算图就是帮你把这层关系可视化的工具。我在笔记里画过很多次计算图,后来发现,凡是能画出计算图的网络,反向传播就几乎没有理解障碍。画不出来,说明结构还没理顺。

有一个很值得手动推一遍的例子:两个变量相乘。假设网络只有一层,y = w x,损失是 (y - t)^2,其中t是目标值。前向计算得到 y,反向时先算 损失对 y 的梯度,也就是 2(y - t),再算 y 对 w 的梯度,也就是 x,两者相乘,就得到 损失对 w 的梯度。整个过程只有两次乘法和一次乘法,但这就是所有复杂网络里反向传播的原子操作。

很多开源框架会自动帮你完成这些梯度计算,这当然是好事。但如果你连梯度是怎么“沿着链传回去的”都没有概念,那么当你遇到梯度消失时,你会完全无从下手。梯度消失的本质,就是连续乘以大量小于1的数,值越乘越小,前面层的参数几乎收不到更新信号。理解到这一层,你才会明白为什么ReLU这个看起来特别简单的激活函数如此重要——它在正半轴上梯度恒为1,不会继续放大“衰减”效应。

3.2 损失函数:回归和分类背后的选择逻辑

很多入门项目会直接把均方误差用在所有任务上,结果分类任务做得一塌糊涂。这不是网络本身的问题,而是损失函数选错了。

回归任务通常用均方误差,因为它对大误差更敏感,能推动模型更快接近目标值。分类任务则几乎默认使用交叉熵。为什么分类不用均方误差?我当年反复读到一个朴素说法:因为交叉熵能更好地衡量“概率分布之间的差异”。当时没感觉,后来自己动手算了一组数字才算看懂。对于分类问题,模型输出经过Softmax之后是一组概率值,真实标签是one-hot向量。均方误差更新出来的梯度,在模型已经“比较自信”但恰好分错时,信号会很小,导致训练慢;交叉熵在这种情形下仍然能给出足够强的梯度,把错误答案尽快压下去。

理解损失函数的时候,笔记里最好附一张自己手算的对照表。我试过传一组很极端的预测概率,比如对某个样本,预测正确类的概率只有0.001,然后用两种损失分别算梯度,对比它们差了多少倍。那张表至今还在我笔记里,每次解释“为什么分类要用交叉熵”都会翻出来看。数字比口号有说服力得多。

另外,损失函数的值本身没有绝对意义。同一个模型,换一种损失函数,数值范围完全不同;哪怕同样是交叉熵,batch大小变了,单步loss也会变。所以不要只看loss的绝对值,要看它的变化趋势,要看它是否在持续下降,是否在验证集上同步下降。

3.3 优化器:学习率到底怎么调

优化器是我的“重灾区”,每次实验不收敛,八成是学习率的问题。学习率太大,参数会在最优点附近来回震荡,loss曲线像锯齿;学习率太小,loss下降特别缓慢,训练半天看起来像没动。

先说一下几个常见优化器的关系。最基础的随机梯度下降,就是沿着当前batch算出的梯度方向走一小步。但步子不够灵活的时候,容易卡在局部最优点或震荡。动量优化器给更新方向加了一个“惯性”,如果前后几次梯度方向一致,步子就会越走越大、越过小坑;如果方向不断改变,它也会自动减速,更稳定。自适应学习率的优化器,则会给不同参数不同的学习率,让稀疏特征和密集特征都能获得相对合理的更新幅度。这也是为什么它在很多任务上表现稳定、几乎不用怎么调学习率的原因。

但“自适应”不是万能药。我见过很多人把学习率设置为一个非常大的数,然后指望优化器自己救回来,结果是训练直接发散。一般经验是,如果不知道怎么设,可以先从一个小值开始,比如0.001,然后观察曲线。loss乱跳或者变成NaN,就往小调;loss下降太慢,就往大调。每次调整至少乘或者除以3,不要小幅微调,否则你试不出明显变化。

我记录过一张学习率实验表,调整同一个模型,唯一变化的是学习率,然后记录第10轮、第50轮、第100轮的loss值。这张表直观展示了一个东西:学习率对训练结果的影响,经常是数量级的差异。在笔记里保留类似实验记录,比背任何调参口诀都有用。

4. 实操过程里最容易翻车的三个环节

4.1 数据准备:花的时间永远值得

从我的经验看,数据准备占据了一个深度学习项目几乎一半的工作量。它也是最容易出“隐蔽bug”的环节。一个模型训练效果差,第一反应不应该是不停改网络结构,而是先回去检查数据。

数据预处理的常见步骤包括:清洗缺失值、统一格式、归一化或标准化、划分训练集和验证集。很多人会在归一化上犯错:直接用全量数据的均值方差做归一化,然后再划分数据集。这其实会造成轻微的信息泄漏,因为验证集的信息已经通过统计量进入了训练过程。正确做法是先划分,再用训练集部分计算均值方差,验证集和测试集都复用这套统计量来变换。

我踩过的另一个坑是数据顺序问题。有一次做图像分类,加载数据时忘记打乱顺序,导致前一半batch全部是同一类,后一半又是另一类。模型前几步把权重调向某一类,后几步又疯狂回调,loss曲线就像过山车,怎么都训不平。排查半天才发现,只是少了一次shuffle。后来我把“是否shuffle”“是否归一化”“数据划分比例”都写进实验配置里,问题就少了很多。

数据增强也是值得在笔记里单独开一节的。图像任务常用的增强包括随机裁剪、水平翻转、轻微旋转、颜色抖动。文本任务则可以做同义词替换、随机drop部分词。增强不是越多越好,过度的增强反而会让模型学到不真实的数据分布。我的习惯是每次增加一种增强方式,跑一轮对比实验,记录它对验证集指标的影响,而不是一次性堆上十种。

4.2 Debug技巧:NaN、梯度爆炸、过拟合

训练过程中最让人血压飙升的,就是看到loss变成NaN。我总结过几个高频原因:学习率太大、数据里有异常值或缺失值、损失函数里出现对0取对数、除零运算、模型输出值过大导致Softmax溢出。排查顺序建议是:先看输入数据,再看学习率,最后看损失函数里的数值操作。很多时候,一条clip或者对输入做标准化就能解决问题。

梯度爆炸和梯度消失是另一个系列问题。梯度爆炸容易发生在深度网络、recurrent结构以及损失值很大的时候。最常规的做法是梯度裁剪,也就是设定一个阈值,梯度的模长超过阈值就等比缩放。这个操作非常简单,但能解决相当大一部分训练不稳定的问题。梯度消失则更隐蔽,表现为浅层参数几乎不更新,loss下降一段后就停滞。解决思路一般是换激活函数、加Batch Normalization、或者调整网络结构增加跳跃连接。

过拟合可能是初学者最容易遇到、也最容易误判的问题。判断过拟合的标志,是训练集loss持续下降,但验证集loss先降后升,形成典型的“开口曲线”。这时候不要慌,先确认是不是验证集分布和训练集不一致,排除数据问题后再做正则化处理。常用手段有增加数据量、数据增强、降低模型复杂度、加权重衰减、加Dropout。我自己的一个习惯是,把“每轮训练集loss”“每轮验证集loss”打印在同一张图里,这样过拟合出现的第一时间就能看到,而不是等训练结束再去算。

4.3 实验管理:不记录等于白跑

先讲一个我真实的翻车经历。某次图像识别实验,我调整了网络结构、学习率、数据增强三种因素,因为偷懒没有分步记录,直接一起改了。跑出很好结果之后,我根本不知道是哪个改动起了作用,想复现也只能重来。更尴尬的是,我连当时用的是哪份代码都没法确定。

从那次之后,我给自己立了一条规矩:每一次实验只有一个变量发生变化。如果要调整三个因素,就拆成三组实验,每次只动一个。虽然慢,但结果可信。实验记录也不用写得复杂,但至少要包含:日期、代码版本、数据集版本、模型结构描述、超参数列表、关键指标、loss曲线保存路径、备注现象。我常用的记录模板就是一张表,每次实验填一行,加上一份简短的文字总结。

我还会在训练结束之后,强制自己写一小段“实验复盘”。不用长篇大论,就写三句话:这轮实验验证了什么?比上一轮好了还是差了?下次该怎么改?这三个问题看似简单,但只要坚持写上一段时间,你就会发现自己对模型行为的直觉飞速提升。很多人训练到后面,会陷入“盲调参数”的焦虑中,很大一部分原因就是没有把每次实验当成一次有假设的验证。

5. 常见问题排查速查表与避坑清单

学习深度学习的前三个月,我经常在同一批问题上反复犯错。后来我把这些问题整理成了一张排查速查表,放在笔记最前面。每当训练异常,我先对照表格定位方向,再深入查细节。表格不求覆盖所有情况,但能解决80%的入门期问题。

问题现象可能原因快速排查思路
loss变成NaN学习率过大、数据有异常值、除零或log0先降学习率,检查数据和损失函数数值
loss下降很慢学习率过小、数据未归一化增大学习率,检查输入数据范围
loss剧烈震荡学习率偏大、batch size过小降低学习率,适当增大batch size
训练集loss持续下降,验证集loss反弹过拟合增加数据增强、加正则化、提前停止
训练集和验证集loss都不下降数据处理错误、特征没有预测力检查数据标签,检查预处理是否合理
浅层参数几乎不更新梯度消失换激活函数、加归一化层、检查网络深度
同一份代码,两次结果不同随机种子、GPU非确定性操作固定随机种子,关闭部分确定性开关
不同任务用了同一个预处理方法数据分布不一致按任务单独设计预处理流程
验证集指标好,线上效果差训练集和线上数据分布不一致检查数据来源、特征分布,重构验证集

这张表里,我特别想强调“随机性”那条。深度学习中,同一段代码在不同硬件、不同库版本上结果都可能不同。为了实验结果可复现,我会在代码开头固定随机种子,同时把框架配置为确定性模式。虽然多花一点时间,但换来的是实验之间可以公平对比。

还有两个环境层面的坑比较容易忽略。一个是框架版本不一致,旧版本项目换到新环境经常报错;另一个是依赖库的隐性版本冲突。我的建议是,每个项目单独建一个虚拟环境,并把依赖版本号写进配置文件里。这样你在半年后重新复现自己的实验时,不需要靠回忆来装环境。

6. 一份可以直接抄走的深度学习笔记模板

说了这么多,最后分享一套我一直在用的笔记模板。它分成四个部分:概念卡片、实验记录、问题清单、阶段性小结。你可以直接复制到自己的笔记软件里,按实际情况调整。

# 概念卡片 ## 概念名称 - 一句话定义: - 解决什么问题: - 核心机制: - 代价/缺点: - 我的生活化类比: - 代码对应环节: # 实验记录 ## 实验编号:X - 日期: - 目标/假设: - 数据集版本: - 代码版本: - 模型结构: - 核心超参数:(学习率、batch size、训练轮数...) - 训练集指标: - 验证集指标: - 现象描述:(loss曲线形态、异常点...) - 结论与下一步: # 问题清单 - 问题1:现象 / 排查过程 / 原因 / 解决方案 - 问题2:.... # 阶段性小结 - 本周我真正搞懂了哪些概念? - 哪些概念还说不清楚? - 目前最卡我的问题是什么?

这套模板的关键,不是让你把它填满,而是逼你在每个实验前先写下“目标和假设”。没有假设就去跑实验,跑完也很难有收获;带着假设去训练,就算结果不如意,你也能知道否定了什么。

我个人感受最深的一件事是:深度学习学习中,智商不是决定性因素,记录习惯才是。一个愿意把每个失败都写下来的人,进步速度远超一个“看起来很聪明但不做笔记”的人。因为前者每一次失败都在为下一次成功铺路,后者则每次都从零开始。

最后再说一个我自己的小习惯:每周日会翻一遍本周笔记,把那些“当时觉得懂了、现在又有点模糊”的概念重新写一遍。这个过程很慢,但特别有效。如果你现在正处在“视频看了一堆、代码跑了不少、却还是觉得说不清楚”的阶段,不妨就从一张最简单的概念卡片开始,写起来,一切都会慢慢顺的。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询