尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

从零构建AI工程能力:手写神经网络到推理部署全链路实战

从零构建AI工程能力:手写神经网络到推理部署全链路实战 1. 从零搭建AI工程能力为什么我劝你别一上来就调包这两年AI应用开发的门槛肉眼可见地在降低随便拉个框架、调个API、套个模板一个能跑通的Demo半天就能出来。但我自己带过几轮团队、也帮不少朋友做过技术方案评审之后发现一个很普遍的现象很多人能跑通Demo却完全说不清楚数据是怎么流的、模型为什么这么选、推理延迟卡在哪、线上出问题该从哪查。一旦业务量上来、需求一变整个项目就推倒重来。ai-engineering-from-scratch这个标题说的其实就是这件事——从零开始把AI工程当成一门正经的工程学科来搭而不是当成调包游戏。它不是一个具体的开源库也不是某个框架的教程而是一套完整的、自底向上的能力构建路径。核心关键词就是从零构建、AI工程化、全链路理解。它要解决的问题是让一个只会调API的人真正理解并掌握从数据处理、模型训练、推理优化到服务部署的完整工程链路最终能独立设计并落地一个可维护、可扩展的AI系统。这篇文章适合谁看如果你是刚入行一两年、天天在写业务代码但想往AI方向转的工程师或者你已经能跑通模型但总觉得心里没底、想补上工程化这一课再或者你是技术负责人、需要给团队规划一条靠谱的AI能力成长路线那这篇内容应该能给你一些可以直接抄作业的思路。我会把整个从零构建的过程拆成几个阶段每个阶段讲清楚做什么、为什么这么做、具体怎么落地以及我自己踩过的那些坑。2. 整体设计思路为什么“从零”不等于“什么都自己写”2.1 先想清楚“从零”的边界在哪很多人一听到“从零构建”第一反应就是什么都要自己手写——自己实现矩阵运算、自己写反向传播、自己搭一个推理引擎。这个理解不能说错但很容易走偏。我见过不少人花了两三个月手撸了一个简易的神经网络库结果发现除了加深了对链式求导的理解之外对实际工程能力的提升非常有限因为真实项目里你不可能用自己写的矩阵库去跑生产任务。所以“从零”的核心不是“什么都自己造”而是把黑盒拆开理解每一层的职责和边界然后在需要的时候有能力自己实现关键环节。打个比方你学开车不需要从造发动机开始但你得知道发动机、变速箱、刹车系统各自负责什么出了问题大概能判断是哪一块的毛病。AI工程也是一样你不需要自己写CUDA核函数但你得知道GPU显存是怎么被占满的、batch size调大之后为什么OOM、量化到底损失了什么。基于这个思路我把整个从零构建的过程分成四个层次从下往上依次是数学与算法基础层、数据处理与特征工程层、模型训练与调优层、推理部署与服务化层。每一层都有“必须自己动手实现一遍”的核心环节也有“理解原理、熟练使用现成工具”的部分。这个划分不是拍脑袋来的而是根据我实际带项目和做技术评审的经验总结出来的——大部分线上事故和性能瓶颈都出在层与层之间的衔接上而不是某一层内部。2.2 技术选型的几个关键取舍在具体动手之前有几个选型决策会直接影响你后面的学习曲线和工程效率我一个个说。第一个取舍用PyTorch还是TensorFlow。这个问题在2024年其实已经没什么好纠结的了新项目无脑选PyTorch。原因很简单动态图调试体验好太多社区生态活跃大部分新论文的官方实现都是PyTorch。TensorFlow在工业部署侧曾经有优势但现在ONNX、TensorRT这些中间格式和推理引擎已经把这个差距抹平了。我自己的做法是训练用PyTorch导出用ONNX部署用ONNX Runtime或TensorRT这条链路最顺。第二个取舍要不要上分布式训练。我的建议是在你单卡能把一个中等规模模型跑通之前不要碰分布式。原因很实际分布式训练引入的复杂度是指数级上升的通信开销、梯度同步、数据分片、故障恢复每一个都能让你调好几天。而且大部分业务场景单卡甚至单机多卡就足够了。先把单卡训练的效率优化做到极致——比如混合精度、梯度累积、数据加载并行——这些手段带来的收益往往比盲目上分布式更明显。第三个取舍推理框架怎么选。这个取决于你的部署环境。如果是服务端GPU部署TensorRT基本是首选性能优化最彻底如果是CPU环境或者需要跨平台ONNX Runtime更合适如果是在移动端或边缘设备那可能要考虑TFLite或者NCNN。我一般会建议先跑通ONNX Runtime因为它跨平台、上手快、社区支持好等性能真的成为瓶颈了再针对特定硬件做深度优化。2.3 一条可复现的学习路线图把上面的思路串起来我给出一条我自己验证过的路线图按顺序走下来大概需要三到六个月取决于你每天能投入的时间阶段核心任务关键产出建议时长第一阶段手写基础算法与自动求导一个能跑通的微型神经网络库3-4周第二阶段数据处理流水线搭建可复用的数据加载与预处理模块2-3周第三阶段模型训练与调优实战一个完整训练项目调优记录4-6周第四阶段推理优化与服务化部署一个带监控的推理服务4-6周第五阶段全链路串联与项目复盘端到端可复现的完整项目2-3周这个路线图的关键在于每个阶段都有明确的产出物而不是泛泛地“学习某个知识点”。产出物是可以拿给别人看、可以放进简历、可以在面试里讲的东西。我自己带人的时候也是按这个标准来要求的——你说你懂数据处理那你把你写的那个数据加载模块拿出来看看代码结构、异常处理、性能测试报告一目了然。3. 核心细节拆解每个阶段到底在练什么3.1 第一阶段手写微型神经网络库练的是“直觉”这个阶段的目标不是造一个能用的库而是建立对前向传播、反向传播、梯度下降这三个核心概念的肌肉记忆。具体怎么做我建议从标量开始先实现一个最简单的自动求导引擎支持加、减、乘、除、幂、指数、对数这几个基本运算然后基于它搭一个两层全连接网络在MNIST或者一个更简单的二维分类数据集上跑通训练。为什么从标量开始而不是直接上矩阵因为标量版本的代码逻辑最清晰每一个节点的梯度怎么算、怎么传你都能用print打出来一步步看。等你把标量版本吃透了再扩展到矩阵版本你会发现矩阵版本无非就是把标量运算换成了矩阵运算核心的链式法则和计算图逻辑完全一样。这个阶段有几个细节特别值得注意。第一个是计算图的构建方式我建议用“定义即运行”的动态图方式也就是每做一次运算就记录一个节点而不是先定义整个图再执行。这样调试起来直观得多也跟PyTorch的设计哲学一致。第二个是梯度累加的处理很多人第一次写反向传播的时候会忘记把梯度累加而不是覆盖导致多个分支汇聚到一个节点时梯度算错。第三个是数值稳定性比如softmax的实现要先减去最大值再取指数否则很容易溢出这个技巧在后面的实际项目里也会反复用到。注意这个阶段不要追求性能不要用numpy的向量化操作去优化就用最朴素的循环。你要的是理解每一步在算什么而不是跑得快。3.2 第二阶段数据处理流水线练的是“工程规范”数据处理是AI工程里最容易被低估、但实际耗时最多的环节。我自己的经验是一个完整的AI项目数据相关的工作能占到60%到70%的时间。这个阶段要练的不是某个具体的清洗技巧而是建立一套可复用、可测试、可监控的数据处理规范。具体来说你需要实现一个数据加载器支持批量读取、打乱、并行加载、预取这几个基本功能。然后在这个基础上把数据清洗、格式转换、特征提取、归一化这些步骤串成一条流水线。关键点在于每一步都要有独立的单元测试输入输出要明确异常情况要能捕获并记录。我见过太多项目的数据处理代码是一坨意大利面条所有逻辑塞在一个函数里改一个地方就崩一片。正确的做法是把每个处理步骤拆成独立的函数或类用配置文件来组织流水线这样换数据集、调参数的时候只需要改配置不用动代码。另外数据版本管理也很重要每次训练用的数据要能追溯到具体的版本和预处理参数否则实验结果没法复现。这个阶段还有一个容易被忽略的点数据质量的监控。线上推理的时候输入数据的分布可能会慢慢漂移如果不做监控模型效果会悄无声息地下降。所以从这个时候开始就要养成记录数据统计特征的习惯——均值、方差、分位数、缺失率这些指标在后面的服务化阶段会直接用到。3.3 第三阶段模型训练与调优练的是“实验方法论”到了这个阶段你已经有了一定的基础可以开始用PyTorch这样的成熟框架来做真实的训练任务了。但重点不是“能跑通”而是建立一套科学的实验方法论。什么叫实验方法论简单说就是每次只改一个变量记录所有超参数和对应的评估指标用数据说话而不是凭感觉。我自己的做法是维护一个实验记录表每一行是一次实验列包括实验编号、数据集版本、模型结构、学习率、batch size、优化器、训练轮数、验证集指标、测试集指标、备注。这个表看起来简单但坚持记录能帮你省下大量重复试错的时间。调优的顺序也很重要。我的经验是先调学习率和batch size再调模型结构最后调正则化手段。学习率是最敏感的超参数一般从1e-3开始试如果loss震荡就调小如果下降太慢就调大。batch size受显存限制但也不是越大越好太大会导致泛化性能下降通常从32或64开始试。模型结构方面不要一上来就堆很深的网络先从简单的开始逐步加深加宽观察验证集指标的变化。正则化手段比如dropout、weight decay、数据增强放在最后调因为它们的效果往往没有学习率那么显著。提示训练过程中一定要监控训练集和验证集的loss曲线。如果训练loss下降但验证loss上升说明过拟合了如果两个都不下降说明欠拟合或者学习率有问题。这个判断逻辑看起来简单但实际调优的时候非常管用。3.4 第四阶段推理优化与服务化练的是“生产思维”训练出一个好模型只是第一步把它变成线上能用的服务才是真正的挑战。这个阶段要练的是生产环境下的工程思维延迟、吞吐、资源占用、容错、监控这些指标比模型精度更影响用户体验。推理优化有几个常用的手段我按投入产出比从高到低排一下。第一是量化把FP32的权重和激活值转成INT8模型大小直接缩小四倍推理速度通常能提升两到三倍精度损失一般在1%以内性价比极高。第二是算子融合把多个连续的小算子合并成一个大的算子减少kernel launch的开销和内存访问次数这个在TensorRT里是自动做的。第三是批处理把多个请求攒成一个batch一起推理能显著提升GPU利用率但会增加单次请求的延迟需要根据业务场景权衡。第四是模型剪枝去掉不重要的权重或通道这个对精度影响较大需要仔细调。服务化方面我建议从最简单的HTTP服务开始用FastAPI或者Flask把模型包起来加上健康检查、请求日志、性能指标这几个基本功能。然后逐步引入异步处理、请求队列、限流熔断这些机制。监控是重中之重至少要记录每个请求的延迟分布、错误率、输入数据的统计特征。这些数据不仅能帮你发现性能瓶颈还能在模型效果下降时提供排查线索。4. 实操过程一个完整项目的落地记录4.1 项目背景与目标设定为了把上面的思路串起来我拿一个自己实际做过的项目来复盘。项目需求是做一个图像分类服务输入是一张商品图片输出是商品所属的品类总共20个类别。业务方的要求是单次推理延迟不超过100毫秒准确率不低于90%服务要能扛住每秒50次的请求量。这个需求看起来不复杂但拆开来看涉及了数据采集与标注、模型选型与训练、推理优化、服务部署、监控告警这一整条链路。我当时的做法是先花两天时间把整个链路的技术方案写清楚包括每个环节用什么工具、预期指标是多少、风险点在哪然后才开始动手。这个习惯我强烈建议大家养成——方案先行动手在后能避免很多返工。4.2 数据准备与预处理流水线数据这块业务方提供了大约5万张标注好的图片20个类别分布不太均衡最多的类别有8000张最少的只有300张。我的处理步骤是这样的第一步是数据清洗去掉损坏的图片、重复的图片、标注明显错误的图片。这一步用Python脚本批量处理大概花了一天时间最终保留了4.6万张有效图片。第二步是类别平衡对样本少的类别做数据增强包括随机裁剪、旋转、颜色抖动、水平翻转。增强之后每个类别至少保证有2000张图片。第三步是划分数据集按7:1.5:1.5的比例分成训练集、验证集、测试集。这里有个细节要注意划分的时候要保证每个类别的比例一致也就是分层采样否则可能出现某个类别在验证集里一张都没有的情况。第四步是构建数据加载流水线用PyTorch的Dataset和DataLoader加上多进程加载和预取。这里我踩过一个坑num_workers设得太大反而会拖慢速度因为进程间通信的开销上来了。我的经验是num_workers设为CPU核心数的70%左右比较合适比如8核的机器设6。4.3 模型选型与训练调优模型选型上我对比了ResNet50、EfficientNet-B0和MobileNetV3三个方案。ResNet50准确率最高但推理慢MobileNetV3最快但准确率差一点EfficientNet-B0在两者之间取得了不错的平衡。考虑到延迟要求是100毫秒我最终选了EfficientNet-B0输入分辨率224x224。训练配置方面优化器用AdamW学习率用余弦退火从1e-3降到1e-5batch size设为64训练50个epoch。损失函数用带标签平滑的交叉熵标签平滑系数0.1这个技巧能缓解过拟合、提升泛化性能。训练过程中用了混合精度显存占用从8G降到了5G训练速度提升了大约40%。调优过程中我做了几轮实验记录如下实验编号学习率batch size数据增强验证集准确率备注exp-0011e-364基础87.2%基线exp-0021e-364强增强89.5%加了颜色抖动和随机擦除exp-0035e-464强增强90.1%学习率调小exp-0045e-4128强增强90.8%batch size调大exp-0055e-4128强增强标签平滑91.3%最终方案最终在测试集上达到了91.5%的准确率满足了业务要求。4.4 推理优化与服务部署训练完之后我把PyTorch模型导出成ONNX格式然后用ONNX Runtime做推理。优化步骤是这样的第一步是图优化ONNX Runtime自带了一些图级别的优化比如常量折叠、算子融合开启之后推理速度提升了大约15%。第二步是量化用ONNX Runtime的静态量化工具把FP32转成INT8。量化需要校准数据我从训练集里抽了500张图片做校准。量化之后模型大小从16MB降到了4MB推理延迟从45毫秒降到了18毫秒准确率只掉了0.6个百分点非常划算。第三步是服务封装用FastAPI写了一个HTTP接口接收图片base64编码返回类别和置信度。服务启动时加载模型常驻内存。并发处理用uvicorn的多worker模式开了4个worker。第四步是监控埋点每个请求记录请求ID、时间戳、推理延迟、输入图片尺寸、输出类别、置信度。这些数据写到日志文件然后用Prometheus采集Grafana做可视化。另外还加了一个数据漂移监控定期统计输入图片的均值和方差跟训练集对比偏差超过阈值就告警。最终上线后的实测数据平均延迟22毫秒P99延迟58毫秒吞吐量在4核8G的机器上能达到每秒120次请求完全满足了业务要求。5. 常见问题与排查技巧实录5.1 训练阶段的典型问题问题一loss不下降或者震荡。这是最常见的问题排查顺序是这样的先检查数据有没有问题比如标签是不是对的、输入归一化有没有做然后检查学习率是不是太大试着调小一个数量级再检查模型初始化是不是有问题可以换成标准的初始化方法最后检查损失函数是不是用对了比如多分类用交叉熵、二分类用BCE。问题二显存不够用OOM。解决方案按优先级排先减小batch size这是最直接的然后开启混合精度训练能省大约40%显存再检查有没有不必要的中间变量没释放比如在训练循环里累积了loss列表最后考虑用梯度累积来模拟大batch或者用梯度检查点来省显存。问题三训练速度慢。先看GPU利用率如果低于70%说明数据加载是瓶颈调大num_workers或者把数据预处理放到GPU上做如果GPU利用率很高但速度还是慢检查是不是模型太大或者batch size太小另外混合精度训练能显著提速建议默认开启。5.2 推理部署阶段的典型问题问题一推理延迟波动大。常见原因是请求的输入尺寸不一致导致每次推理的计算量不同。解决方案是在预处理阶段统一resize到固定尺寸或者用动态shape的推理引擎。另外如果服务是多worker的要注意worker之间的负载均衡。问题二量化后精度掉太多。说明校准数据不够有代表性或者某些层的量化敏感度太高。解决方案是增加校准数据的数量和多样性或者对敏感层保持FP32精度只量化其他层。ONNX Runtime支持混合精度量化可以精细控制哪些层量化、哪些不量化。问题三服务内存持续增长。这通常是内存泄漏常见原因是请求处理过程中创建的对象没有及时释放或者日志文件没有轮转导致越来越大。排查方法是定期打印内存使用情况用memory profiler定位泄漏点。另外Python的GC有时候不够及时可以在请求处理完后手动触发一次。5.3 我踩过的几个印象深刻的坑第一个坑数据泄露。有一次做数据增强的时候我把增强后的图片同时放进了训练集和验证集导致验证集准确率虚高上线后效果差了一大截。后来我养成了一个习惯数据增强只在训练时做验证集和测试集绝对不做增强而且划分数据集要在增强之前做。第二个坑版本不一致。训练的时候用的是PyTorch 1.12部署的时候环境里装的是1.13结果导出的ONNX模型推理结果对不上。后来我强制要求训练和部署环境用同一套依赖版本并且用Docker把环境固化下来。第三个坑监控缺失。有一次线上服务突然变慢但因为没有监控数据排查了两天才发现是某个类别的输入图片尺寸特别大导致预处理耗时暴增。从那以后我强制要求所有服务必须加监控而且监控指标要覆盖输入、处理、输出全链路。5.4 常见问题速查表问题现象可能原因排查方法解决方案训练loss不下降学习率过大/数据有问题打印梯度范数、检查数据标签调小学习率、清洗数据验证loss上升过拟合对比训练和验证曲线加正则化、增加数据显存OOMbatch size过大打印显存占用减小batch、混合精度推理延迟高模型太大/未优化profile各阶段耗时量化、算子融合量化后精度掉校准数据不足对比量化前后指标增加校准数据、混合量化服务内存泄漏对象未释放定期打印内存手动GC、检查日志轮转6. 从零构建之后下一步往哪走走完上面这条路线你基本上已经具备了独立设计和落地一个AI系统的能力。但AI工程这个领域变化很快新的模型架构、新的推理框架、新的部署方案层出不穷所以持续学习是必须的。我自己的做法是保持对几个方向的关注一是模型压缩技术的新进展比如稀疏化、知识蒸馏二是推理引擎的更新比如TensorRT和ONNX Runtime的新版本特性三是MLOps工具链的演进比如实验管理、模型注册、自动化部署这些环节的新工具。另外我强烈建议你养成写项目复盘的习惯。每做完一个项目花半天时间把整个过程梳理一遍哪些地方做得好、哪些地方走了弯路、如果重来一次会怎么改进。这些复盘记录积累下来就是你最宝贵的经验资产。我带新人的时候最看重的不是他掌握了多少工具而是他有没有自己的方法论和踩坑记录——因为工具会过时但方法论和踩坑经验是通用的。最后分享一个我自己的小技巧每次学一个新东西不要只看文档和教程一定要找一个真实的小项目从头到尾做一遍。哪怕这个项目很简单比如做一个手写数字识别服务只要你把数据、训练、优化、部署、监控这整条链路都走通了你对AI工程的理解就会比只看书深得多。我自己就是这么一步步走过来的踩过的坑不少但每一个坑都让我对这套东西的理解更扎实了一层。
返回列表