7.7. Normalization¶
ml.Model.predict() neemt een lijst met invoer omdat sommige netwerken meer dan één invoertensor hebben, maar de lijst heeft geen manier om argumenten per invoer inline mee te dragen – er is geen kwarg-slot voor “snij deze invoer bij tot (x, y, w, h) maar laat de andere invoer met rust”. ml.preprocessing.Normalization is de wrapper die dat gat opvult. Een Normalization-instantie bevat de parameters voor één invoer; het script geeft de gewrapte invoer door in de predict-lijst wanneer het iets anders dan de standaardwaarden nodig heeft.
De meest voorkomende reden om ernaar te grijpen is om een specifiek gebied van het vastgelegde frame in het netwerk bij te snijden in plaats van de hele afbeelding.
7.7.1. Parameters¶
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)rechthoek in het bronframe die vóór het schalen wordt bijgesneden. Standaard het hele frame. De meeste toepassingen vanNormalizationstellen alleen deze parameter in.scale– het(min, max)-bereik dat float-invoertensoren na normalisatie verwachten. Het pixelbereik0..255wordt lineair op dit bereik afgebeeld. Veelvoorkomende waarden zijn(0.0, 1.0)voor met ReLU getrainde netwerken en(-1.0, 1.0)voor symmetrisch genormaliseerde netwerken.mean– het(R, G, B)-gemiddelde per kanaal dat na het schalen van de afbeelding wordt afgetrokken. Komt overeen met de kanaalstatistieken waartegen het netwerk is getraind –(0.485, 0.456, 0.406)voor van ImageNet afgeleide netwerken is het canonieke voorbeeld. Grijswaardennetwerken reduceren het gemiddelde tot een luma-waarde met de standaard0.299*R + 0.587*G + 0.114*B.stdev– de(R, G, B)-standaardafwijking per kanaal waardoor de afbeelding wordt gedeeld nadat het gemiddelde is afgetrokken, opnieuw overeenkomend met de trainingsstatistieken van het netwerk. Voor grijswaardennetwerken op dezelfde manier tot luma gereduceerd.
7.7.2. Wanneer parameters ertoe doen¶
scale, mean en stdev worden genegeerd wanneer de input_dtype van het netwerk int8 of uint8 is. Voor netwerken met integer-invoer worden de bytes van de bijgesneden afbeelding rechtstreeks in de tensor geschreven en handelen de eigen input_scale en input_zero_point van het netwerk de int-naar-reëel-conversie af. De drie parameters doen er alleen toe wanneer het netwerk drijvende-komma-invoer verwacht.
roi wordt in elk geval gelezen – het bepaalt welk deel van het bronframe het netwerk bereikt, ongeacht de invoer-dtype.
7.7.3. ROI en schalen¶
De ROI wordt bilineair geschaald van zijn brondimensies naar de invoerdimensies van het netwerk. De afbeelding wordt in de bestemming gecentreerd en het schalen vult de bestemming – het behoudt de beeldverhouding niet. Een niet-vierkante ROI die aan een vierkante netwerkinvoer wordt gegeven, komt er horizontaal of verticaal uitgerekt uit.
Of het uitrekken ertoe doet, hangt af van het netwerk. Gezichtsdetectie- en oriëntatiepuntmodellen zoals de MediaPipe-familie (BlazeFace, FaceLandmarks, HandLandmarks, MoveNet) zijn getraind tegen vierkante uitsnedes en verslechteren snel wanneer de beeldverhouding van de invoer afwijkt; voor die modellen moet de applicatie ze een vierkante ROI geven – ofwel door vast te leggen op een vierkante framesize via window(), ofwel door bij te snijden met de roi=-parameter. Objectdetectoren uit de YOLO-familie worden doorgaans getraind met augmentatie die willekeurige uitrekkingen omvat en accepteren niet-vierkante ROI’s zonder veel verlies aan nauwkeurigheid; het hele vastgelegde frame er rechtstreeks in doorgeven is meestal prima.
Wanneer de invoerdimensies van het netwerk exact overeenkomen met de ROI, valt het schalen samen tot een kopie, wat het goedkoopste geval is.
7.7.4. De standaard overschrijven¶
predict() wrapt elke image.Image-invoer automatisch met Normalization() – de bovenstaande standaardparameters. De meeste modellen die met de cam worden meegeleverd, zijn getraind tegen pixelbereiken die de standaardwaarden al dekken, dus het gangbare geval is om de afbeelding rechtstreeks door te geven:
result = model.predict([img])
Om een aangepaste ROI te gebruiken – de meest voorkomende override – bouw je een Normalization met de ROI ingesteld en bind je de afbeelding eraan:
from ml.preprocessing import Normalization
norm = Normalization(roi=(80, 60, 160, 120))
result = model.predict([norm(img)])
Om overeen te komen met de trainingstijd-kanaalstatistieken van een netwerk, stel je de drijvende-komma-parameters in:
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)])
Het aanroepen van de Normalization-instantie op de afbeelding geeft een nieuwe gebonden instantie terug waaruit de engine de tensor vult. De gebonden instantie is wat predict accepteert in plaats van de ruwe afbeelding, en omdat het een object per invoer is, kan een netwerk met meerdere invoeren afbeeldingen met verschillende ROI’s in dezelfde predict-lijst combineren.
Voor netwerken die invoer verwachten die de applicatie al in tensorvorm heeft geproduceerd – een buffer van een randapparaat, een ndarray die door een andere pijplijn is berekend, niet-afbeeldingsgebonden numerieke data – sla je Normalization volledig over en geef je de ndarray of een callable die deze produceert door. predict() geeft die zonder wrapping door aan de engine.