当前位置: 首页 > news >正文

01 初试模型的部署

目录

  • 一、什么是“模型部署”?一句话 & 五种场景
  • 二、为什么选 ONNX?核心概念 5 件事
  • 三、PyTorch → ONNX 最稳姿势(含动态维度、常见坑)
  • 四、TensorFlow/Keras → ONNX 两种方式(CLI & 代码)
  • 五、导出后如何“验模”?等价性校验与可视化
  • 六、进一步优化:Simplify、融合、量化、FP16
  • 七、用 ONNX Runtime 推理(CPU/GPU/TensorRT)
  • 八、上线服务:FastAPI + Uvicorn 模板(可直接用)
  • 九、容器化与部署(含 GPU Dockerfile)
  • 十、性能调优清单:吞吐、延迟、内存
  • 十一、排坑大全:典型报错 & 解决
  • 十二、上线工程要点:版本、监控、安全
  • 十三、写作彩蛋:一键复用的文章骨架 & SEO 提示

一、什么是“模型部署”?一句话 & 五种场景

一句话:把“训练好的模型”变成“可被真实业务低延迟高可用地调用的系统”让你的代码走出舒适区,走出学术的象牙塔,到车间去,到户外去,到生产的一线去!

二、为什么选 ONNX?核心概念 5 件事

  1. 跨框架中间表示:一次导出(导一次刚刚好,煮啵说的是模型),多处运行(CPU/GPU/NPU),便于迁移。
  2. Opset:算子集版本号。不同导出器/后端支持范围不同。建议优先选较新的稳定 opset(如 17+),遇到不支持算子再降级或替换实现。
  3. 图结构Graph = Node + Tensor + Attribute。便于做常量折叠、算子融合。
  4. 静态 vs 动态形状:通过 dynamic_axes 指定批大小/可变尺寸,提升泛化但可能弱化部分优化;静态形状则更易做极致优化。
  5. 生态:ONNX Runtime(ORT)、TensorRT、OpenVINO、CoreML、Web(ONNX Runtime Web)。

小工具:可视化用 Netron,简化用 onnx-simplifier(onnxsim)。传送门:Netron


三、PyTorch → ONNX 最稳姿势(含动态维度、常见坑)

3.1 基础导出(以 ResNet18 为例)

# pip install torch torchvision onnx onnxruntime-gpu onnxsim
import torch
import torchvision.models as modelsmodel = models.resnet18(weights=models.ResNet18_Weights.DEFAULT)
model.eval()dummy = torch.randn(1, 3, 224, 224)  # 代表输入样例torch.onnx.export(model,dummy,"resnet18.onnx",input_names=["input"],output_names=["logits"],opset_version=17,               # 建议 17 起步;遇到不支持再调整do_constant_folding=True,       # 常量折叠dynamic_axes={                  # 动态维度(批大小可变)"input": {0: "batch"},"logits": {0: "batch"}}
)
print("Exported to resnet18.onnx")

3.2 导出技巧

  • 一定要 model.eval():避免 Dropout/BN 训练态差异。
  • 确保输入前后处理一致:导出时把归一化、Resize、Padding 等逻辑“定型”,上线端严格复刻。
  • 控制算子interpolategroupnorm 等在早期 opset/后端可能不完美;必要时改写为等价算子或固定尺寸。
  • 自定义算子:优先改写为通用算子组合;否则考虑自定义 kernel(TensorRT Plugin/ORT Custom Op)。
  • 多输入多输出:合理命名并在 dynamic_axes 中逐一声明可变维度。

3.3 导出检测/分割类模型的要点

  • NMS、后处理(阈值、解码)通常不要放进 ONNX(跨后端兼容差),更稳的做法是导出纯网络主干,后处理在应用层实现。
  • 需要放进 ONNX 时,优先选 ORT/TensorRT 支持的实现(如 TRT 的 BatchedNMSPlugin)。

四、TensorFlow/Keras → ONNX 两种方式(CLI & 代码)

4.1 使用 tf2onnx(CLI 最省心)

# pip install tf2onnx onnx onnxruntime-gpu
python -m tf2onnx.convert \--saved-model ./saved_model_dir \--opset 17 \--output model.onnx

支持 --from_keras--concrete_function--inputs-as-nchw 等参数,遇到通道顺序不一致问题时很有用。

4.2 Python 代码方式

import tensorflow as tf
import tf2onnxmodel = tf.keras.applications.MobileNetV2(weights="imagenet")
# Keras -> ConcreteFunction
spec = tf.TensorSpec((1, 224, 224, 3), tf.float32, name="input")
model_func = tf.function(model).get_concrete_function(spec)onnx_model, _ = tf2onnx.convert.from_function(model_func,input_signature=[spec],opset=17,output_path="mobilenetv2.onnx"
)

五、导出后如何“验模”?等价性校验与可视化

5.1 结构合法性检查

import onnx
onnx_model = onnx.load("model.onnx")
onnx.checker.check_model(onnx_model)
print("Checker passed!")

5.2 ONNX Runtime 推理对比(数值容差)

import numpy as np
import onnxruntime as ort# 原框架输出 (以 PyTorch 为例)
import torch
x = torch.randn(2, 3, 224, 224)
with torch.no_grad():torch_out = model(x).cpu().numpy()# ORT 输出
providers = ["CUDAExecutionProvider", "CPUExecutionProvider"]
sess = ort.InferenceSession("model.onnx", providers=providers)
onnx_out = sess.run([sess.get_outputs()[0].name], {"input": x.numpy()})[0]# 比较
np.testing.assert_allclose(torch_out, onnx_out, rtol=1e-03, atol=1e-05)
print("ORT output is close to PyTorch output!")

5.3 可视化

  • 使用 Netron 打开 .onnx,检查输入输出名称、维度、算子连接是否符合预期。

六、进一步优化:Simplify、融合、量化、FP16

6.1 图简化

python -m onnxsim model.onnx model-sim.onnx

好处:消灭冗余节点、常量折叠,更容易被后端吃满。

6.2 ONNX Runtime 图优化

import onnxruntime as ort
opt = ort.SessionOptions()
opt.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
sess = ort.InferenceSession("model-sim.onnx", sess_options=opt,providers=["CUDAExecutionProvider", "CPUExecutionProvider"])

6.3 量化(Dynamic / Static)

动态量化(简单、无需标注数据)

from onnxruntime.quantization import quantize_dynamic, QuantType
quantize_dynamic(model_input="model-sim.onnx",model_output="model-int8.onnx",weight_type=QuantType.QInt8,optimize_model=True
)

静态量化(效果更好,需要校准数据)
核心思路是实现 CalibrationDataReader,将若干代表性样本喂给校准器。

from onnxruntime.quantization import CalibrationDataReader, quantize_static, QuantFormat, QuantType
import numpy as npclass NumpyFolderReader(CalibrationDataReader):def __init__(self, samples):  # samples: List[np.ndarray]self.samples = iter(samples)def get_next(self):try:arr = next(self.samples)return {"input": arr}except StopIteration:return None# 假设已准备好若干 (1,3,224,224) 的样本数组
reader = NumpyFolderReader(samples)
quantize_static(model_input="model-sim.onnx",model_output="model-int8s.onnx",calibration_data_reader=reader,quant_format=QuantFormat.QDQ,   # 兼容更好activation_type=QuantType.QInt8,weight_type=QuantType.QInt8
)

6.4 FP16(GPU 友好)

import onnx
from onnxconverter_common import float16
m = onnx.load("model-sim.onnx")
m_fp16 = float16.convert_float_to_float16(m, keep_io_types=True)
onnx.save(m_fp16, "model-fp16.onnx")

A100 场景:优先尝试 TensorRT 或 ORT 的 TensorRT Execution Provider,再考虑 FP16/INT8。


七、用 ONNX Runtime 推理(CPU/GPU/TensorRT)

7.1 选择后端

  • CPUCPUExecutionProvider(可设置线程数、亲和性)。
  • GPUCUDAExecutionProvider(支持 FP16、BFloat16 等)。
  • TensorRTTensorrtExecutionProvider(极致延迟/吞吐,支持 engine 缓存)。

7.2 Python 最简调用

import onnxruntime as ort, numpy as np
opt = ort.SessionOptions()
opt.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALLproviders = [("TensorrtExecutionProvider", {"trt_fp16_enable": True}),"CUDAExecutionProvider","CPUExecutionProvider"
]sess = ort.InferenceSession("model-fp16.onnx", sess_options=opt, providers=providers)x = np.random.randn(4, 3, 224, 224).astype(np.float32)
out = sess.run([sess.get_outputs()[0].name], {"input": x})[0]
print(out.shape)

7.3 进阶:Session 环境变量与 Provider 参数

  • intra_op_num_threadsinter_op_num_threads
  • TensorRT:trt_max_workspace_size, trt_engine_cache_enable, trt_timing_cache_enable
  • CUDA:cuda_mem_limit, cudnn_conv_algo_search

八、上线服务:FastAPI + Uvicorn 模板

目录结构:

app/├── server.py├── preprocess.py└── postprocess.py

server.py

from fastapi import FastAPI
from pydantic import BaseModel
import onnxruntime as ort
import numpy as npapp = FastAPI(title="ONNX Inference Service")# 1) 加载模型(进程启动即加载与预热)
opt = ort.SessionOptions()
opt.graph_optimization_level = ort.GraphOptimizationLevel.ORT_ENABLE_ALL
providers = [("TensorrtExecutionProvider", {"trt_fp16_enable": True}),"CUDAExecutionProvider","CPUExecutionProvider"
]
sess = ort.InferenceSession("model.onnx", sess_options=opt, providers=providers)
output_name = sess.get_outputs()[0].nameclass Item(BaseModel):data: list  # 简易示例:传二维/四维数组@app.on_event("startup")
async def warmup():dummy = np.zeros((1,3,224,224), dtype=np.float32)sess.run([output_name], {"input": dummy})@app.post("/predict")
def predict(item: Item):x = np.array(item.data, dtype=np.float32)if x.ndim == 3:x = x[None, ...]y = sess.run([output_name], {"input": x})[0]return {"shape": list(y.shape), "result": y.tolist()[:10]}  # demo:返回前 10 个数

启动:

uvicorn app.server:app --host 0.0.0.0 --port 8000 --workers 1

压测(示例):

# 安装 locust 或 wrk 任选其一
# wrk 示例
wrk -t4 -c64 -d30s --timeout 2s \-s post.lua http://127.0.0.1:8000/predict

post.lua(简单脚本):

wrk.method = "POST"
wrk.headers["Content-Type"] = "application/json"local data = {}
for i=1,3 do data[i] = {}for j=1,224*224 do data[i][j] = 0.0 end
end
local body = '{"data":[' .. table.concat(data, ",") .. ']}'request = function()return wrk.format("POST", "/predict", nil, body)
end

九、容器化与部署

Dockerfile(GPU)

FROM nvidia/cuda:12.4.1-cudnn-runtime-ubuntu22.04
RUN apt-get update && apt-get install -y python3-pip && rm -rf /var/lib/apt/lists/*
RUN pip install --no-cache-dir fastapi uvicorn[standard] onnx onnxruntime-gpu onnxsim numpy pillow
WORKDIR /app
COPY app /app
EXPOSE 8000
CMD ["uvicorn", "server:app", "--host", "0.0.0.0", "--port", "8000"]

构建 & 运行:

docker build -t onnx-service:gpu .
# 需要 NVIDIA Container Toolkit
docker run --rm -it -p 8000:8000 --gpus all onnx-service:gpu

Kubernetes 小提示

  • 设定 livenessProbe/readinessProbe
  • 使用 nvidia.com/gpu: 1 资源请求;
  • 通过 ConfigMap/Secret 注入模型路径与密钥;
  • 滚动更新 + 金丝雀发布。

十、性能调优清单:吞吐、延迟、内存

  • Batch:在线低延迟场景小批或零批,离线/流式可用微批聚合。
  • Pinned Memory:数据拷贝更快;Python 端使用 numpy 的 page-locked 需要配合 IOBinding/自定义缓冲。
  • IOBinding:ORT 把输入/输出绑定到 GPU,减少 H2D/D2H;极端延迟优化利器。
  • 图静态化:能固定就固定(尺寸、步幅、Pad),换取更强优化。
  • Provider 顺序:优先 TensorRT,其次 CUDA,最后 CPU。
  • 混合精度:FP16/INT8;校验精度,记录 A/B 实验数据。
  • 多进程:Python GIL 影响下,多进程优于多线程;或用 C++/Rust 封装服务。

十一、排坑大全:典型报错 & 解决

报错/现象可能原因解决思路
No Op kernel registered for ...后端不支持该算子/数据类型提升/降低 opset;替换算子;切换 Provider;自定义插件
Non-zero status code while running ...维度不一致/越界检查预处理、动态轴,打印真实输入形状
导出后精度突降训练/推理前后处理不一致;BN/Dropouteval();统一归一化/Resize;比对中间层
TensorRT 构建失败或极慢动态维度过多;不支持算子固定关键维度;开启 Engine Cache;替换不支持算子
显存炸裂批太大;中间激活过多降低 batch;FP16/INT8;图简化;分块推理

十二、上线工程要点:版本、监控、安全

  • 版本管理:模型文件加 model_name/version/opset;用 MLflow/DVC/S3 做注册与溯源。
  • 可观测性:请求计数、P50/P95/P99、GPU 利用率;Prometheus + Grafana。
  • 灰度/回滚:按流量/用户分群灰度;事故一键回滚到上一稳定版本。
  • 安全:输入校验、超时/限流、CORS 与鉴权;容器只读文件系统、非 root 运行。

十三、写作彩蛋:一键复用的文章骨架 & SEO 提示

文章开头三板斧

  1. 痛点:训练模型很顺,上线反而卡
  2. 承诺:这篇文章给你从导出到部署可复制路径
  3. 预告:PyTorch/TensorFlow 都有示例,GPU/CPU 都能跑。

SEO 关键词(标题/小节/Alt 文案中穿插):“模型部署”、“ONNX 转换”、“ONNX Runtime 推理”、“TensorRT 加速”、“FastAPI 部署”。

结尾 CTA:给出 Demo 仓库链接/压测数据图(可后续补充)。


附:可直接复用的最小 Demo

A. PyTorch 导出 + ORT 对比

# pip install torch torchvision onnx onnxruntime onnxsim
import torch, torchvision as tv, onnx, onnxruntime as ort, numpy as np
m = tv.models.resnet18(weights=tv.models.ResNet18_Weights.DEFAULT).eval()
dummy = torch.randn(1,3,224,224)
torch.onnx.export(m, dummy, "res18.onnx", input_names=["input"], output_names=["logits"], opset_version=17,dynamic_axes={"input":{0:"batch"},"logits":{0:"batch"}})
# ORT 推理
sess = ort.InferenceSession("res18.onnx", providers=["CPUExecutionProvider"]) # CPU 也能跑
x = np.random.randn(1,3,224,224).astype(np.float32)
y = sess.run([sess.get_outputs()[0].name], {"input": x})[0]
print(y.shape)

B. FastAPI 服务最小化

from fastapi import FastAPI
import onnxruntime as ort, numpy as np
app = FastAPI()
sess = ort.InferenceSession("res18.onnx", providers=["CPUExecutionProvider"])
name = sess.get_outputs()[0].name
@app.post("/predict")
def predict(data: list):arr = np.array(data, dtype=np.float32)if arr.ndim==3: arr=arr[None,...]out = sess.run([name], {"input": arr})[0]return out.tolist()

到这里,你已经具备:会把模型转成 ONNX、会验证和优化、会用 ORT 推理、会把服务跑起来并容器化。把具备生产力的业务前后处理接上去,就是真实生产的雏形!

http://www.dtcms.com/a/572970.html

相关文章:

  • StarRocks技术分享
  • 电子商务网站建设特色泰州做网站的
  • 多模态 AI 时代的数据困局与机遇,Bright Data 赋能LLM 训练以及AEO场景
  • 昇腾NPU性能调优实战:INT8+批处理优化Mistral-7B全记录
  • 未来之窗昭和仙君(五十五)标签票据打印模板设计器——东方仙盟筑基期
  • 10.26-11.5力扣数组刷题
  • 【C++闯关笔记】哈希表模拟实现unordered_map与unordered_set
  • 【Agentic RL 专题】四、深入浅出RAG原理与实战项目
  • 开源力量:GitCode+昇腾NPU 部署Mistral-7B-Instruct-v0.2模型的技术探索与经验总结
  • 网站被人做跳转了做网站横幅的软件
  • 暖色调网站什么网站上面能接点小活做
  • 网站栏目是什么上海城隍庙必吃美食
  • 智慧康养人形机器人——银发科技的革命者及在日本超老龄化社会的实验(中)
  • 微算法科技(NASDAQ MLGO)“自适应委托权益证明DPoS”模型:重塑区块链治理新格局
  • 小康AI家庭医生:以科技之翼,守陪伴之初心
  • 司马阅与铨亿科技达成生态战略合作,AI赋能工业领域智能化转型
  • 【旋智科技】SPC1158 MCU 参数要点和开发资料
  • 天元建设集团有限公司管理工资发放2个网站 同意内容 百度优化
  • 算法26.0
  • 二十二、STM32的ADC(二)(ADC单通道)
  • 芯谷科技--D3915高性能点阵/条形显示驱动器,点亮智能显示新时代
  • 空间革命:智慧档案馆三维立体一体化科技监控系统方案
  • 苏州网站建设代理装饰设计资质乙级
  • layui窗口标题
  • Linux(docker)安装搭建CuteHttpFileServer/chfs文件共享服务器
  • ubuntu 系统下 将 ROS2 apt 存储库添加到系统,用apt授权我们的GPG 密钥
  • 网站域名注册基本流程微网站移交
  • 线性代数 - 正交矩阵
  • Flink DataStream × Table API 融合双向转换、变更流、批流一体与执行模型
  • 汽车配件 AI 系统:重构汽车配件管理与多语言内容生成新范式