
做AI工程一年半从连CUDA是什么都不知道到手里两个OCR服务稳定扛着线上流量我想把这条从零起步的路仔细拆一遍。这个标题太容易引发误会了——很多人以为AI工程的开端是学Transformer是啃反向传播公式后来又以为AI工程就是调参炼丹再后来发现是在Docker里跟CUDA版本缠斗。实际上这三层全是却又远不止于此。这篇文章是写给打算入行、或者正在学了一堆AI理论却落不了地的读者的。我不会讲什么宏大的行业趋势只讲一件事按照一个合理顺序把AI工程这座山翻过去。你会发现它是一条由无数细碎工程问题串联起来的路知识点不是学完再去用而是用到哪学到哪。1. AI工程的门槛到底拦在哪儿——先搞清楚自己学的是AI还是工程1.1 会训练模型和会做AI工程之间隔着一整条流水线我最早也想过这个问题AI工程的重心应该放在模型上吧毕竟AI两个字摆在前面。这个直觉害人不浅。假设你在Jupyter Notebook里用一套公开数据集训练了一个图像分类模型准确率97%看起来一切顺利。但AI工程师的工作不是在这块Notebook里结束的而是从把模型机部署到生产环境才算刚开始。这个过程中你会连续撞上这些问题模型文件几百兆线上服务加载一次要好几秒单机QPS上不去一百部署环境的GPU驱动和CUDA版本不匹配服务起不来训练时候的预处理逻辑和线上推理的预处理逻辑差一行代码线下97%的准确率到了线上直接跌破80%数据分布变了模型在用户真实场景下开始犯错但你没有任何监控告诉你它开始犯错了产品提了一个新需求要识别新的类别你得重新标注数据、重新训练、重新上线整个流程要跑三天。所谓AI工程本质上是把模型当做一个软件组件去解决它从训练到上线到迭代的这个完整生命周期问题。模型训练只是其中一环就像盖房子打地基很重要但你不能只打地基。1.2 AI的软件工程系统工程双重身份我自己的体会是AI工程是软件工程和系统工程的交叉。软件工程的一面包括代码结构、接口设计、测试和CI/CD系统工程的一面包括GPU资源管理、分布式训练、推理延迟和吞吐优化、服务稳定性。只擅长任何一边都不够。举个例子我写过的一个OCR服务端最耗时间的不是模型推理那个几十毫秒而是图片前处理——读取、解码、缩放这些步骤在CPU上做一并发上来CPU飙升。后来把图片解码换成了更快的库加了缓存和批处理整个服务吞吐翻了一倍。这哪是AI问题这纯粹是系统工程问题。但用户看到的就是这个AI服务卡不卡。绝大多数线上AI服务的性能瓶颈恰恰出在这些工程细节上而不是模型参数量够不够大。这一点你越早意识到走的弯路越少。1.3 为什么说从零开始最好的路线是学一个端到端项目理论先行还是项目先行争论不休。以我带过新人的实际经验判断对AI工程来说端到端项目先行的效率远高于理论先行。原因是这个领域知识密度实在太高——数学、编程、系统、框架、云平台全要涉及。如果按学科顺序学你至少花一年时间才能触碰到工程这个边界。但如果你上来就做一个端到端项目比如把一张手写发票照片变成结构化文本你会发现自己需要的东西立刻浮出水面得会Python处理图像、知道怎么装PyTorch、能读懂OCR模型文档、能写个API接口、还得部署到服务器上。每一个缺口都会逼迫你立刻去补。这种以项目为索引、反向学习的方式才是从零开始最务实的展开方式。下面的技术栈拆解我也不按学科来而是按一条真实的AI工程链路来排。2. 一张技术栈全景图——把从零开始拆成三条递进路线AI工程的知识体系我习惯拆成三层AI基础层、AI系统层和AI落地层。很多人学到一半放弃是因为一直在第一层打转从没抬头看第二、三层。2.1 第一层模型能力——不需要从数学深渊游过去首先声明一个观点学习AI工程把数学重修一遍是最低效的做法。你需要的是够用的数学直觉不是数学证明能力。理解梯度下降是在沿着下山最快的方向迈步就够了不需要在第一次接触时就亲手推完整个反向传播公式。具体知识清单如下Python编程能做数据处理、循环判断、函数封装读文件能用Pandas做基本表格处理机器学习基础明白回归、分类、聚类的基本概念理解训练集和测试集分离的意义深度学习框架PyTorch优先TensorFlow除非公司强制否则不建议新人入手。你需要搞清楚Tensor的shape流转、Dataset/DataLoader的用法而不是急着搭一堆没必要的自定义层预训练模型的使用会用Hugging Face的Transformers加载BERT、ViT这类预训练模型进行微调。到这里已经具备训练一个基础模型的能力了。注意这一层我强调的是使用而不是发明。2.2 第二层系统能力——决定模型能否跑起来的生存技能这一层经常被完全忽视却是AI工程和纯算法岗最显著的差异所在Linux服务器操作能力文件权限、环境变量、进程管理、ssh远程操作、日志查看这些都是日常动作Docker容器把训练环境和推理环境打包成镜像保证在谁机器上跑结果都一样。只用docker run是不够的得会写Dockerfile、会解决基础镜像依赖问题GPU基础搞清CPU和GPU分工的边界会看nvidia-smi的输出理解显存与批大小的关系能排查CUDA版本和驱动不匹配的问题数据管线从爬取/收集、清洗、格式转换到标签校验和增强这一步占整个工程耗时不低于40%。很多人低估数据工作实际上数据质量直接决定模型上限版本管理Git是基础LFS用来管理大文件DVC这类工具用来管理数据集和模型版本。没有这一层你训练出来的模型只是一坨跑得起来的代码离产品还有巨大距离。2.3 第三层落地能力——从模型到产品服务的最后一公里这一层决定你的成果能否真正创造价值也是AI工程师和AI研究员分道扬镳的分水岭模型转换与加速把PyTorch模型转为ONNX配合TensorRT或ONNX Runtime推理引擎把首延迟从几十毫秒压到个位数毫秒推理服务封装用FastAPI写HTTP接口做好输入校验、超时控制、并发管理性能评测与压测会用Apache Bench或wrk做简单压测关注QPS、P99延迟、显存占用这些指标模型监控与迭代线上模型需要日志、指标追踪、数据漂移检测形成数据回流闭环部署运维至少掌握一种云平台或容器平台的部署方式能够配置健康检查、环境变量和有限的自动扩缩容策略。这三层模型能力、系统能力、落地能力不是选修关系而是层层依赖关系。最常见的从零半途而废路径是在第一层学了三个月理论结果因为第二层不会配环境第一个像样的实战项目始终跑不起来于是自我怀疑我不适合学AI。3. 从零搭一套能跑的实验环境硬件、软件与数据集三件套关于硬件先说结论学习期没必要一上来买昂贵的GPU。一台普通笔记本电脑就能完成环境搭建入门绝大多数开源模型在CPU上只是跑得慢不是跑不起来。当你真的开始做规模化训练或部署时再考虑云GPU按需租用这是性价比最高的方案。3.1 硬件选择的现实考量我见过太多人一开始就纠结4090还是A6000其实这是典型的工具导向思维。真实情况是学习探索阶段第一次跑通模型、理解训练流程普通电脑CPU足够慢一点就慢一点反正重点是流程理解小规模训练阶段微调一个中小尺寸模型租一块云GPU按小时计费用完即停生产部署阶段按线上QPS和延迟需求推算需要的GPU数量初期可以只配一台带单卡的服务器起步。如果你真想买卡预算有限时也不用一步到位。学习期的关键不在于显卡多强而在于能持续动手。显卡只是加速器不是魔法棒。3.2 软件栈的标准起步组合我推荐直接用Anaconda管理Python环境再装PyTorch和Transformers。这是目前资料最丰富、问题搜得到中文解答的组合。别一开始就掉进源码编译的泥坑那是进阶之后的事。另外Docker建议尽早装。你不需要一开始就理解它的一切但至少学会一件事用官方PyTorch镜像起一个容器把代码和数据集挂载进去跑。这样你就绕开了90%的在我电脑上是好的这种环境问题。# 拉取PyTorch官方镜像CPU版适合起步阶段 docker pull pytorch/pytorch:2.0.0-cpu # 启动容器并挂载本地工作目录 docker run -it --name ai-env \ -v $(pwd)/projects:/workspace/projects \ pytorch/pytorch:2.0.0-cpu bash我所有的新手训练营第一天只干这件事让每个人起好容器跑一个最简单的图像识别Demo。谁能在这一天之内跑通后面的学习节奏都是良性的。3.3 数据集选择策略宁缺毋滥先小后大数据集这一步是有大坑的。很多人一上来就找了十几个GB的公开数据集然后发现下载花了一天、解压花了两小时、批量读取再花一下午最后还没开始训练就已经筋疲力竭了。正确的做法是先找一个小体量但结构完整的数据集。比如图像分类CIFAR-10或MNIST几百MB以内任务清晰OCR识别放几张真实拍摄的证件照片、发票照片批量图片做个几十张起步完全够第一次跑通流程文本分类拿新闻数据跑个主题分类理解Transformer在文本上的用法。小数据集的价值在于让训练-评估-调试的代码循环转起来。数据规模可以后面逐步扩大数据处理流程一旦成型换数据集只是改个路径的事。4. 跑通一条AI工程主线OCR项目从数据到部署的全链路理论说再多都不如亲手跑通一条完整链路来得踏实。我以OCR为例因为它覆盖了图像预处理、模型微调、推理优化、服务封装、性能压测整个AI工程核心环节。这个案例是我实操过的完全可以直接照做。4.1 数据准备从图片进来到能喂给模型OCR项目的第一步永远是整理数据。网上找公开OCR数据集或者自己拍照片都可以关键是建立如下目录结构ocr_project/ ├── data/ │ ├── raw/ # 原始图片 │ ├── labels/ # 标注文件json/txt │ └── processed/ # 处理后的标准格式 ├── src/ │ ├── preprocess.py # 预处理脚本 │ ├── train.py # 训练脚本 │ ├── infer.py # 推理脚本 │ └── api.py # FastAPI服务 ├── models/ # 保存权重 └── Dockerfile如果你的标注文件还不是统一格式先花时间写个转换脚本。这步看着枯燥实则是整个项目最关键的环节——模型训练遇到问题八成问题出在数据格式不统一上。4.2 预处理一个微不足道却决定成败的环节OCR的预处理逻辑是积分转灰度、缩放、去除噪声、矫正方向每一步都影响识别效果。而且训练时的和推理时的处理逻辑必须完全一致编码同一份代码否则就是众所周知的训练线上不一致问题。这里必须坚持一个原则写一个preprocess.py函数训练脚本和推理服务都import它而不是各自复制一份。# preprocess.py import cv2 import numpy as np def preprocess_image(img: np.ndarray, target_size(512, 512)) - np.ndarray: img cv2.cvtColor(img, cv2.COLOR_BGR2GRAY) img cv2.resize(img, target_size, interpolationcv2.INTER_AREA) img img.astype(np.float32) / 255.0 img np.expand_dims(img, axis-1) return img这段代码没有讲任何高深知识但如果你训练时用了一张RGB图推理时却拿到BGR图后面的一切再好也是白搭。像这种细节实战中我会专门安排一个冒烟测试来验证一致性。4.3 训练/微调用预训练模型而不是从零开始对于大多数实际任务从零训练一个OCR模型毫无必要。用现有的预训练模型做微调是最务实的选择。以文本识别为例加载一个开源的CRNN或TrOCR模型在自有数据集上跑几个epoch就够了。训练脚本的核心骨架大概是这样from transformers import TrOCRProcessor, VisionEncoderDecoderModel processor TrOCRProcessor.from_pretrained(microsoft/trocr-base-printed) model VisionEncoderDecoderModel.from_pretrained(microsoft/trocr-base-printed) # 你的训练循环 # 1. 读取图片 - preprocess_image - processor # 2. 输出文本与标注文本算交叉熵损失 # 3. 反向传播保存最佳权重注意一个细节批次大小batch size的选择要结合显存大小。8GB显存上batch size大于16大概率OOM显存溢出。报错后别慌先把batch size减半试试。这个看起来很小的参数却是GPU奔溃报告的核心主角。4.4 推理优化从PyTorch到ONNX到TensorRT模型训练完只是成果的一半。原始PyTorch模型直接部署推理延迟经常会高到无法接受。我的习惯是走一遍PyTorch - ONNX - TensorRT的优化链路。ONNX格式的价值在于它是跨框架的中间表示发布时不用把整个PyTorch环境带上去TensorRT则能用层融合、精度校准等手段把模型压得更快。实际经验中OCR模型从PyTorch到TensorRT推理延迟降低40%~70%是很普遍的。import torch import torch.onnx # 导出ONNX dummy_input torch.randn(1, 3, 512, 512) torch.onnx.export( model, dummy_input, ocr_model.onnx, input_names[input], output_names[output], dynamic_axes{input: {0: batch_size}, output: {0: batch_size}}, opset_version17 )设置dynamic_axes是为了允许推理时batch size可变否则部署时只能固定一次处理一张图。这个参数新手经常忽略后续上生产时必然会回来改。4.5 服务化用FastAPI把模型变成接口服务本身不复杂重点是稳定性设计。推荐用FastAPI简洁且自动生成接口文档。from fastapi import FastAPI, UploadFile from preprocess import preprocess_image import onnxruntime as ort app FastAPI() session ort.InferenceSession(ocr_model.onnx, providers[CUDAExecutionProvider]) app.post(/ocr) async def ocr(file: UploadFile): image_bytes await file.read() img preprocess_image(image_bytes) result session.run(None, {input: img})[0] return {text: decode_output(result)}上传接口务必做大小限制和异常捕获。生产环境里大量诡异的服务崩溃其实都是用户上传了一张超大图或者损坏的图片文件没有捕获异常导致进程直接退出。这一类防御性编码细节是线上可靠性的分水岭。4.6 性能压测与调优别让你的服务在流量面前裸奔上线前不做压测等于裸奔。用wrk做一个简单压测wrk -t4 -c100 -d30s http://127.0.0.1:8000/ocr看两个核心指标QPS每秒能处理多少请求和P99延迟99%的请求在多少毫秒内返回。如果QPS上不去优先排查瓶颈在哪——是CPU做图像解码慢还是GPU推理满还是API的Python解释器GIL锁限制就我自己那个OCR服务第一轮压测QPS只有预期的一半。逐层排查后定位竟然是图像解码全部压在CPU上后台线程池一满瓶就直接卡住。后来改用更快的解码库并把解码操作放到消息队列异步处理吞吐立刻翻倍。这一实践经验说明很多AI服务性能差的根源根本不在模型本身而在工程环节的配合是否流畅。5. AI工程学习路线中我踩过的坑以及六条自查清单走完整条链路之后你会发现不知道学什么慢慢变成踩过的坑要扫清。下面这些坑几乎每个AI工程新人都躲不掉写出来给你做避雷参考。5.1 五个高频翻车现场数据集泄漏训练集和验证集混用了同来源照片验证准确率虚高。真实业务场景一上立刻现形。解决思路是严格按样本来源切分不要按文件名随机切。预处理不一致训练时RGB、推理时BGR这种类型问题最不想排查因为错误出来的效果完全没规律。你的保险就是共用预处理函数。环境漂移这个模型在Python 3.8下跑出来的结果跟Python 3.10下不一样了。核心依赖要锁版本镜像要打标签留档。指标不对齐训练时的准确率跟线上效果指标不是一回事。你用字符级准确率训练线上却按整行精确匹配评估结果当然落差巨大。要在项目开始时就明确定义线上评测指标。欠拟合业务模型在测试集上很理想真实数据却稀烂。原因往往是真实数据里包含了大量你数据清洗时顺手洗掉的困难样本。保留一些与线上分布更接近的困难样本是评测之外很重要的补充。5.2 六条自查清单做完任何一个AI项目上线前走一遍这条清单可以拦住绝大多数翻车训练和推理是否共用同一份预处理代码训练集和验证集是否按业务来源切分关键依赖是否有明确版本锁定接口是否有输入校验和异常捕获压测指标QPS、P99延迟、显存占用是否达标线上是否有日志、监控、数据回流机制这六条看起来平平无奇但照着做能躲掉至少80%的线上故障。我把它贴在工位上每次发版前从头过一遍。5.3 为AI工程长期主义做的保留项目最后想聊一个认知层面的东西。AI工程这个领域变化太快新的框架、新的模型、新的工具层出不穷。今天学的工具可能三个月后又出现更优的替代品。所以我不建议把精力全投在追新上。更好的策略是把规律性知识学扎实剩下的工具层面随用随学。规律性知识指的是数据质量决定模型上限、训练与推理的一致性设计、性能瓶颈的可观测性排查思路、先小后大的迭代节奏。掌握了这一层换个工具、换套框架需要的仅仅是重新熟悉接口的时间不存在从头再学的风险。我个人从实践里得到的最大体会AI工程拼的从来不是谁的模型更先进而是谁的链路更完整、更不容易出故障。一个用中等模型但工程质量扎实的系统远比一个模型很炫但一上线就崩的系统有价值得多。最后再分享一个小技巧尽量给自己建一个AI工程工具箱把所有同一个功能反复用到的脚本、Dockerfile、预处理函数、压测命令统一整理起来。换新项目时直接从工具箱里拼装效率提升很可观。学AI工程这条路前三个月最苦但只要完整跑通第一个端到端项目后面的路会越走越顺畅。