☰
AI工程从零到一:数据、模型、部署与MLOps全链路实践
2026/11/3 14:41:44 网站建设 项目流程

1. 项目概述:AI工程“从零开始”到底是什么意思

先说结论:ai-engineering-from-scratch不是一门课,也不是某个开源仓库的名字,而是一整套从零搭建 AI 工程能力的学习与实战路径。很多人听到 AI 工程师,第一反应是“会训练模型”“懂调参”“会写 Python 调用 OpenAI SDK”,但实际上,AI 工程是一个比这宽得多的领域。它覆盖数据管线的搭建、模型训练与评估、实验管理、模型部署、监控运维、成本控制,甚至还包括团队协作和代码规范。

这个项目最适合三类人:第一类是刚入门机器学习、被各种教程膨胀到不知道从哪里下手的学习者;第二类是已经在做算法或数据相关工作、但还没有接触过“工程化”的开发者和数据科学家;第三类是那些想从“能跑 demo”进阶到“能上线系统”的人。这三类人的共同痛点,不是因为不知道某个算法怎么实现,而是不知道一个完整的 AI 工程项目从开始到落地到底要经历哪些环节,每个环节又需要什么样的取舍。

我最早意识到这个问题,是带一个实习生做图像分类项目的时候。他花了三周把 ResNet 的准确率从 89% 调到 92%,然后我们准备把它接进公司内部的一个工单系统。结果发现:模型训练时的输入尺寸是 224x224,但线上传过来的图片有长有短;训练的代码里写死了本地文件路径;没有做版本管理,模型文件就叫model_final.pth,后面又变成model_final_really.pth。准确率很好看,但一旦要上线,到处都是坑。这个经历让我重新理解了“AI 工程”这四个字的分量。

所以这篇内容就是围绕这样一个“从零到一”的完整路径展开。我会从能力模型、基础实操、工程化落地、常见问题四个维度,把自己这几年踩过的坑、验证过的方案、总结出的方法一遍讲透。适合把所有章节看完之后照着走一遍,而不是只挑自己感兴趣的部分看。

2. 能力模型拆解:AI 工程需要哪些硬核技能

2.1 不要把算法和工程混为一谈

先从最基础的一点说起:AI 工程不是只会调库调参就行。很多初学者最大的误区,是把 AI 工程师等同于“炼丹师”——会导入torchvision.models.resnet50,会写一个训练循环,会调 learning rate,就觉得自己会 AI 工程了。这就像说会用微波炉热菜就等于会做饭一样,加热只是最后一个动作,前面还差着买菜、洗菜、备菜、调味、火候掌控一大堆活儿。

在真实的 AI 工程项目里,模型训练只占整个工作量的 30% 左右。剩余的时间里,你可能在处理脏乱的数据格式,可能在排查线上写 XGBoost 输出的结果与线下结果不一致的问题,可能在为节省一半的 GPU 显存而重构数据加载逻辑,也有可能在为模型能稳定支撑每秒几百个请求而调整推理服务端的批处理策略。

以数据管线为例。真实场景中的数据,极少会像 Kaggle 上那样已经被清洗得干干净净。我在一个用户行为预测的项目里,需要融合点击日志、订单记录和商品 Metadata,光是统一时间戳的格式就花了整整两天。点击日志里时间一般是 Unix 毫秒,订单记录里是字符串"2024-03-21 14:22:01",商品 Metadata 里又是 Excel 导出的日期序列号。每份数据单独看都是精心制作的,合并起来却是一场灾难。

2.2 五项核心能力,缺一块都不行

如果把我认为 AI 工程师必须具备的能力做成清单,可以浓缩成五项:

  1. 数据处理与 ETL 能力:会使用 Pandas、SQL、Spark 或 DataFrames API 进行数据清洗、特征构造、数据校验。这不是简单的df.dropna()就够用的,关键是能快速理解数据里的业务含义,能设计出不丢失信息的特征表示方式,并且能保证处理过程可复现。

  2. 模型训练与调优能力:不只是会调用某个现成模型接口,而是能根据数据量级、业务目标、计算资源来选择方案。数据量小的时候是用传统机器学习还是用小模型微调?数据量大的时候分布式训练怎么设计?过拟合怎么识别和缓解?这些都要求你真正理解算法背后的原理,而不是只会 GridSearch。

  3. 实验管理与版本化能力:你得知道今天是哪份数据、哪段代码、哪个超参数组合产出这版模型的。Git 管代码,DVC 或类似工具管数据,MLflow 或 W&B 管实验参数和模型 artifact。这套体系能保证你三个月后还能定位到“为什么那版模型的线上效果更好”。

  4. 模型部署与服务化能力:会把训练好的模型转成可对外提供的服务。这里涉及模型导出格式(ONNX、TorchScript、PMML 或纯 Pickle)、推理框架(Triton、TorchServe、FastAPI + ONNX Runtime)、容器化与编排(Docker、Kubernetes)。你还得知道怎么量化、剪枝,把模型压到能满足线上延迟要求的体积。

  5. 监控、日志与迭代能力:模型上线不是终点。输入数据分布发生变化怎么办?线上效果怎么评估?预测结果能不能回溯?要有监控指标的设计方案,有告警和异常检测机制,还要有 grep 日志快速定位线上 bug 的经验。

刚才说的这五项能力,并不是要你每一项都成为专家,但至少要达到“能独立走通全流程”的熟练度。项目是串行推进的,每一项卡住都会让整个链路卡住。

2.3 编程基础:Python 以外还要掌握什么

Python 是 AI 工程的主语言,这点毋庸置疑。但你绝不能只停留在语法层面。在实际工程中,我强烈建议至少把下面这几个方面的基本功打扎实:

  • Python 性能优化基础:学会用multiprocessing或concurrent.futures做并行处理,理解 GIL 对 CPU 密集任务的影响,会使用numpy的向量化操作代替显式 for 循环。大数据量下这些差距是几何级的。
  • Linux 与 Shell:训练任务经常跑在远程服务器上,你需要会用 tmux 或 screen 保持会话,会用nohup和日志重定向,会用nvidia-smi查看 GPU 状态,会用df -h检查磁盘空间。很多时候线上出问题,第一个发现异常的就是 Shell 命令和日志。
  • Git 协作规范:不只是会git commit,要理解分支管理、Code Review 流程、怎么处理冲突、怎么保持提交粒度合理。我在代码评审里见过最头痛的,是有人把调试代码和业务逻辑混在一个 commit 里,review 根本没办法进行。
  • 基础容器概念:Docker 不用精通,但能看懂 Dockerfile 里每一行在干什么,知道怎么构建镜像、怎么把端口暴露出来、怎么挂载数据卷,这已经能覆盖 80% 的 AI 工程场景。

这些基本功每一项看起来都不复杂,但它们是后续所有环节的地基。地基不牢,后边每个阶段都会用隐性方式给你“还账”。

3. 起步实操:搭建环境并跑通第一个端到端项目

3.1 环境准备:从零构建一套可复现的 AI 开发环境

如果你连 Python 环境管理都没有搞定,后面的所有实操都会变得混乱。我在这个项目里推荐的环境方案是:使用conda管理 Python 环境,使用pip安装包,使用 Docker 做环境固化与交付。三个工具各司其职,并不冲突。

# 创建独立的 Python 3.11 环境 conda create -n ai-engineering python=3.11 -y conda activate ai-engineering # 安装核心依赖 pip install torch torchvision --index-url https://download.pytorch.org/whl/cu121 pip install pandas numpy scikit-learn matplotlib jupyter pip install mlflow dvc pip install fastapi uvicorn onnxruntime

为什么用 conda 而不直接用系统 Python?因为项目与项目之间的依赖版本冲突太常见了。这个项目要 PyTorch 2.x,那个项目要 TensorFlow 1.15,还有的项目要在 Python 3.8 环境下跑老代码。conda 能做到环境级别的隔离,比 virtualenv 在处理一些带原生扩展的库时更省心。

另外两个容易被忽略但直接影响开发效率的点。第一个是.gitignore必须把虚拟环境目录、数据集目录、模型权重目录、日志文件全部排除掉,否则仓库会迅速膨胀且无法溯源。第二个是建议在一开始就把requirements.txt用pip freeze > requirements.txt生成清楚,而不是每次装个包就更新一次,否则后期回溯环境会把自己气死。

3.2 数据准备与特征工程:以房价预测为例

为了不让理论悬空,我在这里用一个非常经典、又很适合展示完整工程流程的示例:房价预测。这个任务的业务含义清晰,数据量适中,且涉及数值特征、类别特征、缺失值、异常值等常见问题,是练手的绝佳选择。

数据准备阶段的核心是一个理念:把数据处理写成可复制的脚本,而不是在 Notebook 里点一个单元执行一次。我见过太多人在 Jupyter 里各自动手清洗数据,结果每人得到的数据版本都不一样。到模型融合阶段就完全没法对账。

按照工程化思路,数据准备应该拆成三步:

  1. 数据探查:先不急着处理,把数据读进来,用df.info()、df.describe()、df.isnull().sum()观察基本情况。对异常值,不能只看数值,还要结合业务理解—比如房价数据里面积是 0 或者总价是 0,这显然代表缺失而非真实值。

  2. 清洗与构造:用 Sklearn 的ColumnTransformer统一处理数值列和类别列。数值列用SimpleImputer填充中位数,再做StandardScaler标准化;类别列用OneHotEncoder编码或OrdinalEncoder处理有序类别。特征构造上可以加一些业务理解的组合特征,比如房龄与装修档次的交叉项,或者单位面积价格是否偏离周边合理区间的虚拟变量。

  3. 数据拆分与固化:严格按时间顺序或者随机种子拆分训练集、验证集、测试集,并把拆分后的三个数据集落到磁盘上的固定目录。拆分的过程必须记录随机种子,因为后续所有实验都要基于完全相同的训练集和验证集进行,否则模型对比就没有意义。

# 数据预处理管线示例 from sklearn.compose import ColumnTransformer from sklearn.pipeline import Pipeline from sklearn.impute import SimpleImputer from sklearn.preprocessing import OneHotEncoder, StandardScaler numeric_features = ["area", "bedrooms", "bathrooms", "age"] categorical_features = ["location", "furnishing"] numeric_transformer = Pipeline(steps=[ ("imputer", SimpleImputer(strategy="median")), ("scaler", StandardScaler()) ]) categorical_transformer = Pipeline(steps=[ ("imputer", SimpleImputer(strategy="most_frequent")), ("onehot", OneHotEncoder(handle_unknown="ignore")) ]) preprocessor = ColumnTransformer(transformers=[ ("num", numeric_transformer, numeric_features), ("cat", categorical_transformer, categorical_features) ])

这一套写下来的一小时代价,能为你省下后面模型实验中的大量返工时间。

3.3 模型训练与实验追踪:第一次用 MLflow 记录一切

模型训练在工程上的核心问题不是“怎么把准确率调高”,而是“怎么知道当前版本比上一版本好,并且能随时复现这个结果”。解决方法是引入 MLflow Tracking。

用 MLflow 的原因有三个:第一,它开源且轻量,一段mlflow.start_run()就可以接进现有代码;第二,它的 UI 能直观对比多次实验的指标;第三,它能把参数、指标、模型 artifact 和代码版本自动关联起来,真正解决“这是哪个跑出来的”的问题。

import mlflow import mlflow.sklearn from sklearn.ensemble import RandomForestRegressor from sklearn.metrics import mean_absolute_error, mean_squared_error mlflow.set_tracking_uri("file:///home/user/mlruns") mlflow.set_experiment("house_price_prediction") with mlflow.start_run(): params = { "n_estimators": 300, "max_depth": 12, "min_samples_split": 5, "random_state": 42 } model = RandomForestRegressor(**params) model.fit(X_train, y_train) y_pred = model.predict(X_valid) mae = mean_absolute_error(y_valid, y_pred) rmse = mean_squared_error(y_valid, y_pred, squared=False) mlflow.log_params(params) mlflow.log_metrics({"mae": mae, "rmse": rmse}) mlflow.sklearn.log_model(model, "model")

跑完这一次实验之后,你可以在 MLflow UI 里看到这次运行的参数、指标和产出的模型文件。后面每调一次参数,又多一条记录。对比两条记录的指标,就能清楚地知道变化方向。这个习惯一旦养成,你的调参路径就从“靠感觉”变成“有据可查”。

3.4 模型评估:不要只盯着一个指标

在房价预测这个任务里,RMSE 和 MAE 是最常用的两个评价指标,但它们代表的含义完全不同。RMSE 对大误差更敏感,如果你的模型在少数高价房上预测偏差巨大,RMSE 会显著升高;MAE 则更鲁棒,不会因为少数极端样本而大起大落。一个合格的做法是两个都看,再结合业务视角评估误差分布。

什么叫结合业务视角?如果这个模型是用来给银行做抵押贷款额度参考,那么你更在意的是不要让预测值严重高估房价,因为高估意味着更大的风险敞口。此时看误差分布的尾部情况、看高价位段的相对误差比看单一 RMSE 更有价值。你不能只跟模型较劲,要跟业务目标对齐。

我自己还会额外画两张图:预测值与真实值的散点图、误差随预测值变化的分布图。前者能看出是否存在系统性偏移,比如模型系统性低估高房价;后者能发现模型在哪一段表现最差,往往那一段就是下一步特征工程的重点方向。

4. 进阶工程化:MLOps 与模型上线全链路

4.1 为什么工程化链路经常断在“交接”上

从训练到生产,最典型的失败模式是企业里有算法团队把握模型训练,有后端团队负责服务开发,两边各做各的,然后在模型交接时频繁扯皮。算法说“模型文件我发你了,你直接用就行”,后端说“你给的文件格式不对,我们这边没法加载”。问题的根源在于,算法团队交付的是一个.pkl文件或不完整的模型说明,而没有交付一个“可复现的制品包”。

工程化的思路是,把训练后的模型连同它的预处理逻辑、依赖环境、输入输出格式、示例调用代码一起打包。模型不是一个孤立的权重文件,而是一个自包含的服务单元。以下总结一个我在项目里验证过的模型交付清单:

交付物说明必须包含的内容
模型权重文件训练产出的模型参数权重文件、模型结构代码或导出后的格式文件
预处理配置与训练时一致的预处理逻辑特征列顺序、填充值、scaler 参数、编码器映射
依赖清单运行环境所需第三方库requirements.txt 或 conda env.yaml
API 定义模型服务的输入输出协议请求字段说明、响应格式、错误码约定
示例调用一秒钟能跑通的调用示例curl 命令或 Python 脚本
评估报告模型在验证集上的表现摘要评估指标、受限范围、已知缺陷

只有把清单上的每一项都补齐,交付才算完成。任何一项缺失,后续接手的工程师都需要用额外的时间和线上的故障来补齐。

4.2 模型导出:从 PyTorch/Sklearn 到 ONNX Runtime

训练用的模型框架和线上推理用的框架经常不是同一个。PyTorch 训练好一个模型,直接用 TorchServe 部署当然没问题,但当服务端并发升高、需要多模型混合调度时,ONNX Runtime 往往是更中庸高效的选择。它不绑定某一个深度学习框架,而是把模型转换为一种统一的中间表示,推理性能在 CPU 和 GPU 上都不错。

以房价预测模型为例,Sklearn 的模型导出 ONNX 已经非常成熟:

from skl2onnx import convert_sklearn from skl2onnx.common.data_types import FloatTensorType initial_type = [("float_input", FloatTensorType([None, X_train.shape[1]]))] onnx_model = convert_sklearn(preprocessor_and_model, initial_types=initial_type) with open("house_price_model.onnx", "wb") as f: f.write(onnx_model.SerializeToString())

导出后的 ONNX 文件可以直接被 ONNX Runtime 加载推理,速度比纯 Sklearn predict 快数倍。这里有一个容易踩的坑:预处理管线必须和模型一起导出,而不是把预处理留在外部 Python 代码里单独执行。否则线上推理解释不好,pipeline.predict()里的内部变换顺序一旦与训练不一致,效果会断崖式下跌。

对于 PyTorch 模型,更推荐的做法是先转成 TorchScript 或 ONNX。TorchScript 的好处是保留动态图的灵活性,但部署时最好直接序列化一个静态图。torch.onnx.export需要指定输入尺寸的 dummy input,dynamic_axes参数如果需要动态 batch 必须显式声明,否则默认 batch 维度会被固定,线上服务一次只能预测一个样本,并发能力大打折扣。

4.3 服务化封装:FastAPI 写一个能扛住真实流量的推理服务

模型导出来后,下一步是封装成 HTTP 服务。FastAPI 是当下 AI 工程的主流选择。它基于 Starlette 和 Pydantic,性能在纯 Python 框架里属于第一梯队,同时自带请求参数校验和自动生成 API 文档,对团队协作非常友好。

import onnxruntime as ort import numpy as np from fastapi import FastAPI from pydantic import BaseModel app = FastAPI(title="House Price Prediction Service") sess = ort.InferenceSession("house_price_model.onnx", providers=["CPUExecutionProvider"]) class HouseInfo(BaseModel): area: float bedrooms: int bathrooms: int age: int location: str furnishing: str @app.post("/predict") def predict(info: HouseInfo): features = preprocess_input(info) # 与训练时完全一致的预处理函数 input_name = sess.get_inputs()[0].name pred = sess.run(None, {input_name: features.astype(np.float32)})[0] return {"predicted_price": float(pred[0])}

这里最容易被忽略的是并发处理。FastAPI 默认是异步框架,但如果你在路由函数里直接调用 CPU 密集的 ONNX Runtime 推理,会阻塞事件循环,高并发时服务直接卡死。正确做法是:

import asyncio from concurrent.futures import ThreadPoolExecutor executor = ThreadPoolExecutor(max_workers=4) @app.post("/predict") async def predict(info: HouseInfo): loop = asyncio.get_running_loop() result = await loop.run_in_executor(executor, sync_predict, info) return result

用线程池把推理操作扔到独立的线程里执行,主事件循环保持畅通。这样才能在真实流量下扛住并发。上面这个小改动,在我一个项目里直接让压测 QPS 从 15 提升到 120,效果显著。

4.4 容器化部署:Dockerfile 里藏着细节

写 Dockerfile 时,大多数人只会把环境搭好、复制代码进去、启动服务,然后得到一个 5 个 G 的恐怖镜像。这个镜像不仅构建慢、拉取慢,运行时还占用大量磁盘空间。一个工程化的做法是使用多阶段构建,把依赖安装和运行环境分离。

# 第一阶段:构建所需依赖 FROM python:3.11-slim as builder WORKDIR /app COPY requirements.txt . RUN pip install --prefix=/install onnxruntime fastapi uvicorn # 第二阶段:精简运行环境 FROM python:3.11-slim COPY --from=builder /install /usr/local COPY ./app /app COPY ./models/house_price_model.onnx /app/models/house_price_model.onnx WORKDIR /app CMD ["uvicorn", "main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]

第一阶段的镜像包含所有编译缓存和中间依赖,第二阶段只保留运行所需文件。这样构建出的镜像通常能控制在 1GB 以内。注意最后一个--workers 4,多开几个 worker 能充分利用多核 CPU,推理服务的吞吐量又上了一个台阶。

我遇到过很多次这种情况:Docker 本地构建成功,但一部署到服务器就崩溃。排查到最后,八成是用了本地已经存在的某个镜像层,而服务器上不存在。解决方法是构建时只用明确的 base 镜像 tag,不要依赖缓存清理不干净带来的“薛定谔的成功”。

4.5 模型监控与迭代闭环

服务上线只是开始。数据不会保持不变,用户行为在变化,特征分布也在漂移。模型上线后的监控设计,是把 AI 工程闭环收起来的最后一步。

我常做的监控分为三种:

  • 服务健康监控:请求量、错误率、P95/P99 延迟,这些必须接入现有的监控和告警体系,服务宕了或者慢到不可用,要能及时发现。
  • 输入数据监控:检查线上请求的特征分布和训练时是否一致。例如训练集里的area中位数是 75,某天突然变成 180,大概率是上游传参出了问题,也可能是业务本身发生了重大变化。这种变化用 KS 检验或简单统计量就能实现粗筛告警。
  • 模型效果监控:反馈延迟的时候,可以定期用人工标注的样本评测线上模型的表现。如果没有标注,至少记录预测值的分布变化和置信度变化,再做人工抽样复核。

这是一套很朴素但实用的监控栈。它不能阻止所有问题,但能在问题变得不可收拾之前提醒你。AI 工程里没有“上线即结束”的剧本,上线才是运维和迭代的开始。

5. 常见问题与排查技巧实录

5.1 训练集与测试集分布不一致:所有准确率都是假的

这是我见过最阴险的问题。模型在验证集上表现极好,一到线上立刻拉垮,但你又说不清楚哪里出了问题。排查时第一个怀疑的对象就是训练集和测试集的分布不一致。特别是按时间划分的数据,如果训练数据来自今年上半年,线上数据来自下半年,而业务模式刚好在中间发生了变化,分布偏移就是必然的。

排查方法很简单:把训练集和验证集的特征分布并排画出来,看均值、方差、分位数是否有肉眼可见的差异。也可以用对抗验证——把训练集和线下测试集打上标签 0/1,训练一个分类器看能不能较好地把两个集合分开。如果分类准确率显著高于 50%,说明两组数据在特征层面是可以区分的,分布确实偏移了。

遇到这种问题时,最差的应对是继续硬调模型参数。正确方向是寻找更稳定的特征,或者把时间窗纳入模型设计,比如增加趋势变量、周期变量,减少对纯静态特征的依赖。

5.2 数据泄漏:模型“作弊”的方式千奇百怪

数据泄漏不会报错,只会让你的模型在离线验证时显得异常优秀,上线后立刻原型毕露。最常见的泄漏是目标变量被不知不觉放进了特征里。之前做一个用户流失预测项目时,同事把“客户是否已提交退订工单”放进了特征集,线上环境里这个字段在预测时往往是 NULL,模型离线表现接近 100% 准确,上线后连 60% 都做不到。

排查数据泄漏可以从三个角度入手:第一,检查特征构造的时点是否严格早于预测时点;第二,对高重要度特征做业务合理性质疑—这个特征线上真的能拿到吗?第三,用模型输出的置信度分布做异常检测,如果正样本置信度都在 0.99 以上,大概率有泄漏。

5.3 GPU 显存不足:不只靠换大卡

训练大模型时最常见的问题就是CUDA out of memory。很多人第一反应是换更大显存的卡,但更工程化的做法是检查自己的代码有没有把显存浪费掉。

常见原因有几个:第一个是 batch size 设得过大,直接减半就能解决;第二个是输入序列长度不一致导致 PyTorch 对每个 batch 都用最长的序列做 padding,显存被无效 token 大量占用;第三个是模型和优化器之外还缓存了大量中间激活值,通过torch.utils.checkpoint或梯度累积能大幅降低峰值显存;第四个是验证阶段没有用torch.no_grad()包裹,梯度计算仍然在分配显存。

with torch.no_grad(): for batch in valid_loader: outputs = model(batch)

一行torch.no_grad()就能省掉验证阶段将近一半的显存开销。我见过太多人因为没有加这一行,不得不在 24GB 的卡上把 batch size 调到 4,训练速度慢到怀疑人生。

5.4 线上和线下预测不一致:三步定位法

模型训练时一切正常,部署后通过 API 调用结果却和本地跑不一样,这是让无数 AI 工程师项目半夜睡不着的问题。按我的经验,用三步定位法基本能覆盖 80% 的情况。

第一步,检查输入数据的预处理是不是完全复刻。最容易遗漏的是 feature order。训练时特征是["area", "bedrooms"],线上请求进来如果字段顺序不同,而你没有显式固定顺序,结果必然乱套。第二步,检查数据类型。线上传的是 string,离线用的是 float,模型内部某些操作为了安全可能做了类型转换,得到完全不同的数值。第三步,检查模型文件本身。ONNX 导出时是否带了 dynamic_axes,模型在 batch size 为 1 和 batch size 为 32 时输出的数值是否完全一致,都可能导致误差。

这类问题的排查,一定要有成体系的方法,不要在线上日志里瞎猜。我自己的习惯是:保留 10 条线下推理的输入输出样本,线上出问题后直接用这些样本跑一遍线上 API,对比结果差异,百分之八十的问题能在一小时内定位到。

5.5 常见的工程化烂代码模式

最后分享几个我在代码审查里反复看到、直接反映工程成熟度不足的模式。

  • 函数越写越长:一个函数干十件事,参数十几个,里面嵌套三四层循环,没有拆分,没有注释。这种代码早晚会在某个上线压力下成为事故源头。
  • 魔法数字满天飞:if x > 0.8:和learning_rate = 0.001直接裸写在代码里,没有常量名或配置管理。调参时你只能全文搜索手动替换,改漏一个就埋下炸弹。
  • 测试覆盖缺失:数据预处理函数没有单元测试,模型服务接口没有集成测试,等到上线出问题才追悔莫及。
  • 日志当摆设:没有在关键环节打印关键信息,线上排查问题时两眼一抹黑。但日志也不是越多越好,要建立分级日志的规范,什么级别该输出什么内容得有约定。

把这些问题平时就解决好,比反复救火要省力得多。

6. 写在最后:我的个人体会

几年下来,我对 AI 工程最深的体会是:它本质上是“用工程方法让 AI 技术在真实场景里稳定创造价值”的学科,核心不是模型有多聪明,而是系统有多可靠。一个准确率 85% 但能稳定运行半年不出的简单模型,远胜过一个准确率 95% 但没人敢碰、一上线就事故的复杂系统。

最后分享一个小技巧,也是我自己从零摸索时最有用的习惯:每学一个新技术,不要只跟着教程敲一遍代码,而是想方设法把它接进一个不存在的“伪需求”里,给自己造一个小项目去把它跑通。想学 Docker,就写一个一键部署某小模型的脚本;想学 MLflow,就把以前的模型训练重构成带实验追踪的版本;想学 ONNX,就给自己的项目写一个推理服务。越是这种“不正经”的练手小项目,越能把零散的知识焊进大脑。

AI 工程这条路不太拥挤,哪怕从零开始,一步一步走,总能走到真正能扛事的那个位置。

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

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

立即咨询