كيفية تصدير نماذج PyTorch غير المعتمدة على YOLO باستخدام Ultralytics
عادةً ما يعني نشر نماذج PyTorch في بيئة الإنتاج التعامل مع أداة تصدير مختلفة لكل هدف: torch.onnx.export لـ ONNX، coremltools لأجهزة Apple، onnx2tf لـ TensorFlow، pnnx لـ NCNN، وهكذا. كل أداة لها API الخاص بها، ومتطلبات تبعية معينة، واتفاقيات مخرجات خاصة.
توفر Ultralytics أدوات تصدير مستقلة تغلف منصات خلفية متعددة ضمن واجهة واحدة متسقة. يمكنك تصدير أي نماذج صور torch.nn.Module متعددة، بما في ذلك timm، أو نماذج التصنيف والاكتشاف الخاصة بـ torchvision، أو معمارياتك المخصصة، إلى ONNX, TorchScript, OpenVINO, CoreML, NCNN, PaddlePaddle, MNN, ExecuTorch، وTensorFlow SavedModel دون الحاجة إلى تعلم كل منصة خلفية على حدة.
لماذا تستخدم Ultralytics لتصدير نماذج غير YOLO؟
- واجهة API واحدة عبر 10 تنسيقات: تعلم اتفاقية استدعاء واحدة بدلاً من العشرات.
- سطح أداة مشترك: تقع أدوات المساعدة في التصدير تحت
ultralytics.utils.export، لذا بمجرد تثبيت حزم الخلفية، يمكنك الاحتفاظ بنفس نمط الاستدعاء عبر التنسيقات. - نفس مسار الكود الخاص بتصديرات YOLO: نفس الأدوات المساعدة تدعم كل عملية تصدير في Ultralytics YOLO.
- كمية FP16 و INT8 مضمنة للتنسيقات التي تدعمها (OpenVINO, CoreML, MNN, NCNN).
- تعمل على CPU: لا حاجة إلى GPU لخطوة التصدير نفسها، لذا يمكنك تشغيلها محلياً على أي جهاز كمبيوتر محمول.
بداية سريعة
أسرع مسار هو تصدير من سطرين إلى ONNX بدون كود YOLO وبدون إعداد بخلاف pip install ultralytics onnx timm:
import timm
import torch
from ultralytics.utils.export import torch2onnx
model = timm.create_model("resnet18", pretrained=True).eval()
torch2onnx(model, torch.randn(1, 3, 224, 224), output_file="resnet18.onnx")تنسيقات التصدير المدعومة
فئة النموذج torch2* تأخذ الوظائف torch.nn.Module قياسياً وموتر إدخال تجريبي. MNN و TF SavedModel و TF Frozen Graph تمر عبر ONNX وسيط أو أداة Keras. لا يلزم وجود سمات خاصة بـ YOLO في أي من الحالتين.
| الصيغة | الوظيفة | تثبيت | المخرجات |
|---|---|---|---|
| ONNX | torch2onnx() | pip install onnx | .onnx ملف |
| TorchScript | torch2torchscript() | مضمنة مع PyTorch | .torchscript ملف |
| OpenVINO | torch2openvino() | pip install openvino | _openvino_model/الدليل |
| CoreML | torch2coreml() | pip install coremltools | .mlpackage |
| TF SavedModel | onnx2saved_model() | انظر المتطلبات التفصيلية أدناه | _saved_model/الدليل |
| TF Frozen Graph | keras2pb() | انظر المتطلبات التفصيلية أدناه | .pb ملف |
| NCNN | torch2ncnn() | pip install ncnn pnnx | _ncnn_model/الدليل |
| MNN | onnx2mnn() | pip install MNN | .mnn ملف |
| PaddlePaddle | torch2paddle() | pip install paddlepaddle x2paddle | _paddle_model/الدليل |
| ExecuTorch | torch2executorch() | pip install executorch | _executorch_model/الدليل |
MNN, TF SavedModel، وتصديرات TF Frozen Graph تمر عبر ONNX كخطوة وسيطة. قم بالتصدير إلى ONNX أولاً، ثم قم بالتحويل.
تقبل العديد من وظائف التصدير قاموس metadata اختياري (مثلاً، torch2torchscript(..., metadata={"author": "me"})) الذي يقوم بتضمين أزواج مفتاح-قيمة مخصصة في الأداة المصدرة حيثما يدعم التنسيق ذلك.
أمثلة خطوة بخطوة
يستخدم كل مثال أدناه نفس الإعداد، نموذج ResNet-18 مدرب مسبقاً من timm في وضع التقييم:
import timm
import torch
model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)طبقات Dropout، وbatch normalization، وغيرها من الطبقات الخاصة بالتدريب فقط تتصرف بشكل مختلف أثناء الاستدلال. تخطي .eval() ينتج عنه تصديرات ذات مخرجات غير صحيحة.
التصدير إلى ONNX
from ultralytics.utils.export import torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")لحجم دفعة ديناميكي، مرر قاموس dynamic:
torch2onnx(model, im, output_file="resnet18_dyn.onnx", dynamic={"images": {0: "batch_size"}})الـ opset الافتراضي هو 14 واسم الإدخال الافتراضي هو "images". تجاوز ذلك باستخدام وسيطات opset, input_names، أو output_names.
تصدير إلى TorchScript
لا حاجة إلى تبعيات إضافية. يستخدم torch.jit.trace في الخلفية.
from ultralytics.utils.export import torch2torchscript
torch2torchscript(model, im, output_file="resnet18.torchscript")تصدير إلى OpenVINO
from ultralytics.utils.export import torch2openvino
ov_model = torch2openvino(model, im, output_dir="resnet18_openvino_model")يحتوي الدليل على زوج model.xml و model.bin ذو اسم ثابت:
resnet18_openvino_model/
├── model.xml
└── model.binمرر dynamic=True لأشكال الإدخال الديناميكية، و half=True لـ FP16، أو int8=True لتكميم INT8. يتطلب INT8 بالإضافة إلى ذلك calibration_dataset.
يتطلب openvino>=2024.0.0 (أو >=2025.2.0 على macOS 15.4+) وtorch>=2.1.
تصدير إلى CoreML
import coremltools as ct
from ultralytics.utils.export import torch2coreml
inputs = [ct.TensorType("input", shape=(1, 3, 224, 224))]
ct_model = torch2coreml(model, inputs, im, output_file="resnet18.mlpackage")بالنسبة لـ classification نماذج، مرر قائمة بأسماء الفئات إلى classifier_names لإضافة رأس تصنيف إلى نموذج CoreML.
يتطلب coremltools>=9.0, torch>=1.11، وnumpy<=2.3.5. غير مدعوم على Windows.
coremltools>=9.0 يوفر حزم Python 3.10–3.13 على macOS و Linux. في إصدارات Python الأحدث، يفشل تحميل ملحق C الأصلي. استخدم Python 3.10–3.13 لتصدير CoreML.
تصدير إلى TensorFlow SavedModel
يتم تصدير TF SavedModel عبر ONNX كخطوة وسيطة:
from ultralytics.utils.export import onnx2saved_model, torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")
keras_model = onnx2saved_model("resnet18.onnx", output_dir="resnet18_saved_model")ترجع الوظيفة نموذج Keras وتنشئ أيضاً ملفات TFLite (.tflite) داخل دليل المخرجات:
resnet18_saved_model/
├── saved_model.pb
├── variables/
├── resnet18_float32.tflite
├── resnet18_float16.tflite
└── resnet18_int8.tfliteالمتطلبات:
tensorflow>=2.0.0,<=2.19.0onnx2tf>=1.26.3,<1.29.0tf_keras<=2.19.0sng4onnx>=1.0.1onnx_graphsurgeon>=0.3.26(ثبته باستخدام--extra-index-url https://pypi.ngc.nvidia.com)ai-edge-litert>=1.2.0,<1.4.0على macOS (ai-edge-litert>=1.2.0على منصات أخرى)onnxslim>=0.1.71onnx>=1.12.0,<2.0.0protobuf>=5
تصدير إلى TensorFlow Frozen Graph
استمراراً من تصدير SavedModel أعلاه، قم بتحويل نموذج Keras المرجع إلى رسم .pb مجمد:
from pathlib import Path
from ultralytics.utils.export import keras2pb
keras2pb(keras_model, output_file=Path("resnet18_saved_model/resnet18.pb"))تصدير إلى NCNN
from ultralytics.utils.export import torch2ncnn
torch2ncnn(model, im, output_dir="resnet18_ncnn_model")يحتوي الدليل على ملفات param و bin ذات اسم ثابت بالإضافة إلى غلاف Python:
resnet18_ncnn_model/
├── model.ncnn.param
├── model.ncnn.bin
└── model_ncnn.pytorch2ncnn() يتحقق من ncnn و pnnx عند الاستخدام الأول.
تصدير إلى MNN
يتطلب تصدير MNN ملف ONNX كمدخل. قم بالتصدير إلى ONNX أولاً، ثم قم بالتحويل:
from ultralytics.utils.export import onnx2mnn, torch2onnx
torch2onnx(model, im, output_file="resnet18.onnx")
onnx2mnn("resnet18.onnx", output_file="resnet18.mnn")يدعم half=True لـ FP16 و int8=True لتكميم INT8. يتطلب MNN>=2.9.6 و torch>=1.10.
تصدير إلى PaddlePaddle
from ultralytics.utils.export import torch2paddle
torch2paddle(model, im, output_dir="resnet18_paddle_model")يحتوي الدليل على نموذج PaddlePaddle وملفات المعلمات:
resnet18_paddle_model/
├── model.pdmodel
└── model.pdiparamsيتطلب x2paddle وتوزيع PaddlePaddle الصحيح لمنصتك:
paddlepaddle-gpu>=3.0.0,<3.3.0على CUDApaddlepaddle==3.0.0على ARM64 CPUpaddlepaddle>=3.0.0,<3.3.0على وحدات CPU أخرى
غير مدعوم على NVIDIA Jetson.
تصدير إلى ExecuTorch
from ultralytics.utils.export import torch2executorch
torch2executorch(model, im, output_dir="resnet18_executorch_model")يتم حفظ ملف .pte المصدر داخل دليل المخرجات:
resnet18_executorch_model/
└── model.pteيتطلب torch>=2.9.0 وبيئة تشغيل ExecuTorch مطابقة (pip install executorch). لمعرفة كيفية الاستخدام أثناء التشغيل، راجع تكامل ExecuTorch.
التحقق من النموذج المُصدر
بعد التصدير، تحقق من التكافؤ الرقمي مع نموذج PyTorch الأصلي قبل الشحن. اختبار سريع مع ONNXBackend من ultralytics.nn.backends يقارن المخرجات ويحدد أخطاء التتبع أو التكميم في وقت مبكر:
import numpy as np
import timm
import torch
from ultralytics.nn.backends import ONNXBackend
model = timm.create_model("resnet18", pretrained=True).eval()
im = torch.randn(1, 3, 224, 224)
with torch.no_grad():
pytorch_output = model(im).numpy()
onnx_model = ONNXBackend("resnet18.onnx", device=torch.device("cpu"))
onnx_output = onnx_model(im)[0]
diff = np.abs(pytorch_output - onnx_output).max()
print(f"Max difference: {diff:.6f}") # should be < 1e-5بالنسبة لتصديرات FP32، يجب أن يكون أقصى فرق مطلق أقل من 1e-5. تشير الاختلافات الأكبر إلى عمليات غير مدعومة، أو شكل إدخال غير صحيح، أو نموذج ليس في وضع التقييم. تصديرات FP16 و INT8 لها تفاوتات أكثر مرونة. تحقق من البيانات الحقيقية بدلاً من الموترات العشوائية.
بالنسبة لبيئات التشغيل الأخرى، قد يختلف اسم موتر الإدخال. على سبيل المثال، يستخدم OpenVINO اسم وسيط التمرير للنموذج (عادةً x للنماذج العامة)، بينما torch2onnx يستخدم افتراضياً "images".
القيود المعروفة
- دعم تعدد المدخلات غير متساوٍ:
torch2onnxوtorch2openvinoيقبل صفاً أو قائمة من موترات الأمثلة للنماذج ذات المدخلات المتعددة.torch2torchscript,torch2coreml,torch2ncnn,torch2paddle، وtorch2executorchيفترض موتر إدخال واحد. - يحتاج ExecuTorch إلى
flatc: تتطلب بيئة تشغيل ExecuTorch مترجم FlatBuffers. قم بالتثبيت باستخدامbrew install flatbuffersعلى نظام macOS أوapt install flatbuffers-compilerعلى Ubuntu. - لا يوجد استنتاج عبر Ultralytics: لا يمكن تحميل نماذج غير YOLO المصدرة مرة أخرى من خلال
YOLO()للاستنتاج. استخدم بيئة التشغيل الأصلية لكل تنسيق (ONNX Runtime, OpenVINO Runtime، إلخ). - تنسيقات YOLO فقط: Axelera و Sony IMX500 تتطلب التصديرات سمات نموذج خاصة بـ YOLO وغير متاحة للنماذج العامة.
- تنسيقات خاصة بالمنصة: TensorRT تتطلب NVIDIA GPU. RKNN تتطلب
rknn-toolkit2SDK (لنظام Linux فقط). Edge TPU تتطلبedgetpu_compilerالثنائي (لنظام Linux فقط).
الأسئلة الشائعة
ما النماذج التي يمكنني تصديرها باستخدام Ultralytics؟
أي torch.nn.Module. يشمل ذلك النماذج من timm، أو torchvision، أو أي نموذج PyTorch مخصص. يجب أن يكون النموذج في وضع التقييم (model.eval()) قبل التصدير. يقبل ONNX و OpenVINO بالإضافة إلى ذلك صفاً من موترات الأمثلة للنماذج متعددة المدخلات.
ما تنسيقات التصدير التي تعمل بدون GPU؟
يمكن لجميع التنسيقات المدعومة (TorchScript، ONNX، OpenVINO، CoreML، TF SavedModel، TF Frozen Graph، NCNN، PaddlePaddle، MNN، ExecuTorch) التصدير على CPU. لا يلزم وجود GPU لعملية التصدير نفسها. TensorRT هو التنسيق الوحيد الذي يتطلب NVIDIA GPU.
ما إصدار Ultralytics الذي أحتاجه؟
استخدم Ultralytics >=8.4.38، والذي يتضمن وحدة ultralytics.utils.export و output_file/output_dir.
هل يمكنني تصدير نموذج torchvision إلى CoreML لنشره على iOS؟
نعم. تُصدر مصنفات torchvision، والكاشفات، ونماذج التجزئة إلى .mlpackageأحد أبرز التحسينات هو سرعة الاستدلال على CPU. نظرًا لبنيته المحسنة وإزالة DFL، يقدم YOLO26 torch2coreml. بالنسبة لنماذج تصنيف الصور، مرر قائمة بأسماء الفئات إلى classifier_names لدمج رأس التصنيف. قم بتشغيل التصدير على macOS أو Linux. لا يتم دعم CoreML على Windows. راجع تكامل CoreML للحصول على تفاصيل النشر على iOS.
هل يمكنني تكميم النموذج المصدر الخاص بي إلى INT8 أو FP16؟
نعم، بالنسبة للعديد من التنسيقات. مرر half=True لـ FP16 أو int8=True لـ INT8 عند التصدير إلى OpenVINO، أو CoreML، أو MNN، أو NCNN. يتطلب INT8 في OpenVINO بالإضافة إلى ذلك وسيط calibration_dataset لـ تكميم ما بعد التدريب. راجع صفحة تكامل كل تنسيق للحصول على مقايضات التكميم.