7.7. Normalisering¶
ml.Model.predict() tar en lista med indata eftersom vissa nätverk har mer än en indatatensor, men listan har inget sätt att bära argument per indata inline – det finns ingen kwarg-plats för ”beskär denna indata till (x, y, w, h) men lämna de andra indatan ifred”. ml.preprocessing.Normalization är omslaget som fyller den luckan. En Normalization-instans håller parametrarna för en indata; skriptet skickar den inslagna indatan i predict-listan närhelst det behöver något annat än standardvärdena.
Det vanligaste skälet att ta till det är att beskära ett specifikt område av den infångade bildrutan in i nätverket istället för hela bilden.
7.7.1. Parametrar¶
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)-rektangel i källbildrutan att beskära innan storleksändring. Standardvärdet är hela bildrutan. De flesta användningar avNormalizationsätter bara denna parameter.scale– det(min, max)-intervall som flyttalsindatatensorer förväntar sig efter normalisering. Pixelintervallet0..255mappas linjärt in i detta intervall. Vanliga värden är(0.0, 1.0)för ReLU-tränade nätverk och(-1.0, 1.0)för symmetriskt normaliserade nätverk.mean– medelvärde per kanal(R, G, B)som subtraheras från bilden efter skalning. Matchar den kanalstatistik som nätverket tränades mot –(0.485, 0.456, 0.406)för ImageNet-härledda nätverk är det kanoniska exemplet. Gråskalenätverk reducerar medelvärdet till ett luma-värde med standardformeln0.299*R + 0.587*G + 0.114*B.stdev– standardavvikelse per kanal(R, G, B)som bilden divideras med efter att medelvärdet subtraherats, återigen matchande nätverkets träningsstatistik. Reduceras till luma på samma sätt för gråskalenätverk.
7.7.2. När parametrar spelar roll¶
scale, mean och stdev ignoreras när nätverkets input_dtype är int8 eller uint8. För nätverk med heltalsindata skrivs den beskurna bildens byte direkt in i tensorn och nätverkets egna input_scale och input_zero_point hanterar omvandlingen från heltal till reellt tal. De tre parametrarna spelar roll endast när nätverket förväntar sig flyttalsindata.
roi läses i samtliga fall – den styr vilken del av källbildrutan som når nätverket oavsett indata-dtype.
7.7.3. ROI och storleksändring¶
ROI:n skalas bilinjärt från sina källdimensioner till nätverkets indatadimensioner. Bilden centreras i destinationen och skalningen fyller destinationen – den bevarar inte bildförhållandet. En icke-kvadratisk ROI som matas till en kvadratisk nätverksindata kommer ut horisontellt eller vertikalt sträckt.
Huruvida sträckningen spelar roll beror på nätverket. Ansiktsdetektering och landmärkesmodeller som MediaPipe-familjen (BlazeFace, FaceLandmarks, HandLandmarks, MoveNet) tränades mot kvadratiska beskärningar och försämras snabbt när indatans bildförhållande är fel; för dessa behöver applikationen ge dem en kvadratisk ROI – antingen genom att fånga in i en kvadratisk bildstorlek via window() eller genom att beskära med parametern roi=. Objektdetektorer av YOLO-familjen tränas vanligtvis med augmentering som inkluderar slumpmässiga sträckningar och accepterar icke-kvadratiska ROI:er utan större noggrannhetsförlust; att skicka in hela den infångade bildrutan direkt går oftast bra.
När nätverkets indatadimensioner matchar ROI:n exakt kollapsar skalningen till en kopia, vilket är det billigaste fallet.
7.7.4. Åsidosätta standardvärdet¶
predict() slår automatiskt in varje image.Image-indata med Normalization() – standardparametrarna ovan. De flesta modeller som levereras med kameran tränades mot pixelintervall som standardvärdena redan täcker, så det vanliga fallet är att skicka bilden direkt:
result = model.predict([img])
För att använda en anpassad ROI – den vanligaste åsidosättningen – bygg en Normalization med ROI:n satt och bind bilden till den:
from ml.preprocessing import Normalization
norm = Normalization(roi=(80, 60, 160, 120))
result = model.predict([norm(img)])
För att matcha ett nätverks kanalstatistik från träningstillfället, sätt flyttalsparametrarna:
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)])
Att anropa Normalization-instansen på bilden returnerar en ny bunden instans som motorn fyller tensorn från. Den bundna instansen är vad predict accepterar i stället för den råa bilden, och eftersom det är ett objekt per indata kan ett nätverk med flera indata blanda bilder med olika ROI:er i samma predict-lista.
För nätverk som förväntar sig indata som applikationen redan har producerat i tensorform – en buffert från en kringutrustning, en ndarray beräknad av en annan pipeline, icke-bildbaserade numeriska data – hoppa över Normalization helt och hållet och skicka ndarray:en eller ett anropbart objekt som producerar den. predict() skickar dessa vidare till motorn utan att slå in dem.