7.12. Post-procesoare¶
O rețea de detectare nu emite casete. Emite unul sau mai mulți tensori a căror dispunere depinde de arhitectura pe care a fost antrenat modelul – un tensor 2-D de predicții candidate pentru un detector din familia YOLO, o pereche de tensori (boxes, scores) pentru un detector MediaPipe, o listă plată de coordonate de puncte-cheie pentru o rețea de poziție. Aplicația nu poate citi niciunul dintre aceștia direct; ceea ce dorește – o listă de casete, o listă de puncte-cheie, o descompunere pe clase – trebuie decodat din tensorul brut.
Acel decodor este un post-procesor. Modulul ml.postprocessing îi grupează după ecosistemul sursă.
7.12.1. Darknet¶
ml.postprocessing.darknet decodează modele din era YOLO originală. YOLO v2 a introdus ideile de grilă și ancoră pe care majoritatea detectoarelor ulterioare le-au moștenit într-o anumită formă, așa că dispunerea v2 este cel mai curat punct de plecare.
YOLO v2 începe prin împărțirea imaginii de intrare într-o grilă grosieră – o dispunere de 13 pe 13 pentru intrarea canonică de 416 pixeli, mai mică pentru modele mai mici – și antrenează rețeaua astfel încât fiecare celulă de grilă să fie responsabilă pentru detectarea oricărui obiect al cărui centru cade în interiorul ei. Dispunerea spațială a tensorului de ieșire reflectă dispunerea intrării: o poziție în ieșire pentru fiecare celulă din imagine.
La fiecare celulă de grilă, rețeaua nu prezice o casetă din senin. Alege dintre mai multe forme de referință prestabilite numite ancore – perechi fixe (width, height) derivate offline prin gruparea dimensiunilor casetelor din setul de antrenament astfel încât să acopere obiectele tipice pe care modelul se așteaptă să le vadă. Sarcina rețelei la fiecare celulă este să prezică, pentru fiecare ancoră, o mică deplasare a centrului casetei în interiorul celulei, o scalare a lățimii și înălțimii ancorei, un scor de obiectivitate (probabilitatea ca ceva să fie acolo) și un vector de probabilitate pe clase. O grilă de 13 pe 13 cu cele 5 ancore implicite și 20 de clase emite deci 13 * 13 * 5 * (4 + 1 + 20) = 21,125 numere per inferență.
YoloV2 decodează acea dispunere: parcurge celulele, aplică deplasările și scalările fiecărei ancore pentru a recupera coordonatele absolute ale casetei, combină obiectivitatea cu probabilitatea de clasă pentru un scor pe clasă, aplică pragul și transmite supraviețuitorii către NMS. Clasa preia un argument de constructor anchors= când modelul a fost antrenat față de un tabel de ancore personalizat și recurge la o valoare implicită încorporată în caz contrar. Variante reglate pentru seturi specifice de clase sunt livrate în același submodul.
7.12.2. Ultralytics¶
ml.postprocessing.ultralytics decodează generațiile YOLO mai noi. YoloV8 citește o ieșire orientată pe coloane, unde fiecare coloană este o predicție de ancoră ce conține coordonatele casetei și un vector de scor pe clase – canalul de obiectivitate pe care îl purtau ieșirile YOLO anterioare a fost eliminat în v8, iar scorurile de clasă stau de sine stătătoare. Parcurgerea pas cu pas a YOLOv8 parcurge decodarea tensor cu tensor. Versiuni mai vechi din era Ultralytics sunt livrate în același submodul pentru modele antrenate față de dispunerile lor.
7.12.3. MediaPipe¶
ml.postprocessing.mediapipe decodează familia ușoară de la Google, destinată rulării pe dispozitiv. BlazeFace este detectorul de fețe tratat în hello-blazeface: un detector rapid bazat pe ancore care emite casete și șase coordonate de repere per față, returnate ca tupluri (box, score, keypoints) cu reperele atașate fiecărei casete, nu ca o listă de ieșire separată. Modele de detectare a mâinilor, de repere și de poziție din aceeași familie sunt livrate alături de el și urmează aceeași formă de returnare cu puncte-cheie atașate.
7.12.4. Alegerea unuia¶
Post-procesorul potrivit este determinat de arhitectura pe care a fost antrenat modelul, nu de ceea ce dorește aplicația. Un .tflite YOLOv8 se decodează corect doar prin YoloV8; un .tflite BlazeFace doar prin BlazeFace. Alegerea post-procesorului face parte din alegerea modelului. Când arhitectura unui model nu este reprezentată de un post-procesor livrat, scrierea propriului post-procesor este simplă.
Rețelele de clasificare sunt excepția. Singurul lor tensor de ieșire este deja ceea ce dorește aplicația – o listă de scoruri pe clase – și nu este nevoie de niciun post-procesor. Încărcarea modelului fără postprocess= și citirea rezultatului predicției ca un ndarray plat este calea corectă, așa cum a tratat I/O de tensori.