Paddle
Un modèle d'inférence PaddlePaddle, c'est un graphe model.pdmodel accompagné d'un fichier de poids model.pdiparams. LibreYOLO exporte un graphe ONNX statique en opset 15, le convertit avec X2Paddle et empaquette le résultat avec un metadata.yaml pour qu'il se charge par la même factory que tous les autres runtimes.
- Flag
export(format="paddle")- Écrit
- Un répertoire contenant model.pdmodel, model.pdiparams et metadata.yaml
- Extra
pip install "libreyolo[paddle]"- Se recharge avec
LibreYOLO("weights/LibreYOLO9t_paddle", device="cpu")- Backend
libreyolo.backends.paddle.PaddleBackend- Formes
- Statiques, batch 1, opset 15. Les trois sont imposés.
- Précision
- FP32 uniquement, CPU uniquement.
- Chaîne d'outils
- PaddlePaddle 2.6.2, X2Paddle 1.6.0, ONNX 1.17 ou antérieur, vérifiés exactement
Installation
# Python 3.10 à 3.12. WSL2 avec Ubuntu 22.04 est le chemin Windows validé.pip install "libreyolo[paddle]"python -c "from importlib.metadata import version; print(version('paddlepaddle'), version('x2paddle'), version('onnx'))"L'extra épingle exactement la pile sur laquelle la parité a été mesurée :
PaddlePaddle 2.6.2, X2Paddle 1.6.0 et ONNX 1.17 ou antérieur. Ces épinglages sont
vérifiés au moment de l'export, pas seulement à l'installation, et une version
différente lève une ImportError qui nomme celle attendue. Les versions plus
récentes de Paddle rejettent une partie du code statique que génère X2Paddle
1.6.0 ; échouer tôt vaut donc mieux que produire un artefact que personne n'a
validé.
Export
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9t.pt") # Écrit le répertoire weights/LibreYOLO9t_paddlepath = model.export(format="paddle")print(path)libreyolo export --model LibreYOLO9t.pt --format paddlemodel.export( format="paddle", imgsz=640, # int, le canevas carré de cette famille batch=1, # toute autre valeur lève ValueError dynamic=False, # True lève ValueError simplify=True, # False lève ValueError opset=15, # toute autre valeur lève ValueError output_path=None, # None écrit weights/<stem>_paddle)Quatre arguments sont figés plutôt que dotés d'une valeur par défaut. dynamic
doit valoir False, batch doit valoir 1, simplify doit valoir True pour
obtenir un graphe de conversion entièrement statique, et opset doit valoir 15,
le plafond qu'accepte X2Paddle 1.6.0. Passer autre chose lève avant le tracing.
Une seule normalisation s'applique au graphe intermédiaire. ONNX définit une dilatation MaxPool omise comme valant un, PyTorch écrit explicitement l'attribut rempli de uns, et X2Paddle 1.6.0 le rejette : l'exporteur supprime donc cette valeur par défaut redondante et laisse l'opération spécifiée inchangée.
L'artefact est un répertoire : model.pdmodel, model.pdiparams et
metadata.yaml. Le code Python que X2Paddle génère pendant la conversion n'en
fait pas partie.
Exécuter l'artefact
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("weights/LibreYOLO9t_paddle", device="cpu")result = model.predict(SAMPLE_IMAGE)print(result.boxes.xyxy[:3])libreyolo predict --model weights/LibreYOLO9t_paddle \ --source https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpg --device cpu --savefrom libreyolo.backends.paddle import PaddleBackend # Ce que LibreYOLO() construit pour un répertoire Paddle. Le même objet# Results, sans routage par la factory entre les deux.backend = PaddleBackend("weights/LibreYOLO9t_paddle", device="cpu")result = backend.predict("parkour.jpg")print(result.boxes.xyxy[:3])import numpy as npimport paddle.inference as paddle_inferimport yaml directory = "weights/LibreYOLO9t_paddle"config = paddle_infer.Config( f"{directory}/model.pdmodel", f"{directory}/model.pdiparams")config.disable_gpu()config.disable_mkldnn()config.switch_ir_optim(False) predictor = paddle_infer.create_predictor(config)handle = predictor.get_input_handle(predictor.get_input_names()[0])handle.reshape([1, 3, 640, 640])handle.copy_from_cpu(np.zeros((1, 3, 640, 640), dtype=np.float32))predictor.run()for name in predictor.get_output_names(): print(name, predictor.get_output_handle(name).copy_to_cpu().shape) meta = yaml.safe_load(open(f"{directory}/metadata.yaml"))print(meta["model_family"], meta["task"], meta["names"]) # Le prétraitement et le postprocessing sont à votre charge ici.LibreYOLO() reconnaît tout répertoire contenant à la fois model.pdmodel et
model.pdiparams, lit metadata.yaml et renvoie le même objet Results que le
checkpoint. Un device autre que auto ou cpu lève : ce backend fonctionne
uniquement sur CPU.
Ce que la factory construit, c'est PaddleBackend, exporté depuis libreyolo et
importable sous libreyolo.backends.paddle.PaddleBackend. Construisez-le
vous-même quand vous voulez le backend sans le routage par suffixe de la factory,
par exemple pour passer task= explicitement sur un répertoire dont vous n'avez
pas écrit le metadata.yaml. Son predict() accepte les mêmes sources et renvoie
les mêmes résultats.
Le snippet en runtime brut reprend ce que configure le backend, et les trois options désactivées le sont délibérément. Le pipeline de fusion CPU de Paddle 2.6 peut planter en optimisant les grands graphes gather et scatter émis pour l'attention déformable ; c'est donc sur le graphe statique portable et non fusionné que la parité a été mesurée. Le prétraitement, le décodage, le NMS et le rééchelonnement des coordonnées sont à votre charge sur ce chemin.
Contraintes
Pas de formes dynamiques, pas de FP16, pas d'INT8, pas de NMS intégré, pas de runtime GPU.
Les combinaisons validées sont la détection YOLO9, la détection YOLO9-E2E et YOLO9-P2, la détection, l'estimation de pose et la segmentation EC, la détection RT-DETRv4, D-FINE, DEIM et DEIMv2, et la détection et l'estimation de pose YOLO-NAS. Chacune est couverte par la conversion, un rechargement du runtime sur CPU, une parité des sorties brutes et des résultats publics appariés.
Bloquées, avec la raison enregistrée pour chaque combinaison :
| Combinaison | Pourquoi |
|---|---|
| RF-DETR, toutes tâches | Exige l'opset ONNX 17 et GridSample ; X2Paddle 1.6.0 accepte l'opset 15 ou inférieur et n'a pas de mapper GridSample |
| Détection RT-DETR et RT-DETRv2 | Les graphes entraînés exigent GridSample à l'opset 16 ou plus récent |
| Segmentation D-FINE | Se convertit et se recharge, mais l'erreur RMS relative des logits de masque est de 3.52 % et l'IoU minimal des masques appariés est de 0.582 |
| Segmentation YOLO9 | YOLO9 ne fait que de la détection dans LibreYOLO |
| Segmentation RTMDet-Ins | Le décodage de masque à noyaux dynamiques n'a pas de contrat de runtime exporté |
Tout ce qui n'est listé ni comme validé ni comme bloqué est refusé, avec la note indiquant que cela n'a pas été validé via le chemin de conversion ONNX vers Paddle.
Pour la grille complète des familles et des tâches, voir la matrice d'export. Pour une seule combinaison :
libreyolo formats --family yolo9 --task detect