7.7. Normalizare¶
ml.Model.predict() primește o listă de intrări deoarece unele rețele au mai mult de un tensor de intrare, dar lista nu are nicio modalitate de a transporta argumente per intrare în linie – nu există un slot pentru argumente cu cuvânt-cheie pentru „decupează această intrare la (x, y, w, h) dar lasă celelalte intrări neatinse”. ml.preprocessing.Normalization este învelișul care umple acest gol. O instanță Normalization păstrează parametrii pentru o singură intrare; scriptul transmite intrarea învelită în lista predict ori de câte ori are nevoie de altceva decât valorile implicite.
Cel mai frecvent motiv pentru a apela la ea este de a decupa o anumită regiune a cadrului capturat pentru a o transmite rețelei, în loc de întreaga imagine.
7.7.1. Parametri¶
Normalization(scale=(0.0, 1.0),
mean=(0.0, 0.0, 0.0),
stdev=(1.0, 1.0, 1.0),
roi=None)
roi– dreptunghiul(x, y, w, h)din cadrul sursă care urmează să fie decupat înainte de redimensionare. Implicit este întregul cadru. Majoritatea utilizărilor luiNormalizationsetează doar acest parametru.scale– intervalul(min, max)pe care tensorii de intrare în virgulă mobilă îl așteaptă după normalizare. Intervalul de pixeli0..255este mapat liniar în acest interval. Valorile frecvente sunt(0.0, 1.0)pentru rețelele antrenate cu ReLU și(-1.0, 1.0)pentru rețelele normalizate simetric.mean– media per canal(R, G, B)scăzută din imagine după scalare. Corespunde statisticilor de canal pe care a fost antrenată rețeaua –(0.485, 0.456, 0.406)pentru rețelele derivate din ImageNet este exemplul canonic. Rețelele în tonuri de gri reduc media la o valoare de luminanță folosind formula standard0.299*R + 0.587*G + 0.114*B.stdev– abaterea standard per canal(R, G, B)la care imaginea este împărțită după scăderea mediei, corespunzând din nou statisticilor de antrenare ale rețelei. Redusă la luminanță în același mod pentru rețelele în tonuri de gri.
7.7.2. Când contează parametrii¶
scale, mean și stdev sunt ignorate atunci când input_dtype al rețelei este int8 sau uint8. Pentru rețelele cu intrare întreagă, octeții imaginii decupate sunt scriși direct în tensor, iar input_scale și input_zero_point proprii rețelei gestionează conversia din întreg în valori reale. Cei trei parametri contează doar atunci când rețeaua așteaptă intrare în virgulă mobilă.
roi este citit în fiecare caz – controlează ce parte a cadrului sursă ajunge la rețea, indiferent de dtype-ul intrării.
7.7.3. ROI și redimensionare¶
ROI-ul este scalat biliniar de la dimensiunile sale sursă la dimensiunile de intrare ale rețelei. Imaginea este centrată în destinație, iar scalarea umple destinația – nu păstrează raportul de aspect. Un ROI nepătrat transmis unei intrări pătrate de rețea iese întins orizontal sau vertical.
Dacă întinderea contează sau nu depinde de rețea. Modelele de detectare a fețelor și de repere precum familia MediaPipe (BlazeFace, FaceLandmarks, HandLandmarks, MoveNet) au fost antrenate pe decupaje pătrate și se degradează rapid când raportul de aspect al intrării nu este corect; pentru acestea, aplicația trebuie să le ofere un ROI pătrat – fie prin capturarea la o dimensiune de cadru pătrată prin window(), fie prin decupare cu parametrul roi=. Detectoarele de obiecte din familia YOLO sunt de obicei antrenate cu augmentare care include întinderi aleatorii și acceptă ROI-uri nepătrate fără pierderi mari de precizie; transmiterea directă a întregului cadru capturat este de obicei în regulă.
Atunci când dimensiunile de intrare ale rețelei se potrivesc exact cu ROI-ul, scalarea se reduce la o copiere, ceea ce este cazul cel mai economic.
7.7.4. Suprascrierea valorilor implicite¶
predict() învelește automat fiecare intrare image.Image cu Normalization() – parametrii impliciți de mai sus. Majoritatea modelelor livrate împreună cu camera au fost antrenate pe intervale de pixeli pe care valorile implicite le acoperă deja, așa că în cazul frecvent imaginea se transmite direct:
result = model.predict([img])
Pentru a folosi un ROI personalizat – cea mai frecventă suprascriere – construiți un Normalization cu ROI-ul setat și legați imaginea de el:
from ml.preprocessing import Normalization
norm = Normalization(roi=(80, 60, 160, 120))
result = model.predict([norm(img)])
Pentru a corespunde statisticilor de canal din timpul antrenării unei rețele, setați parametrii în virgulă mobilă:
norm = Normalization(scale=(0.0, 1.0),
mean=(0.485, 0.456, 0.406),
stdev=(0.229, 0.224, 0.225))
result = model.predict([norm(img)])
Apelarea instanței Normalization asupra imaginii returnează o nouă instanță legată din care motorul umple tensorul. Instanța legată este ceea ce predict acceptă în locul imaginii brute și, deoarece este un obiect per intrare, o rețea cu intrări multiple poate combina imagini cu ROI-uri diferite în aceeași listă predict.
Pentru rețelele care așteaptă intrări pe care aplicația le-a produs deja sub formă de tensor – un tampon de la un periferic, un ndarray calculat de altă conductă, date numerice care nu sunt imagini – omiteți complet Normalization și transmiteți ndarray-ul sau un obiect apelabil care îl produce. predict() le transmite acestea către motor fără a le înveli.