最近在公司做一个小项目,需要把训练好的BERT模型部署到生产环境。一开始想用PyTorch自带的JIT trace,结果动态shape直接给我整不会了。后来转ONNX,又遇到LayerNorm和GELU算子不支持,各种改代码绕路,最后导出的模型精度还掉了0.3%。我心态有点崩,感觉自己在瞎折腾。想问问各位老哥,现在实际工业落地,如果不想用TensorRT(公司没N卡)也不想上服务端框架(太复杂),有没有比较稳的部署方案?或者是我用ONNX的方式不对?求指条明路,谢谢了!
PyTorch转JIT被坑惨了,ONNX导出也报算子错误,大佬们现在部署都用啥?
全部回复
共 87 条ONNX导LayerNorm和GELU报错太常见了,建议先把opset版本拉到13以上试试,GELU可以用Erf组合手动拆开写,别指望torch自动帮你映射。精度掉点大概率是导出时某些算子走了float16或者近似实现,用onnxruntime的float32跑一遍对比下中间层输出就知道了。没N卡的话其实onnxruntime CPU推理就挺稳的,配上OpenVINO还能再快一点,真没必要硬上TensorRT。
LayerNorm和GELU在ONNX opset里其实早就支持了,你大概率是opset版本设太低,或者用的torch版本和onnxruntime对不上。我上个月也踩过类似的坑,把opset调到17之后大部分算子都能顺利导出,精度掉的问题基本出在GELU的近似实现上,torch默认导出的erf版本和原模型有细微差异,换成tanh近似再对齐一下反而更稳。动态shape的话,JIT trace确实不友好,但你可以试试torch.jit.script配合torch.jit.freeze,比trace对控制流友好很多。如果公司没N卡又不想上Triton这种重框架,其实ONNX Runtime本身就能扛生产,CPU推理加个int8量化,延迟和精度都还能接受,我们线上就这么跑的。真要省心,也可以看看OpenVINO或者直接拿HuggingFace的optimum走一遍,它帮你把导出和优化都封装好了,少折腾不少。
ONNX导LayerNorm得手动改opset版本,精度掉可能出在GELU近似上,试试torchscript加dynamic_axes。
ONNX导BERT这块我也踩过一模一样的坑,LayerNorm和GELU那堆算子问题基本是版本对不上导致的,你试试升到opset 14以上再用onnxruntime的优化工具跑一遍,精度掉0.3%很多时候是GELU被拆成了近似实现。动态shape的话JIT trace确实不友好,得用script模式配合torch.jit.annotate把维度标出来,不然它就把shape焊死了。如果公司没N卡又不想碰TensorRT,其实可以考虑用ONNX Runtime直接跑CPU推理,BERT这种量级做量化后延迟还能接受,或者看看OpenVINO,对Intel机器挺友好的。精度掉那0.3%建议先别急着上线,拿几百条真实样本对比一下输出分布,有时候只是数值误差,有时候是某个算子被替换了。另外导出的时候记得把model.eval()和torch.no_grad()都加上,dropout没关也会让结果飘。你们要是量不大,其实FastAPI套个onnxruntime就能撑住,真没必要上那些重型框架。
ONNX导出LayerNorm和GELU报错这事儿太常见了,尤其是HuggingFace的BERT,opset版本不对就各种炸。你试试把opset升到14以上,GELU直接用Erf分解,LayerNorm手动拆成ReduceMean+Sub+Div,一般能绕过去,精度掉0.3%大概率是某个算子fallback到CPU或者精度模式没对齐。动态shape的话JIT trace确实不友好,得用script或者干脆在导出ONNX时把dynamic_axes写清楚,batch和seq_len都标上。如果不想碰TensorRT和服务端框架,其实ONNX Runtime就挺稳的,CPU上跑BERT量化一下速度也能接受,公司没N卡的话这基本是最省心的路子。另外也可以看看OpenVINO,Intel CPU上推理优化做得不错,转换工具对Transformer支持比前两年好多了。精度掉点的问题建议导出后逐层对比输出,大概率能定位到是哪个算子被替换了。
BERT这种动态shape的模型确实不适合走JIT trace那条路,script模式又得改代码,挺折腾的。ONNX那边LayerNorm和GELU报错一般是opset版本太低,升到14以上基本就支持了,精度掉那0.3%多半是GELU近似实现的问题。没N卡的话可以看看OpenVINO或者ONNX Runtime,CPU推理优化都做得不错,部署也简单。
ONNX导出LayerNorm报错我也踩过,试试用opset 14以上再导,精度掉可能是没对齐eval模式。