神经网络这十年:从反向传播到预训练大模型的演进与工程实践

发布时间:2026/10/19 7:31:46
神经网络这十年:从反向传播到预训练大模型的演进与工程实践
2014年我刚开始碰神经网络时这玩意儿在圈子里其实不太受待见。图像任务的主流做法还是靠手工设计特征再加分类器文本任务则依赖词表统计和线性模型谁要是说想用神经网络做项目组里的导师大概率会先反问一句你有GPU吗十年后再看同样是这批人手里的模型从几十万参数的浅层网络变成了动辄千亿参数的预训练大模型当年的手写识别入门题如今已经变成中学生也能上手的科普演示。这篇东西不是教科书也不打算把十年间的论文全部罗列一遍。我想以一个一线工程师的视角把神经网络这十年的演进脉络、背后的技术逻辑、以及自己在实际项目中反复体会过的东西重新梳理一遍给正在入行的人一张稍微完整一点的地图。1. 2014年前后神经网络还是费力不讨好的冷门手艺1.1 传统机器学习打天下的时代特征设计才是核心手艺在深度学习成为主流之前一个典型的图像识别项目流程大概是这样的先写代码提取各种手工设计的特征——颜色统计量、方向梯度直方图、纹理特征——然后把特征拼成一个高维向量最后扔给支持向量机或者随机森林训练。文本分类更直接词频统计、逆文档频率、N元语法组合起来配上一个线性分类器就能解决大部分问题。那时候决定模型上限的不是模型本身而是特征工程。因为你定义的每一个特征都是把自己对这个领域的理解写进了那段提取代码里。做行人检测的人会反复研究不同尺度下的梯度特征怎么归一化做语音识别的人会关心频域特征怎么拼接上下文。模型反而变成了一个相对固定的组件换了特征提取方式效果可能天差地别。这种模式有一个致命问题特征设计高度依赖专家经验换一个场景就得重新设计一遍。我早期做过一个植物叶片分类的练手项目为了凑够训练样本光数据收集和标注就占了大半个月。边缘特征、纹理特征、颜色特征前前后后试了一个多月最后在测试集上的准确率勉强过了八成。后来看到同样的任务用神经网络做出来的结果心里确实不是滋味。1.2 亲手写反向传播当年入门的必修课我第一次真正理解神经网络是被要求手写一个多层感知机——不依赖任何现成的深度学习框架连基本的矩阵运算都要自己用数值库实现。当时写的网络只有三层一千多个参数跑的任务是最简单的手写数字识别。手写网络本身不难难的是调通。我记得当时踩得最狠的坑是梯度消失隐层激活用的是饱和型函数初始化权重稍大一点误差反向传播到第一层时梯度已经小到几乎看不见训练几百轮损失都不动弹。后来做了两件事才跑通一是把权重初始化范围缩小二是把隐层激活函数换成非饱和的类型。这两件事在今天看来都是基本功但在没有成熟框架指导的情况下每一个都需要靠实验去试错。也正因为亲手写过一遍反向传播我才真正理解了深度学习的本质它就是在做复合函数的链式求导加上大规模数据驱动下的数值优化。这个直觉后来帮了我很多年。至少在看到某个模块出现不该有的行为时我能从梯度的角度推断出问题大概出在哪里而不是只会换个网络结构碰运气。1.3 当年训练小网络要翻过的三座山那时候训练一个像样的神经网络要同时对抗三件事。首先是过拟合。数据量小的时候模型很容易把训练集背下来。我当时试了各种正则化手段权重衰减、早停、随机失活甚至给输入加噪声。经验是随机失活最管用但比例要反复调调狠了模型欠拟合调轻了等于没有。其次是学习率。那时候基本靠经验法则先用一个比较小的初始值训练过程中按固定步数手动调低。没有成熟的学习率调度器也没有自适应优化器参数更新方向完全依赖随机梯度下降及其简单变体。我记得有段时间为了找到合适的学习率要反复重启训练每次都是几个小时起。第三是参数敏感。权重初始化、批量大小、数据增强策略样样都影响最终效果。很多问题像玄学同一份代码同一个随机种子两次跑出来的结果差别很大。当年没有完善的实验管理工具调参靠手写日志复现别人的成果经常要连猜带蒙。回头看这些不友好反而逼着当年的从业者把底层原理搞清楚。如今框架把大多数细节都封装好了训练难度大幅降低但很多人也因此丧失了对底层机制的理解遇到问题只能靠试错。2. 架构换血的三次浪潮卷积、循环、再到自注意力2.1 卷积网络的深意味着什么2012年前后深度卷积神经网络在大规模图像分类竞赛中拿下冠军识别错误率几乎减半。这件事为什么重要因为它证明了只要数据量够大、网络够深、算力够强神经网络可以自己从像素里学出层次化的特征——底层的边缘和颜色中层的部件高层的物体语义。整个特征工程那条路线一下子显得不那么必要了。随后的几年卷积网络的主线就是怎么变得更深。层数从七八层加到几十层再到上百层。但层数加深之后出现了新的问题网络越深训练误差反而上升。这不是过拟合而是优化困难——深层网络的信息传递链路太长梯度难以稳定回流。残差连接就是针对这个问题来的让每一层学习相对于上一层的增量而不是从零学一个完整映射。配合批量归一化把每一层的输入分布拉回来训练上百层的网络才变成一件相对稳定的事。卷积网络给我留下最深的印象不是它有多准而是它把局部性这个归纳偏置用到了极致相邻像素的相关性、平移不变性天然适合图像。但也正是这个强偏置在后面处理长距离依赖时成了束缚。2.2 循环网络的黄金时代与绕不过去的天花板在自然语言和语音这类时序任务上卷积网络并不顺手循环网络才是主角。循环网络的思想很朴素每个时间步的隐藏状态既取决于当前输入也取决于上一个时间步的隐藏状态相当于给模型装了一个记忆。不过朴素的循环结构梯度很难传得远几经改造才有了带门控机制的长短期记忆网络以及门控循环单元。门控机制本质上是给记忆装了闸门输入门决定记住什么遗忘门决定丢掉什么输出门决定放出什么。这套机制让信息可以在隐藏状态里保存几十甚至上百个时间步机器翻译和语音识别任务因此获得了大幅提升。但循环网络有一个绕不过去的天花板它只能按时间顺序逐个处理输入无法并行。句子越长训练和推理就越慢而且无论门控怎么设计极端的长距离依赖依然守不住。我做对话系统时遇到过很典型的问题对话上下文超过几十步之后模型基本就失忆了回答质量断崖式下跌。这个屋顶一直顶着直到自注意力机制出现。2.3 自注意力架构一次全局关系建模的范式替换自注意力机制把思路带回到一个很本质的问题上序列里任意两个位置的依赖关系为什么非要靠一条接力棒似的隐藏状态链条来传递不如让每个位置的表示直接和所有其他位置做交互按相关程度加权聚合。这个思路用数据库检索来类比特别好懂每个位置都是一组键值对查询是当前的位置输出就是根据查询和每个键的匹配程度把对应的值加权求和。整个过程可以一次性算出所有位置之间的关系矩阵天然支持并行。为了保证模型知道每个位置在序列里的前后顺序还要给输入加上位置编码。def attention(Q, K, V): d Q.shape[-1] scores Q K.T / (d ** 0.5) weights softmax(scores) out weights V return out后来的演进大家也都看到了一开始注意力只是作为增强模块嵌在循环层两端后来干脆把循环层整个去掉变为纯自注意力架构再堆叠很多层。这条路几乎同时解决了并行性和长距离建模两个痛点于是在机器翻译、文本分类、阅读理解这些任务上全面反超此前的方案。我还有一个很深的印象纯自注意力架构的训练特别吃数据和算力小数据量下反而不如卷积或循环模型稳因为它的局部性偏置是学出来的而不是结构里自带的。维度卷积网络循环网络自注意力架构并行性较高卷积可并行计算低必须按时间步串行高序列全局可并行长距离依赖依赖层数堆叠代价很高有限超长上下文会丢失天然支持位置间直接交互归纳偏置强局部性、平移不变中顺序建模弱几乎全靠数据学习小数据表现较好较好较差数据不足容易欠拟合训练稳定性中等加深时需要残差和归一化较低需要梯度裁剪等技巧相对高需要合理初始化3. 支撑十年爆发式增长的三条腿数据、算力、框架3.1 数据规模从手工标注几百张图到互联网级别的弱监督早期做视觉项目数据全靠自己收集和标注。我记得为了做一个叶片分类练手项目为了凑够几千张样本光是拍摄、裁剪、清洗、打标签就干了一周。后来才知道这还算运气好有些方向连公开数据都找不到数据质量也参差不齐。深度学习爆发的一个重要前提是互联网级别的数据被系统性地组织了起来百万级标签图像、海量文本语料、大规模语音数据。更重要的是后来大家发现很多训练信号根本不需要昂贵的人工标注图片自带的文字描述可以当弱标签一句文本里挖掉一部分让模型去猜就能构成自监督信号。预训练模型吃的就是这种免费数据。但数据量变大不等于数据变好。我在实际项目中反复遇到过数据泄露、类别不平衡、标注噪声的问题。十年前数据少但你能控制质量十年后数据多但质量控制本身变成了一项系统工程这部分我后面会展开讲。3.2 算力这条腿从CPU熬一夜到集群里烧掉一大笔预算2014年我训练一个几层的小网络用CPU跑一个像样的图像分类实验经常是下午启动、第二天早上看结果中间不敢断电。后来换到带图形处理器GPU的机器一个原本要跑一夜的实验压缩到了几十分钟。这个变化不只是多少倍加速的问题而是改变了实验节奏你可以在一天内试很多组超参数迭代速度上来了试错空间就大了。之后几年的算力主线有三条单卡性能持续提升显存更大、矩阵运算更快分布式训练把任务拆到多张卡甚至多台机器上并行混合精度训练用更低精度的数值表示换取更快的计算和更省的显存同时通过损失缩放把精度损失补回来让训练既提速又不明显掉精度。算力这条腿的代价也是真实的。训练大模型的耗电量、硬件成本、碳排放如今已经是绕不开的话题。对普通团队来说成本约束会直接决定模型规模的选择——不是越大越好而是在预算范围内尽量大。3.3 框架与生态从点火到控火早年没有成熟框架做深度学习要自己写网络定义、手动算梯度、自己实现卷积层。我印象很深的是实现一个反向传播模块写代码两天调试一周而同样的功能在今天的主流框架里就是一行API调用。框架演进的几个阶段其实很有意思。第一代框架是符号图式的先定义一张计算图再编译执行好处是便于优化坏处是调试困难错误往往发生在图编译阶段而不是代码执行的那一行。第二代框架改为定义即运行代码逐行执行的同时动态构建计算图调试体验和普通程序基本一致学习门槛大幅降低。虽然牺牲了一部分编译期优化但开发效率的收益远远盖过了那点损失。现在一个标准的训练循环大概长这样for epoch in range(num_epochs): for batch in data_loader: inputs, targets batch outputs model(inputs) loss loss_fn(outputs, targets) optimizer.zero_grad() loss.backward() optimizer.step() scheduler.step() log(epoch, epoch, loss, loss.item())框架背后的生态同样重要预训练模型仓库、数据增强工具、可视化组件、实验跟踪平台这些共同构成了今天的标准流水线。我在对比过几个主流方案之后最大的心得是选框架就是选生态。不要只看某个API好不好看要看社区活跃度、模型仓库丰不丰富、长期维护稳不稳定——这些东西在项目遇到疑难问题时价值会放大很多倍。3.4 实验管理与可复现性被长期低估的地基数据和框架都成熟之后有一项工作长期被我低估就是实验管理。早年我的实验记录是一堆手写表格加命名混乱的脚本某个超参数或者某个数据预处理步骤没记下来结果就不可复现。有一段时间我在复现一篇论文连着三周结果都对不上最后发现是对方在数据清洗时偷偷去掉了某些异常样本。后来我给自己定了几条铁律每次实验记录随机种子、数据版本、超参数、代码版本跑完一个实验马上固化结果而不是等着最终统一整理所有消融实验都从最简单的基线开始逐步往上加组件。这些习惯听起来琐碎但它们才是这十年技术演进里最值得普通从业者带走的东西。4. 范式转折从训练专用模型到预训练微调再到生成一切4.1 预训练为什么能行先学通识再学专业早期做自然语言任务都是每个任务单独训练一个模型。任务数据不够模型就学不好。后来出现了一个关键思路先用海量无标注文本让模型学习语言本身。比如掩码语言建模——把一句文本随机挖掉一部分让模型根据上下文把挖掉的内容预测出来。这个过程不需要人工标注数据可以无限量供应。学完之后模型肚子里已经装了大量关于语法、语义和世界常识的通识再拿到具体任务上用少量标注数据做微调效果立刻不一样。这个思路后来被搬到了图像、语音、多模态等领域先在大规模无标注数据上做自监督预训练再在下游任务上微调。我做过的一个图像项目也是这样直接用随机初始化的网络在小数据上训练效果很差换用预训练权重之后哪怕只微调最后几层准确率都能提高一大截。预训练的本质是把从零学变成了在巨人肩膀上微调。4.2 规模法则与涌现能力当大本身变成一种超参数预训练模型还有一个独特性质当模型参数量、训练数据量、计算量同时往上加的时候性能会以非常稳定的规律提升这就是规模法则。翻译成人话就是在可预测的预算范围内加大模型和数据量效果大概率变好。这让扩大规模第一次成了一个有依据的决策而不是拍脑袋。更让很多人意外的是涌现能力某些能力在模型很小时完全不存在一旦规模跨过某个阈值突然就出现了。典型例子是少样本学习——给模型几个示例它就能照着做新任务不需要更新任何参数。这种使用方式彻底改变了训练和推理的交互形态模型的角色从针对单任务的专用工具变成了通用的任务执行接口。但规模法则的另一面是成本。大模型的训练预算动辄是一个普通团队几年的研发经费而且规模越大调试和复现的难度也指数级上升。我见过不少团队复现大模型时遇到的问题同样的配置几次运行之间随机波动很大你甚至分不清到底是运气问题还是工程问题。4.3 扩散模型与生成式路线的另一条主线与判别式模型一路狂飙并行生成式模型这十年也经历了一次换代最典型的是从生成对抗网络到扩散模型。生成对抗网络的思路是让一个生成器和一个判别器互相博弈生成器负责造假样本判别器负责分辨真假两者在对抗中共同进步。这个思路很优雅但训练极不稳定经常出现生成器把判别器骗死之后自己崩溃的情况俗称模式坍缩。扩散模型换了一个完全不同的思路先在数据上逐步加噪把一张清晰的图像慢慢变成纯噪声然后训练一个网络学会反向去噪从纯噪声出发一步步还原出图像。这个加噪—去噪的过程在训练上非常稳定生成质量也显著提升。后来它成了图像生成乃至音视频生成的主流方案也把可控生成从实验室带到了普通人的日常使用里。4.4 大模型落地的现实工程账大模型虽然效果惊艳落地时的工程账要复杂得多。推理成本是第一个现实问题模型参数动辄百亿千亿每生成一个结果都要过一遍完整计算在线服务的延迟和硬件成本都很高。于是出现了各种优化手段把重复计算出的中间状态缓存下来避免重算用低精度表示和量化压缩模型体积用大模型的知识去蒸馏出更小的模型……每一个优化手段背后都是精度和速度的权衡。另一个现实问题是看起来很强用起来很脆大模型会在简单问题上翻车而且翻车模式很难预估。我自己的应对方式是永远把大模型当能力很强的部件而不是完整的产品思路。在它外面包上规则校验、兜底逻辑和人工审核而不是无脑信任它的输出。这个原则在我做过的几个落地项目里至少避免了好几次事故。5. 工程化的十年从能跑通到可复制、可维护、可交付5.1 部署与推理优化真正决定项目成败的后半程很多新手把模型训练出来当成项目结束实际上在真实项目里训练只是前半程。部署要考虑的问题包括模型跑在什么硬件上、延迟和吞吐预算各是多少、内存够不够、模型升级时服务怎么平滑切换。模型压缩是部署里最常见的需求。剪枝去掉不重要的参数量化把浮点权重压成更低的精度知识蒸馏用大模型教出一个更小的模型。这三招我都在实战里用过效果因任务而异视觉模型量化通常很稳语言模型的低比特量化在极端情况下会出现明显的性能滑坡必须针对具体场景做基准测试再决定压缩到什么程度。5.2 我在实战里踩过的三个坑第一个坑是时间序列数据被我随手打乱之后才切分。当时我在做某设备的故障预测手一抖把全部数据洗牌之后才划分训练集和验证集结果验证集里混进了未来的信息离线指标好看到不行。上线之后效果打回原形排查了很久才发现是切分顺序的问题。从那以后凡是有时间属性的数据我都坚持按时间先后切分。这个教训值一整堂课。第二个坑是换了优化器之后没有重新调学习率。老代码用的是一套收敛策略我图省事换成了自适应优化器却沿用了原来的学习率结果训练损失在早期疯狂震荡怎么压都压不住。后来翻资料才意识到不同优化器对学习率的敏感度差异极大换优化器必须把初始学习率和调度策略一起重新标定。第三个坑是评估指标和业务目标脱节。验收指标定的是准确率但业务真正关心的是少数高风险样本的召回率。模型在总体验收指标上做到95%高得让所有人高兴真正上线时才发现想抓的坏样本漏了一大半。这之后我每次接项目都会先问一句指标是谁定的指标对应的得失是什么指标达标真的意味着业务达标吗5.3 一个典型的项目复盘某电商平台的图像质检辅助系统拿一个做过的典型案例来说说工程化的完整链条。某电商平台每天有大量商品图片需要审核早期方案是规则加浅层分类器准确率勉强能看但误伤率很高大量正常商品被标记成问题商品运营团队每天要人工复核几千条。我们的方案分三步。第一步用预训练模型在商品图数据上做迁移学习先解决特征是否够好的问题。第二步把模型蒸馏成一个小得多的版本让它在低配置CPU机器上也能实时推理这一步直接砍掉了升级服务器的预算。第三步在模型外面加两层兜底高置信度的结果直接自动化处理低置信度的结果进入人工复核队列同时把人工复核的结果回流成训练数据。最终效果是自动化处理占比达到八成以上人工复核量大幅下降而且每两周一次的数据回流让模型在长尾样本上持续变好。这个项目的成功不在于用了多前沿的模型而在于把模型、部署、审核流程和数据闭环拧成了一根绳子。6. 复盘十年我沉淀下来的几条判断与工作习惯6.1 四条贯穿始终的主线回看这十年技术名词换了一茬又一茬但有几条主线一直没变第一泛化能力永远比训练集上的指标重要第二规模是当前阶段最确定的杠杆但它有两面性成本和边际收益都要算清楚第三数据质量决定了模型上限模型结构只是在逼近这个上限第四实验迭代速度越快团队学习速度越快实验基础设施不是成本而是杠杆。6.2 我给自己定的三条工作原则一是永远跑基线。接任何新任务先跑一个最朴素的方案拿到数据再讨论花哨的模型。这条帮我避免了很多次过度设计。二是实验记录要像实验室笔记一样严格随机种子、数据版本、超参数、代码提交号缺一不可。三是不要相信任何单一指标每次报告结果时都附上坏case分析和置信区间。指标之外的东西往往才是真实问题的藏身处。前几天有师弟来问我现在入行是不是不用再手写反向传播了反正框架都封装好了。我的回答是确实不用但至少要亲手把一个模型从数据清洗一路跑到部署上线。我第一次做完整闭环花了将近三个月现在有了成熟工具可能只要两周但过程中踩的坑基本还是当年那些坑只是换了位置出现。如果说这十年有什么东西是我最想提醒后来者的那大概是别因为工具变好了就跳过对问题本身的理解。架构会换代范式会迁移但把数据搞对、把评价搞准、把迭代闭环跑起来这件事永远有人买单。