كيفية تصدير نماذج 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 في أي من الحالتين.

الصيغةالوظيفةتثبيتالمخرجات
ONNXtorch2onnx()pip install onnx.onnx ملف
TorchScripttorch2torchscript()مضمنة مع PyTorch.torchscript ملف
OpenVINOtorch2openvino()pip install openvino_openvino_model/الدليل
CoreMLtorch2coreml()pip install coremltools.mlpackage
TF SavedModelonnx2saved_model()انظر المتطلبات التفصيلية أدناه_saved_model/الدليل
TF Frozen Graphkeras2pb()انظر المتطلبات التفصيلية أدناه.pb ملف
NCNNtorch2ncnn()pip install ncnn pnnx_ncnn_model/الدليل
MNNonnx2mnn()pip install MNN.mnn ملف
PaddlePaddletorch2paddle()pip install paddlepaddle x2paddle_paddle_model/الدليل
ExecuTorchtorch2executorch()pip install executorch_executorch_model/الدليل
ONNX كتنسيق وسيط

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)
استدعِ دائماً `model.eval()` قبل التصدير

طبقات 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.

خطأ `BlobWriter not loaded`

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.0
  • onnx2tf>=1.26.3,<1.29.0
  • tf_keras<=2.19.0
  • sng4onnx>=1.0.1
  • onnx_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.71
  • onnx>=1.12.0,<2.0.0
  • protobuf>=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.py

torch2ncnn() يتحقق من 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 على CUDA
  • paddlepaddle==3.0.0 على ARM64 CPU
  • paddlepaddle>=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-toolkit2 SDK (لنظام 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 لـ تكميم ما بعد التدريب. راجع صفحة تكامل كل تنسيق للحصول على مقايضات التكميم.

التعليقات