7.7. Normalizálás¶
A ml.Model.predict() egy listát vesz át bemenetekből, mert egyes hálózatoknak több bemeneti tenzoruk van, de a listának nincs módja arra, hogy bemenetenkénti argumentumokat inline módon hordozzon – nincs kulcsszó-hely arra, hogy „vágd ezt a bemenetet (x, y, w, h) méretre, de a többi bemenetet hagyd békén”. A ml.preprocessing.Normalization az a burkoló, amely betölti ezt a rést. Egy Normalization példány egyetlen bemenet paramétereit tartja; a szkript a becsomagolt bemenetet a predict listában adja át, valahányszor az alapértelmezettektől eltérő valamire van szüksége.
A leggyakoribb ok, amiért hozzá nyúlunk, az, hogy a rögzített képkocka egy adott területét vágjuk a hálózatba az egész kép helyett.
7.7.1. Paraméterek¶
Normalization(scale=(0.0, 1.0),
mean=(0.0, 0.0, 0.0),
stdev=(1.0, 1.0, 1.0),
roi=None)
roi–(x, y, w, h)téglalap a forrásképkockában, amelyet az átméretezés előtt vágunk. Alapértelmezetten az egész képkocka. ANormalizationlegtöbb felhasználása csak ezt a paramétert állítja be.scale– az a(min, max)tartomány, amelyet a lebegőpontos bemeneti tenzorok a normalizálás után várnak. A0..255képponttartomány lineárisan képeződik le ebbe a tartományba. Gyakori értékek a(0.0, 1.0)a ReLU-ra tanított hálózatoknál és a(-1.0, 1.0)a szimmetrikusan normalizált hálózatoknál.mean– csatornánkénti(R, G, B)átlag, amelyet a skálázás után kivonunk a képből. Megfelel azoknak a csatornastatisztikáknak, amelyek ellenében a hálózatot tanították – a(0.485, 0.456, 0.406)az ImageNetből származó hálózatoknál a kanonikus példa. A szürkeárnyalatos hálózatok az átlagot egyetlen luma-értékre redukálják a szokásos0.299*R + 0.587*G + 0.114*Bképlettel.stdev– csatornánkénti(R, G, B)szórás, amellyel a képet elosztjuk az átlag kivonása után, ismét megfelelve a hálózat tanítási statisztikáinak. A szürkeárnyalatos hálózatoknál ugyanúgy luma-értékre redukálva.
7.7.2. Mikor számítanak a paraméterek¶
A scale, a mean és a stdev figyelmen kívül marad, amikor a hálózat input_dtype típusa int8 vagy uint8. Az egész számos bemenetű hálózatoknál a vágott kép bájtjai közvetlenül a tenzorba íródnak, és a hálózat saját input_scale és input_zero_point értékei kezelik az egész-valós átváltást. A három paraméter csak akkor számít, ha a hálózat lebegőpontos bemenetet vár.
A roi minden esetben beolvasásra kerül – ez vezérli, hogy a forrásképkocka melyik része jut el a hálózatba, függetlenül a bemeneti dtype-tól.
7.7.3. ROI és átméretezés¶
A ROI bilineárisan skálázódik a forrásdimenzióiról a hálózat bemeneti dimenzióira. A kép a célterületen középre kerül, és a skálázás kitölti a célt – nem őrzi meg a képarányt. Egy négyzetes hálózatbemenetbe betáplált, nem négyzetes ROI vízszintesen vagy függőlegesen megnyújtva jön ki.
Hogy a nyújtás számít-e, az a hálózattól függ. Az arcészlelési és landmark-modellek, mint a MediaPipe család (BlazeFace, FaceLandmarks, HandLandmarks, MoveNet), négyzetes vágatokon lettek tanítva, és gyorsan romlanak, ha a bemeneti képarány eltér; ezeknél az alkalmazásnak négyzetes ROI-t kell adnia – vagy egy négyzetes framesize-on való rögzítéssel a window() segítségével, vagy a roi= paraméterrel való vágással. A YOLO-családú objektumészlelőket jellemzően véletlenszerű nyújtásokat tartalmazó augmentációval tanítják, és különösebb pontosságvesztés nélkül fogadnak el nem négyzetes ROI-kat; a teljes rögzített képkocka közvetlen betáplálása általában megfelelő.
Amikor a hálózat bemeneti dimenziói pontosan megegyeznek a ROI-val, a skálázás másolássá egyszerűsödik, ami a legolcsóbb eset.
7.7.4. Az alapértelmezett felülírása¶
A predict() minden image.Image bemenetet automatikusan Normalization() objektummal csomagol be – a fenti alapértelmezett paraméterekkel. A kamerával szállított legtöbb modellt olyan képponttartományok ellenében tanították, amelyeket az alapértelmezések már lefednek, így a gyakori eset az, hogy a képet közvetlenül adjuk át:
result = model.predict([img])
Egyéni ROI használatához – a leggyakoribb felülíráshoz – építsünk egy Normalization objektumot beállított ROI-val, és kössük hozzá a képet:
from ml.preprocessing import Normalization
norm = Normalization(roi=(80, 60, 160, 120))
result = model.predict([norm(img)])
Egy hálózat tanításkori csatornastatisztikáinak illesztéséhez állítsuk be a lebegőpontos paramétereket:
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)])
A Normalization példány meghívása a képen egy új, lekötött példányt ad vissza, amelyből az engine kitölti a tenzort. A lekötött példányt fogadja el a predict a nyers kép helyett, és mivel ez egy bemenetenkénti objektum, egy többbemenetű hálózat különböző ROI-jú képeket keverhet ugyanabban a predict listában.
Azoknál a hálózatoknál, amelyek olyan bemeneteket várnak, amelyeket az alkalmazás már tenzorformában előállított – egy puffer egy perifériáról, egy másik folyamat által kiszámított ndarray, nem kép típusú numerikus adat –, teljesen hagyjuk ki a Normalization használatát, és adjuk át az ndarray-t vagy egy azt előállító meghívható objektumot. A predict() ezeket becsomagolás nélkül továbbítja az engine-nek.