7.4. Ein Modell laden

ml.Model liest eine Modelldatei aus dem Flash, parst sie, reserviert den RAM, den das Netz während der Inferenz benötigt, und gibt ein Objekt zurück, das alles enthält, was der restliche Teil des Skripts über das geladene Netz wissen muss.

7.4.1. Der Konstruktor

Der Konstruktor nimmt einen Pfad und einen optionalen Post-Prozessor entgegen:

model = ml.Model("/rom/blazeface_front_128.tflite",
                 postprocess=BlazeFace())

Modelle auf /rom/ (dem im Flash residenten Dateisystem) werden an Ort und Stelle gelesen: Die Gewichte des Netzes verbleiben im Flash, und das geladene Modell belegt nur so viel RAM, wie die Tensor-Arena benötigt. Modelle auf /sdcard/ werden beim Laden in den RAM kopiert, sodass die Gesamtkosten der Größe der Modelldatei zuzüglich der Tensor-Arena entsprechen. Beide Pfade funktionieren; der Kompromiss liegt im RAM.

Wenn eine benachbarte .txt-Datei mit demselben Basisnamen existiert, wird ihr Inhalt automatisch in labels geladen. Das Schlüsselwort postprocess= registriert ein aufrufbares Objekt, das predict() nach jeder Inferenz ausführt.

7.4.2. Schreibgeschützte Eigenschaften

Ein geladenes Modell stellt eine kleine Menge schreibgeschützter Eigenschaften bereit, die das Netz beschreiben, ohne dass es jemand ausführt.

Datei und Speicher.

  • len – Größe der Modelldatei auf dem Datenträger, in Bytes.

  • ram – Größe der Tensor-Arena, die das Netz für seine Zwischenaktivierungen während der Inferenz benötigt, in Bytes.

Eingabetensoren.

  • input_shape – eine Liste von Tupeln, eines pro Eingabetensor, die die vom Netz erwartete Form angibt. Vision-Netze haben eine Eingabe mit der Form (1, H, W, C).

  • input_dtype – Liste von Einzelzeichen-dtype-Codes ('b' int8, 'B' uint8, 'h' int16, 'H' uint16, 'f' float32), einer pro Eingabe.

  • input_scale und input_zero_point – die Quantisierungsparameter, die zwischen der reellwertigen Eingabe, mit der das Netz trainiert wurde, und der ganzzahligen Darstellung, gegen die die Kamera arbeitet, umrechnen.

Ausgabetensoren. Spiegelbild der Eingabemenge: output_shape, output_dtype, output_scale, output_zero_point. Erkennungsnetze erzeugen zwei oder drei Ausgabetensoren (Boxen, Konfidenzwerte, manchmal Klassenwahrscheinlichkeiten); Klassifizierungsnetze erzeugen einen.

Extras. labels ist die Klassennamenliste, die aus der benachbarten .txt-Datei geladen wurde, oder None. postprocess ist der registrierte Post-Prozessor, oder None.

7.4.3. BlazeFace untersuchen

Das Laden des mitgelieferten BlazeFace-Modells und das Ausgeben jeder Eigenschaft liefert die tatsächlichen Werte:

import ml
from ml.postprocessing.mediapipe import BlazeFace

model = ml.Model("/rom/blazeface_front_128.tflite",
                 postprocess=BlazeFace())

print("file size:    ", model.len, "bytes")
print("tensor arena: ", model.ram, "bytes")
print("input shape:  ", model.input_shape)
print("input dtype:  ", model.input_dtype)
print("input scale:  ", model.input_scale)
print("input zp:     ", model.input_zero_point)
print("output shape: ", model.output_shape)
print("output dtype: ", model.output_dtype)
print("output scale: ", model.output_scale)
print("output zp:    ", model.output_zero_point)

Die Werte identifizieren die Schnittstelle des Netzes konkret: einen einzelnen (1, 128, 128, 3)-int8-Eingabetensor und zwei int8-Ausgaben – eine für Box-Regressionskoeffizienten, eine für Konfidenzwerte pro Anchor. Die Quantisierungsparameter beschreiben, wie diese int8-Werte auf die reellen Floats abgebildet werden, gegen die das Netz trainiert wurde; der Post-Prozessor verwendet sie, um die Quantisierung rückgängig zu machen, bevor die Boxen dekodiert werden.

Jede Eigenschaft ist die alleinige Quelle der Wahrheit für das, was sie beschreibt. Skripte lesen input_shape, um zu wissen, mit welchen Parametern erfasst werden soll, lesen output_scale und output_zero_point, um Tensoren von Hand zu dekodieren, und lesen labels für menschenlesbare Klassennamen – niemals fest codiert, niemals angenommen.