7.8. Tensor-I/O¶
De engine accepteert één enkele tensor aan de invoerkant en produceert er één of meer aan de uitvoerkant. De tensoren zijn ndarray-objecten met de vorm, dtype en descriptorwoordenschat die in het numpy-hoofdstuk zijn geïntroduceerd. Hun vormen en dtypes komen uit het modelbestand en worden gerapporteerd via input_shape / output_shape en input_dtype / output_dtype.
7.8.1. Kwantisatie¶
De meeste netwerken die de cam draait, werken met gekwantiseerde integer-tensoren – int8 of uint8 – om binnen het RAM- en rekenbudget van de cam te passen. Een gekwantiseerde tensor draagt integer-waarden die reëelwaardige getallen representeren via een schaal en nulpunt per tensor:
De schaal en het nulpunt komen uit de trainingstijd-kalibratie van het model en worden opgeslagen in het modelbestand. Ze worden blootgesteld als input_scale, input_zero_point, output_scale en output_zero_point – elk een lijst met één vermelding per invoer- of uitvoertensor.
ml.utils.quantize() en ml.utils.dequantize() passen de formules toe tegen een opgegeven uitvoerindex:
import ml.utils
real_tensor = ml.utils.dequantize(model, q_tensor, index=0)
q_tensor = ml.utils.quantize(model, real_tensor, index=0)
Beide functies geven de waarde ongewijzigd terug wanneer de uitvoer-dtype op de gegeven index al float is, zodat de aanroep veilig is ongeacht de kwantisatiestatus van het model.
7.8.2. Wat het script aan de uitvoerkant ziet¶
Wat predict() teruggeeft, hangt af van of er een post-processor is geregistreerd.
Zonder post-processor worden de ruwe integer-uitvoeren van de engine automatisch gedekwantiseerd naar float en teruggegeven als een lijst van float ndarray-objecten. Het script ontvangt reëelwaardige getallen die klaar zijn om te lezen. Dit is het juiste pad voor classificatienetwerken, waarvan de enkele uitvoertensor al een lijst is met betrouwbaarheidsscores per klasse waar de applicatie overheen itereert – geen decoderingsstap nodig. Het is ook het eenvoudige pad om een onbekend model snel aan de praat te krijgen of voor ad-hoc-inspectie vanuit de REPL.
Met een geregistreerde post-processor (via postprocess= op de constructor of callback= op de predict-aanroep) worden de ruwe gekwantiseerde tensoren rechtstreeks aan de callable van de post-processor overhandigd. De post-processor ontvangt de ruwe gekwantiseerde tensoren en is verantwoordelijk voor welke dekwantisatie het ook nodig heeft.
De splitsing is een prestatiekeuze. Automatische dekwantisatie reserveert een nieuwe float-tensor voor elke uitvoer en loopt elk element af. Een post-processor die slechts enkele waarden uit elke tensor nodig heeft – de betrouwbaarheidsscores afkappen met een drempelwaarde en vervolgens begrenzingsvakken decoderen voor de overlevenden – slaat de kosten over van het dekwantiseren van de rest. De box-decoders die onder ml.postprocessing worden meegeleverd, nemen allemaal deze route, en ml.utils.threshold() is precies voor dit geval gebouwd: het neemt een gekwantiseerde score-tensor en geeft de indices terug waarvan de gedekwantiseerde waarden een reëelwaardige drempelwaarde passeren, zonder de hele tensor te dekwantiseren.