前段时间我在折腾一个基于大模型API的问答小工具,每天都会在文档里看到"前向传播""梯度下降""反向传播"这几个词,可真有人问我它们是怎么协同工作、把一个随机初始化的模型逐步训练成能回答问题的东西,我基本只能沉默。后来一位朋友顺嘴问了句:"如果模型输出错得离谱,你能通过改参数让它变好一点吗?"我当场噎住,脑子里翻来翻去只有"重新喂数据""换个模型版本"这种接口层面的回答。那一刻我才意识到,我对模型训练原理的认知基本等于零。
"重练AI小号"就是从那天开始的。我给小号定的第一课,就是最基础的三件套:前向传播、梯度下降、反向传播。这篇是第一课的重修日记,适合那些和我一样,能调大模型接口、能跑通Demo,但一被问到底层原理就心虚的小白读者。我会用手推公式、代码验证和生活类比三件工具,把每个概念尽量讲到"不仅能说出名字,还能解释它到底干了什么"的程度。
1. 从"会用"到"想懂":这轮重修我给自己定的规矩
1.1 一个让我脸红的瞬间,暴露我其实不懂训练链路
那次对话发生在一个很普通的周五下午。我在演示自己做的问答工具,流程看起来很顺利:用户输入问题,接口返回答案,我做一些后处理,展示在页面上。朋友问了一句"如果这个答案错得很离谱,你怎么让它变好",我下意识说"多给点上下文提示词试试"。这个回答本身没有错,但它解决的是"怎么让模型更好地理解指令",而不是"怎么改变模型本身的参数"。换句话说,我根本不懂训练。
当天晚上我去翻之前收藏过的一篇讲模型训练的文章,里面反复出现前向传播、损失函数、梯度下降、反向传播。我发现自己能顺着文字念下来,但每句话之间是什么逻辑关系,完全串不起来。那种感觉就像看了一部电影的片段剪辑,每一段都认识,却拼不出完整情节。第二天我决定,干脆把那些一知半解的知识全部放下,从神经网络最原始的计算开始重修一遍。
1.2 重修目标:不背公式,但要把"一次训练"讲清楚
我给自己定了三个很具体的目标。第一,能用手推的方式解释一次训练迭代到底做了什么:数据进来,经过哪些计算,损失怎么算出来,梯度怎么求出来,参数怎么更新。第二,能看懂框架报错信息背后的数学含义,而不是看到"Shape mismatch"就只会复制粘贴到搜索引擎。第三,理解三个概念分工——前向传播负责把输入变成输出,损失函数负责给输出打分,梯度下降加反向传播负责把误差变成参数更新的方向。
我不打算背公式。神经网络里的公式其实很少,关键是理解每个符号从哪来、到哪去。比如一个简单的线性层,本质上就是矩阵乘法和加法,而整层网络的前向传播,就是把这些计算一层一层叠起来。我给自己定了原则:每一个公式都要回答两个问题——它计算了什么?它想解决什么问题?回答不了就算没学会。
1.3 这轮重修的原则:手推公式、代码验证、生活类比
很多人学AI有个误区,喜欢先囤一堆课程和书,然后从环境配置开始折腾,结果三天过去还在装依赖。我这次用的是一种更"笨"的办法:先手推数学,再用代码验证,最后写一个生活类比帮自己记住。比如把前向传播类比成流水线加工,把损失函数类比成质检员打分,把梯度下降类比成摸黑下山,把反向传播类比成"把错误责任沿传送带退回每个工位"。类比不一定严谨,但非常有助于建立直觉。
手推和写代码的顺序也很重要。我先在纸上用一个极小的网络算一遍前向传播,得到一组数字,然后再在代码里复现同样的小网络,对比输出。一旦数字对上了,概念就不再是抽象名词。我的体会是:真正让你记住一个公式的,不是反复阅读,而是亲手算出来、亲眼看到输出变化的那一瞬间。
2. 前向传播:数据在神经网络里流动的完整路径
2.1 神经元的本质:一次加权求和
神经网络最基本的单元,放在数学上并不神秘。一个神经元做的事情就三件事:把输入各自乘以一个权重,加起来,再加一个偏置。写成公式就是 z = w1x1 + w2x2 + ... + b。这里的权重代表"某个输入对结果的影响程度",偏置则像是一个基础分,决定在没有输入时神经元也能有一个初始倾向。
我拿日常场景做了个类比。假设你在配一杯咖啡:不同原料的用量是输入,你对每种原料的偏好是权重,最后固定加的那勺糖就是偏置。前向传播算的就是"按照你的配方,这杯咖啡最终会是什么风味"。神经网络训练的本质,就是不断调整这些权重和偏置,让配出来的咖啡更接近顾客真正想要的味道。
多个神经元排成一层,就构成了全连接层。一层里往往有几十上百个神经元,每个神经元都会同时接收所有输入,各自算一遍加权求和。所以这一层的计算可以用一个矩阵乘法统一表示:输出等于输入矩阵乘以权重矩阵,再加上偏置向量。这也就解释了一个让很多小白困惑的点——为什么神经网络里到处都是矩阵运算,因为它本质上就是"批量执行同一套加权求和规则"。
2.2 激活函数:让网络"弯"起来的开关
如果只是不停地做加权求和,那么无论堆多少层,整个网络最终依然等价于一次线性变换。就好比你把很多条直线首尾相接,拼起来还是直的。真正的神经网络必须能拟合复杂的非线性关系,所以每一层之后都要加一个激活函数,让输出产生"弯曲"。
最常见的两个激活函数,一个是ReLU,公式是 h = max(0, z);一个是Sigmoid,会把任意实数压缩到0到1之间。ReLU现在的使用频率很高,因为它计算简单、在正区间梯度恒为1,能有效缓解梯度消失;而Sigmoid更适合输出层做二分类概率输出。前向传播每经过一层,就是先做线性加权求和,再过一道激活函数的门,换到更高维或非线性的表达空间。
我最初理解"激活"这个词时总觉得抽象,后来换了个角度:它其实是一道开关。ReLU的意思是"你小于等于零,我就把你掐灭;你大于零,我就放你原样过去"。就是这么一个简单的非线性开关,让网络有了表达复杂函数的能力。没有它,深度就失去意义。
2.3 一个两层小网络的手工前向传播示例
空谈公式容易飘,我拿一个具体例子走一遍前向传播。假设一个小网络要预测房价,输入是两个特征:房屋面积和卧室数量。网络结构是2个输入、第一层4个神经元、第二层输出1个值。第一层权重W1是2×4的矩阵,偏置b1长度为4;第二层权重W2是4×1,偏置b2长度为1。
当一个样本 x = [面积80, 卧室2] 进来,第一层的计算是 z1 = x × W1 + b1。得到4个值,比如 [30.1, -12.4, 8.7, 5.5],然后经过ReLU变成 [30.1, 0, 8.7, 5.5]。这个结果 a1 作为第二层的输入,再算 z2 = a1 × W2 + b2,假如结果是235.6,这就是模型当前对这套房子的预测价。注意,这里所有数都是我随手编的,但流程是真实的。
第一遍手算的时候我最大的感受是:前向传播其实一点都不复杂,它就是把输入数据按层一层一层"翻"过去。那我为什么以前总是觉得神经网络很难?因为网上多数示例一上来就是CNN、Transformer,跳跃太大。从这种2×4×1的小网络开始,每个人都能在三分钟内算出结果。
2.4 我栽过的坑:维度对不上
前向传播最容易出问题的地方不是数学,而是维度。我第一次写代码跑前向时,把输入矩阵设计成了[特征数, 样本数],权重矩阵又用了另一套习惯,结果矩阵相乘那一步直接报错。矩阵乘法的规矩是前一个矩阵的列数必须等于后一个矩阵的行数,我折腾了半天才意识到,自己把行列写反了。
这个教训让我总结了一个极其实用的维度检查法:每一步都只问一句话——"结果应该是什么形状?"比如全连接层把2维输入变成4个神经元,那输出一定是[样本数,4];第二层把4维变成1维,输出就是[样本数,1]。用这个期望形状去反推每个矩阵的行列,就能提前发现错误,而不是等报错信息出来再抓瞎。
维度问题看起来只是工程细节,实际上它反映了你对网络结构的理解程度。我后来发现自己只要把"样本数、特征数、神经元数"这三个数量充分分别清楚,前向传播就再没犯过错。对小白来说,这比硬记任何API都有用。
3. 损失函数:训练里唯一裁判怎么打分
3.1 "对错"没法当训练信号,连读误差才是
网络前向一次,得到预测值,但我们怎么知道它预测得好不好?直觉会告诉你:和真实答案越接近越好。可"接近"需要数字来定义。分类任务里很多人第一反应是"预测对了就记1分,错了就记0分",但这种方式给不了训练方向——它对参数更新来说太粗糙了。一个预测概率0.51和一个预测概率0.99,在"对错"上是一样的,但显然0.99更接近正确答案,理应获得更小的损失。
所以损失函数要做的事,就是把"预测值和真实值之间的距离"翻译成一个连续数字。数字越小,说明预测越准;数字越大,说明错得越厉害。这个数字给了梯度下降一个明确的"工作目标":接下来要做的,就是不断调整参数,让这个数字尽可能小。
理解这一点后,我忽然明白为什么训练过程总是围绕损失曲线转。损失不只是一个数字,它是整个训练过程的指挥棒:前向传播算出损失,损失驱动反向传播,反向传播提供梯度,梯度指导参数更新。没有损失函数,前面所有计算都是无头苍蝇。
3.2 MSE与交叉熵:什么时候用哪个
最常见的两个损失函数,一个是均方误差MSE,一个是交叉熵。MSE的公式是把每个样本的预测值与真实值之差平方后求和取平均,主要用在回归问题里,比如预测房价、温度这类连续数值。平方操作有两个作用:去掉正负方向的影响,同时让偏离大的样本获得更大的惩罚。
交叉熵通常用在分类问题里,它衡量的是两个概率分布之间的差异。我一开始看公式觉得抽象,后来用一句话记住:如果模型对一个样本本应给出接近1的概率却给出0.1,交叉熵会给出很大的惩罚;如果给出0.9,惩罚就很小。它对"盲目自信"和"该高不高"的行为特别敏感。
我做了个简单的对比,帮自己记忆:
| 损失函数 | 适用场景 | 直觉解释 | 一个不受用的时刻 |
|---|---|---|---|
| 均方误差MSE | 回归、连续值预测 | 预测值和真实值的直线距离,平方后放大误差 | 分类任务里概率分布差异表达得不够好 |
| 交叉熵 | 分类、概率输出 | 两个概率分布的差异,错误类别惩罚更大 | 回归任务里计算跨度差异大,不太直观 |
选择损失函数不是随便定的,它需要匹配输出层的激活函数。比如二分类输出层用Sigmoid,那配交叉熵通常比MSE效果好;回归任务输出层不加激活函数,那用MSE就很自然。这里面的原因牵扯到梯度形状和收敛速度,第一课里我先记住"匹配关系",后面再深抠。
3.3 看损失曲线调参:震动与停滞
我第一次训练小网络时,最关心的就是损失曲线。结果第一次跑,曲线一路震荡,损失值忽高忽低,完全没见收敛。我以为是代码写错了,后来发现是学习率设得太大,导致参数每次更新都跨过最优区域,来回弹跳。换了一个更小的学习率后,曲线立刻平滑了很多。
另一次经历更邪门,损失刚开始下降很快,到某个点后几乎停住不动。我怀疑网络坏了,后来检查发现,输入数据没有做归一化:房间面积是80、100这种量级,卧室数是2、3这种量级,数值大的特征对梯度的影响完全盖过了小特征。我把输入缩放到相近区间之后,训练恢复顺畅。这两次经历让我养成一个习惯:任何训练问题,都先看损失曲线,而不要急着怀疑代码逻辑。
4. 梯度下降:从山坡摸黑下山的每一步
4.1 梯度:告诉你往哪个方向走下降最快
损失函数是一个以网络所有参数为自变量的函数,训练的目标就是找到一组参数,让损失值最小。但参数有成百上千个,我们不可能一个个枚举去试,所以需要用梯度下降法。梯度这个东西,直观理解就是山坡上"最陡峭方向"的箭头:在多维参数空间里,它告诉你往哪个方向调整参数,损失函数值上升最快。
注意,梯度指向的是上升最快的方向,而我们要的是下降,所以参数更新的方向是梯度的反方向。公式写出来是:w_new = w_old - 学习率 × 梯度。这里的学习率决定了每一步迈多远。我刚开始总记不住为什么是减号,后来想通一个类比:你站在山坡上,梯度告诉你"往东南方向爬能最快到顶",你想下山就往反方向走,所以是减。
单参数情况最好理解。损失函数对某个权重画出来是一条碗形曲线,梯度就是曲线上某一点的切线斜率。斜率为正说明权重增加会让损失变大,那就要减小权重;斜率为负说明权重增加会让损失变小,那就要增大权重。每一步都朝反方向迈一点,就一点一点滑向碗底。
4.2 学习率:步子大小决定生死
学习率的设置,是新手学梯度下降时最容易炸的一个点。我踩过的典型场景是这样的:学习率设成0.5,损失曲线像过山车一样上下乱跳;设成0.001,曲线倒是稳定了,但三千步过去还没走到最优处,训练速度慢得让人抓狂。后来才知道,学习率本质上决定了你每一步"吃进"梯度信息的多少,太大容易震荡甚至发散,太小容易训练半天毫无变化。
比较粗浅的经验是:如果损失曲线反复横跳,优先把学习率调小十倍;如果损失下降得非常缓慢,可以尝试增大学习率。很多框架自带动量或自适应学习率,其实都是为了缓解"一步大一踩空、一步小走得慢"这个矛盾。第一课我暂时不展开,但先把"学习率是关键中的关键"这句话刻在脑子里。
还有一个经常被忽略的点,学习率要配合损失的量级一起看。不同损失函数、不同数据量下,梯度的绝对值范围差异很大,同一个学习率在不同任务里的表现可能天差地别。所以不要死记某个数值,要观察曲线再判断。
4.3 我撞上的局部最优与鞍点
把参数空间想象成起伏的山脉,梯度下降这招从任意位置开始,一路沿着下坡方向走,最后停在一个"爬不动"的地方。这个最低点可能只是附近区域的局部最优,而不是全山最低。更麻烦的是鞍点——某个方向上看着是上坡、另一个方向看着是下坡的地形,梯度很小,更新很慢,像被卡住了一样。
我确实遇到过这种情况:一个两层网络训练到一半,损失停在0.45左右怎么都下不去。一开始我以为是网络容量不够,后来试着换随机初始化的种子、调学习率,损失才跨过那个平台继续下降。这说明梯度下降本身是有局限性的,它不保证找到全局最优,只保证可能找到一个不错的局部解。
理解这一点对我特别重要,因为它解释了训练任务里很多"玄学"现象:同样的代码跑几次,结果却不一样,根源就在于初始参数不同,梯度下降走出的路径不同。小白不需要把所有优化策略一次性学完,但要先接受一个事实:训练是一个在复杂地形里不断摸索的过程,而不是一条直线通往答案。
4.4 梯度下降最有反直觉的一点
我学习梯度下降时觉得最反直觉的地方在于:我们明明希望损失最小,却需要先计算损失对每个参数的"敏感程度",也就是导数;导数好像是"为了增大损失而存在"的信息,我们却拿它反向使用。后来我想通了,导数本身是中立的,它只描述"趋势",不带有"好坏"。就像指南针告诉你北方在哪,至于你要不要往北走,取决于你想去哪里。
梯度下降和反向传播经常被放在一起说,但它们是两个不同的概念。梯度下降是参数更新的策略,反向传播是高效计算梯度的方法。前者决定"往哪走、走多远",后者决定"怎么算出该往哪走"。我在这一课里最大的收获之一,就是把这两个概念彻底分开了。很多人把反向传播当成"神经网络的训练方式",其实反向传播只是一条计算梯度的快速通道,训练的大策略始终是梯度下降。
5. 反向传播:让误差从输出端一路退回每个权重
5.1 链式法则是唯一的引擎
要知道每个权重对损失的影响,最简单的数学工具就是求导。可问题是,神经网络的损失是好多层复合运算的最终结果,直接对某个中间层权重求导,算式会变得很长。链式法则解决的就是这个问题:把整条复合路径的导数拆成一连串局部的导数,然后相乘。
举个例子。如果 y_pred = 第一层输出 × 第二层权重,而损失 L = (y_pred - y)²,那么 L 对第二层权重的导数,等于 L 对 y_pred 的导数乘上 y_pred 对权重的导数。第一项是2(y_pred-y),第二项是第一层输出本身。就这么一个简单的连乘,贯穿了所有层。
我一开始觉得链式法则是高中知识,没什么稀奇。但真正手推才发现,多层的难点不在于规则,而在于路径长、节点多,容易漏乘或乘错。反向传播从名字上看很玄,实际就是"从输出端开始,沿着前向传播的路线倒着走一遍,每次只算局部导数,再把它们一段一段乘回去"。
5.2 从计算图理解梯度怎么"往回传"
把网络画成计算图会直观很多。前向传播从输入开始,经过加权求和、激活函数、加权求和,最后到损失,就像一条生产线。反向传播则是从损失这个终点出发,逆着整条生产线走回去,每到一处就把上一站传下来的梯度,乘以这一站对输入的局部导数,得到往前一站继续传的梯度。
我用传话游戏来理解。队尾传出一句"损失偏大了",队首的每个权重都很想知道"这个责任该算我多少"。偏差从队尾往前传,每个人都在自己的环节补一句"经过我这里要乘以这个系数",最终传到队首时,每个权重都拿到了属于自己的责任份额——这就是梯度。
计算图视角帮我解决了一个一直困惑的问题:为什么反向传播能一次算出所有梯度?因为它本质上是一次"按拓扑顺序倒序执行的计算",每个中间节点的梯度只会被计算一次,然后被送往更前面的节点。整个过程的计算量大致等于一次前向传播,而不是为每个参数各做一遍求导估算。
5.3 手推反向传播最容易算错的三个位置
我手推反向传播时踩过不少坑,挑三个最典型的分享出来。第一个是偏置bias的梯度,很多人算出来之后发现维度对不上。原因是偏置在计算时被广播到了所有样本,所以它对损失的贡献来自所有样本的累积,求梯度时要把每个样本的对应梯度按列求和,而不是简单取某一个位置的值。
第二个位置在ReLU的导数。ReLU在z大于0时导数为1,小于等于0时导数为0。这意味着一旦某个神经元的加权和z为负数,经过ReLU后梯度直接被"掐断",反向传播传不过去。我曾在一次训练里发现第一层某些参数完全没被更新,排查半天发现是ReLU装在前面的输出总是负值,导致对应的梯度全为零。这种"神经元死亡"现象训练深层网络时很常见。
第三个位置是矩阵导数方向容易写反。求 W2 的梯度时,到底是 a1.T @ dz 还是 dz @ a1.T,很多人会绕晕。我用一个最实用的办法避免这个坑:算完先检查结果维度,梯度矩阵的维度必须和原权重矩阵完全一致。比如 W2 的形状是[4,1],如果算出来的梯度是[6,4],那肯定方向反了。维度检查法又一次救了我。
5.4 梯度消失与梯度爆炸:深层模型第一课
多层网络反向传播时,梯度是一路连乘下来的。连乘因子如果普遍小于1,层数一多,传到前面层的梯度会指数级衰减,很快就接近0,这就是梯度消失。反过来,如果因子普遍大于1,梯度又会指数级膨胀,变成梯度爆炸。我拿Sigmoid做过实验,它在饱和区的导数只有0.25左右,假设网络有20层,0.25的20次方小到几乎无法用常规精度表示。前面几层的权重根本得不到有效更新,网络看起来像在"拒绝学习"。
这个知识让我理解了很多框架层面设计的初衷:为什么深层网络常用ReLU而不是Sigmoid,为什么输入要归一化,为什么模型训练时要用一些精巧的初始化策略。它们本质上都是为了让反向传播的梯度链尽可能稳定,不要过早消失或爆炸。对训练一个大模型来说,梯度稳定性甚至比网络宽度更重要。
我不打算在这一课把所有优化技巧讲完,但至少明白了:反向传播不只是"算梯度",它还会暴露网络结构上的隐患。一个深层模型的训练难度,很大程度来自梯度传递路径太长。这个认知让我看大模型相关文章时,少了很多一头雾水。
6. 不靠框架,用几十行代码把训练循环跑通
6.1 网络与数据的准备工作
讲了这么多概念,如果不亲手跑一遍,总感觉隔着一层。我决定不借助任何深度学习框架,只用数值计算库,从零实现一个最简单的双层网络训练循环。数据我自己造:6个样本,每个样本两个特征,分别代表面积和卧室数,标签是房价。因为是我自己造的数据,规律很明显,样本里面积越大、卧室越多,房价越高,方便观察模型是否能学会。
权重初始化我用了随机数乘以0.5的尺度,这是为了让初始预测值不要偏得太离谱。偏置全部初始化为0。输入数据直接使用原始数值,但为了让训练更快,我先手动做了归一化。这一步其实对应了我前面提到的坑——不归一化,训练很可能卡住。
6.2 前向、反向、更新的完整代码
这段代码很短,但它把前向传播、损失函数、反向传播、梯度下降四个概念完整串起来了。核心只有几行矩阵乘法和导数计算:
import numpy as np # 数据:两个特征,6个样本 X = np.array([ [1.0, 2.0], [2.0, 1.0], [1.5, 1.5], [3.0, 2.0], [2.0, 3.0], [3.5, 2.5] ]) y_true = np.array([[300], [250], [275], [450], [500], [550]]) # 初始化参数 np.random.seed(0) W1 = np.random.randn(2, 4) * 0.5 b1 = np.zeros(4) W2 = np.random.randn(4, 1) * 0.5 b2 = np.zeros(1) learning_rate = 0.05 for step in range(1000): # 前向传播 z1 = X @ W1 + b1 # 隐层加权和 a1 = np.maximum(z1, 0) # ReLU激活 y_pred = a1 @ W2 + b2 # 输出层,回归任务不加激活 # 损失:均方误差 loss = np.mean((y_pred - y_true) ** 2) # 反向传播 dL_dy_pred = 2 * (y_pred - y_true) / len(X) dL_dz2 = dL_dy_pred dL_dW2 = a1.T @ dL_dz2 dL_db2 = np.sum(dL_dz2, axis=0) dL_da1 = dL_dz2 @ W2.T dL_dz1 = dL_da1 * (z1 > 0) # ReLU导数 dL_dW1 = X.T @ dL_dz1 dL_db1 = np.sum(dL_dz1, axis=0) # 梯度下降参数更新 W1 -= learning_rate * dL_dW1 b1 -= learning_rate * dL_db1 W2 -= learning_rate * dL_dW2 b2 -= learning_rate * dL_db2 if step % 100 == 0: print(f"step {step}, loss {loss:.4f}")第一次跑通这个循环时,我盯着逐步下降的loss值看了很久。前100步损失从四位数掉到两位数,500步后已经接近零。那一刻我才真正有了"模型在被我训练"的体感:每个参数一行一行更新,损失一分一分下降。
6.3 跑完代码后回头再对照概念
跑完代码之后再回看那三个概念,理解就完全不一样了。前向传播就是循环里从X到y_pred的三行计算,它把输入变成了预测;损失是紧接着那行mean平方差;反向传播是那一串从dL_dy_pred开始的梯度计算;梯度下降是循环末尾那四个带减号的更新语句。命名空间里再也不是抽象的术语,每段代码都长着一张清晰的脸。
代码里还有一个值得注意的细节:y_pred的梯度计算里除以了样本数len(X),这是因为损失函数是"平均"平方误差,反向传播时要把"平均"这个操作的导数也体现出来。很多教程里这一步容易漏,漏了之后梯度会按样本数倍偏大,学习率得相应调小才能平衡。这也是我踩过的一个小坑。
不借助框架手写一遍训练循环,比调第三方接口一个月都更能建立对训练过程的理解。我强烈推荐每个小白都至少做一次这个实验,花不了多少时间,却能打通很多知识关节。
7. 重修第一课的踩坑记录与下一步
7.1 最想提醒小白的几件事
第一课学完,我想把几个自己亲历的教训整理出来。第一个是"先画维度,再写代码"。任何网络层,动笔之前先画出输入维度、权重维度、输出维度,代码很难写错,报错时也容易定位。第二个是"训练中的任何异常,先看损失曲线"。震荡看学习率,停滞看数据归一化和网络结构,发散看学习率是不是大到夸张。第三个是"反向传播和梯度下降要分开记"。一个是算梯度的工具,一个是更新参数的策略,合并记忆会导致后续看优化器都看不懂。
还有一个认知层面的提醒:不要因为公式多就被吓退。我第一遍手推反向传播时也算了满桌草稿纸,可每条链其实都只是链式法则的重复运用。真正理解之后会发现,神经网络训练的骨架类就这么几块:前向传播、损失计算、反向传播、参数更新。各种高级模型,不过是把这几块变得更大、更复杂而已。
7.2 从这一课到大模型还差什么
学完第一课再回看开头那个让我脸红的场景,感受最大的变化,是我终于能清楚说出模型训练的核心链路了。我从一个只会调接口的人,变成了一个至少能画出训练循环、手写几十行代码把loss压下去的人。距离真正训练一个大模型当然还差很多:海量数据的处理、分布式训练、各种先进优化器和架构设计,这些都会在后面慢慢补。
但地基已经不一样了。回头再看那些大模型技术文章,很多以前读不懂的表述,比如"参数更新""梯度检查""学习率调度""损失爆炸",都有了落脚点。这篇是第一课的重修日记,下一课我打算写损失函数的更多细节、优化器的演进,以及它们如何影响深层网络训练。重修之路才刚刚开始,但至少,我已经能说服自己:这个AI小号是真的在练级了。