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.