7.6. Anatomia predict

Model.predict(inputs, *, callback=None) to miejsce, w którym wczytany obiekt modelu faktycznie wykonuje pracę. Pomiędzy wejściem danych a wyjściem wyniku wykonują się po kolei trzy etapy: pre-przetwarzanie, dyspozycja silnika, post-przetwarzanie. Dwa z trzech przyjmują parametry kontrolowane bezpośrednio przez skrypt; o silniku w środku decyduje kamera.

Poziomy przepływ pięciu połączonych prostokątów od lewej do prawej. Skrajnie lewy to "Wejście obrazu"; strzałka prowadzi do "Pre-przetwarzanie" z podpisem "Normalizacja"; strzałka prowadzi do "Silnik" z podpisem "TFLM / STAI"; strzałka prowadzi do "Post-przetwarzanie" z podpisem "postprocess="; a ostatnia strzałka prowadzi do "Wynik". Trzy środkowe etapy mają pod sobą znacznik -- "kontrolowane przez użytkownika" pod Pre-przetwarzaniem, "automatyczne" pod Silnikiem oraz "kontrolowane przez użytkownika" pod Post-przetwarzaniem.

Trzy etapy predict(). Pre-przetwarzanie i post-przetwarzanie przyjmują parametry kontrolowane przez skrypt; o silniku w środku decyduje kamera.

7.6.1. Pre-przetwarzanie

Etap pre-przetwarzania zamienia każde wejście w gęsty tensor, którego oczekuje sieć. Najczęstszym wejściem jest image.Image, przechwycony w RGB565. Etap kadruje go i skaluje do input_shape sieci, konwertuje z RGB565 do formatu kanałów, na którym trenowano sieć (RGB888 dla większości sieci wizyjnych), stosuje skalę i przesunięcie na każdy kanał oraz – gdy sieć oczekuje wejścia całkowitoliczbowego – kwantyzuje do input_dtype modelu w tym samym przebiegu. Sieci trenowane dla wejścia zmiennoprzecinkowego pomijają krok kwantyzacji i otrzymują bezpośrednio wynik skalowania i przesunięcia.

Domyślny ml.preprocessing.Normalization odczytuje dtype wejścia modelu i automatycznie uruchamia właściwą transformację. Ręcznie dostrojona Normalization nadpisuje wartości skali, średniej i odchylenia standardowego dla modeli trenowanych na własnych statystykach kanałów (powszechnym przypadkiem są średnie i odchylenia standardowe wywiedzione z ImageNet). Zwykły obiekt wywoływalny nadpisuje cały etap – przydatne, gdy wejście w ogóle nie jest obrazem lub gdy aplikacja sama wytworzyła już gęsty tensor.

7.6.2. Dyspozycja silnika

Etap silnika uruchamia sieć. To, do którego silnika kieruje, jest ustalone przez kamerę: H7 i RT1062 uruchamiają TFLM (interpreter TensorFlow Lite for Microcontrollers, kierujący do zoptymalizowanych pod ARM jąder CMSIS-NN tam, gdzie istnieją); AE3 uruchamia ten sam interpreter TFLM z awaryjnym Cortex-M55 oraz NPU Ethos-U obsługującym każdy operator, który offline’owy kompilator Vela oznaczył dla akceleratora; N6 uruchamia STAI, środowisko uruchomieniowe ST dla dedykowanego NPU układu N6.

Skrypt nie wybiera silnika. Silnik dostarczany z kamerą uruchamia każdy model, który kamera wczytuje.

7.6.3. Post-przetwarzanie

Etap post-przetwarzania zamienia surowe tensory wyjściowe sieci z powrotem w użyteczny wynik. Domyślnym zachowaniem jest dekwantyzacja każdego tensora wyjściowego do liczby zmiennoprzecinkowej (lub przepuszczenie go bez zmian dla sieci z wyjściami zmiennoprzecinkowymi) i zwrócenie ich jako listy obiektów ndarray. Większość aplikacji rejestruje post-procesor – obiekt wywoływalny znający układ wyjść sieci – aby zdekodować tensory do postaci wyniku, na której aplikacja działa: listy ramek ograniczających, listy punktów kluczowych, listy klas.

Skrypt kontroluje ten etap na dwa sposoby. Słowo kluczowe postprocess= w konstruktorze rejestruje post-procesor uruchamiany przy każdym wywołaniu. Słowo kluczowe callback= w predict() nadpisuje zarejestrowany post-procesor tylko dla jednego wywołania – przydatne do przełączania się między kilkoma dekoderami bez ponownego wczytywania modelu. Każda z form otrzymuje (model, inputs, outputs) i zwraca to, czego oczekuje aplikacja.

7.6.4. Co kontroluje skrypt

Pre-przetwarzanie i post-przetwarzanie to dwa uchwyty skryptu. Domyślny pre-procesor obsługuje większość modeli wizyjnych; właściwy post-procesor dla danej rodziny sieci wybiera się z katalogu pod ml.postprocessing. O silniku w środku decyduje proces budowania i działa on tak samo, niezależnie od tego, o co prosi skrypt.