STM32Cube.AI – walidacja działania modelu

Pakiet STM32Cube.AI w procesie analizy modelu dostosowuje go do możliwości i dostępnych zasobów układów STM32. Generuje tzw. „C model”, który jest następnie wykorzystywany w docelowym projekcie. Czy ta operacja może spowodować, że sieć będzie działała gorzej niż model oryginalny? Możemy to sprawdzić w procesie walidacji.

Czym jest walidacja

Walidacja to mechanizm pozwalający nam porównać dokładność działania sieci w modelu oryginalnym (stworzonym i wyuczonym na komputerze) z modelem zoptymalizowanym przez pakiet X-Cube-AI.

Proces walidacji polega na przeprowadzeniu obliczeń za pomocą obu modeli na tym samym zestawie danych i obliczeniu błędu względnego L2. Dane wejściowe możemy dostarczyć na dwa sposoby:

  • wykorzystując generator liczb losowych (fixed random generator)
  • dostarczając zestaw danych wejściowych i wyjściowych dedykowany dla naszego modelu (custom data-set)

Błąd L2 liczony jest jako różnica wyników pomiędzy dwoma modelami (oryginalnym i zoptymalizowanym) w odniesieniu do modelu zoptymalizowanego wg wzoru:

Mechanizm walidacji dostępny w STM32Cube.AI pozwala nam na przeprowadzenie porównania na dwa sposoby:

  • Na komputerze (Validate on desktop) – walidację możemy wykonać na naszym laptopie/komputerze stacjonarnym bez udziału płytki ewaluacyjnej z mikrokontrolerem
  • Na docelowym urządzeniu (Validate on target) – walidacja jest przeprowadzana przy użyciu docelowego mikrokontrolera, na którym przeprowadzane są obliczenia

Walidacja „on desktop”

Łatwiejszym i szybszym sposobem przeprowadzenia walidacji jest wykorzystanie naszego komputera. Nie musimy podłączać płytki z mikrokontrolerem, programować jej i uruchamiać kodu.

Wszystkie elementy w tym artykule będę wykonywał na modelu wygenerowanym w materiale pt. „Wykrywanie gestów 1D – analogowy czujnik SHARP i STM32Cube.AI„.

Aby uruchomić proces walidacji „on desktop”, musimy stworzyć projekt dla mikrokontrolera. Możemy też wykorzystać dotychczasowy projekt zbudowany pod docelowe zastosowanie sieci, jednak ze względu na drugi rodzaj walidacji („on target”), wygodniej będzie pracować na nowym projekcie.

Tworzymy zatem nowy projekt dla Nucleo-L476RG z domyślną konfiguracją układów peryferyjnych. Następnie dodajemy pakiet X-CUBE-AI poprzez wybór okna „Software Packs -> Select Components” (Alt+O).

W konfiguratorze z listy po lewej stronie wybieramy „Software Packs -> X-CUBE-AI”. Następnie klikamy „Add network”. W oknie dodajemy nazwę (ja zostawiłem domyślną network), typ modelu jako „Keras” i rodzaj jako „Saved model”. Podajemy ścieżkę do zapisanego modelu.

Teraz zajmiemy się dolną częścią okna. Podobnie jak w poprzednim artykule, na początku musimy wygenerować zoptymalizowany model. Wybieramy zatem opcję „Analyze”.

Następnie możemy przejść do procesu walidacji. W wersji z użyciem komputera wystarczy, że klikniemy w przycisk „Validate on desktop”.

Proces walidacji powinien się rozpocząć, a po chwili otrzymamy raport. Znajdziemy w nim informacje o używanym procesorze, budowie sieci i czasie przetwarzania dla każdej warstwy. Jak już wspomniałem, obliczenia są wykonywane na dwóch modelach (oryginalnym i zoptymalizowanym). Najważniejszą informację jest błąd L2 (l2r) widoczny na samym dole raportu.

W naszym przypadku błąd L2 wynosi 0,000000274. Warto podkreślić, że dopuszczalny błąd przyjęty przez oprogramowanie wynosi 0,01, ale nawet jeżeli go przekroczymy, to od nas zależy, czy sieci użyjemy, czy nie (CubeMX nie zablokuje nam takiej możliwości).

W przykładzie zrealizowanym przed chwilą użyliśmy danych generowanych losowo. Aby przeprowadzić walidację przy użyciu naszych danych, musimy przygotować odpowiednie pliki. CubeMX wymaga w tym miejscu danych w formacie „csv”, czyli kolejnych tensorów (tablic) danych umieszczonych w kolejnych liniach. Poszczególne dane w próbce (jednym wierszu) muszą być oddzielony przecinkami. Przykładowy rekord dla danych wejściowych będzie wyglądał jak poniżej.

0.2625,0.275,0.275,0.25,0.4125,0.4875,0.4625,0.525,0.35,0.8375,0.65,0.725,0.5375,0.5,0.5375,0.5375,0.5,0.4875,0.3875,0.375,0.375,0.4,0.3875,0.4125,0.3875,0.4125,0.4375,0.475,0.425,0.3875,0.3875,0.375,0.35,0.5,0.4875,0.4875,0.4,0.45,0.45,0.425,0.4375,0.4125,0.4,0.375,0.325,0.3,0.3375,0.325,0.3375,0.375,0.325,0.3375,0.325,0.325,0.3125,0.3125,0.3,0.3125,0.2875,0.3,0.3375,0.4125,0.375,0.325

Dane wyjściowe przygotowujemy analogicznie, z tym, że w naszym przykładzie z czujnikiem Sharp będziemy mieli tylko jedną liczbę w jednym wierszu.

1.0
1.0
0.0

Dane muszą być znormalizowane zgodnie z tym, jak podawaliśmy je w procesie uczenia. Przykładowe pliki z moim danymi zamieściłem w sekcji „Do pobrania” umieszczonej pod artykułem.

Jeżeli mamy przygotowane pliki, wracamy do CubeMX. Tym razem wybieramy w polach „Validation inputs” oraz „Validation outputs” ścieżki do plików z danymi. Następnie powtarzamy proces walidacji, klikając „Validate on desktop”.

Ponownie otrzymujemy raport z obliczonym błędem L2. Tym razem wyniósł on 0,000000202. W celu porównania przeprowadziłem walidację dla różnych metod kompresji (None, 4 oraz 8). Wyniki zamieściłem w tabeli poniżej.

Typ kompresjiUzyskany stopień kompresjiWykorzystana pamięć FlashWykorzystana pamięć RAMBłąd L2 dla random numbersBłąd L2 dla custom data
None05,19 kB388 B0,0000002740,000000202
42,373,19 kB388 B0,0051940910,003035593
86,36964 B388 B0,0542497040,036548771

Jak można zauważyć, wykonanie walidacji za pomocą liczb losowych jako wejścia oraz pliku z danymi są porównywalne (czego można się było spodziewać). Z tabeli możemy też wynieść inny, nawet ważniejszy wniosek – szczególnie w przypadku użycia kompresji warto wykonać proces walidacji i sprawdzić, jak duży błąd L2 powstaje. Do niektórych zastosowań błąd na poziomie ok. 0,054 może być już zbyt duży. Dlatego w przypadku kompresji musimy znaleźć kompromis pomiędzy zużyciem pamięci, a dokładnością działania sieci.

Walidacja „on target”

Drugim sposobem na wykonanie walidacji jest sprawdzenie modelu na docelowym mikrokontrolerze. W tym celu musimy zaprogramować układ za pomocą dedykowanej aplikacji. Aby ją przygotować, przechodzimy ponownie do widoku okna „Software Packs -> Select Components” (Alt+O). Tym razem poza X-CUBE-AI, wybieramy jeszcze aplikację „Validation”.

W konfiguratorze z listy po lewej stronie wybieramy „Software Packs -> X-CUBE-AI” i zaznaczamy w oknie „Mode” pole „Device Application”.

Następnie przechodzimy do zakładki „Platform settings” i ustawiamy port, jakiego będziemy używali do komunikacji z płytką w trakcie procesu walidacji.

Jeżeli wcześniej tego nie zrobiliśmy, musimy jeszcze w zakładce „Project Manager->Code Generator” zaznaczyć opcję „Generate peripheral initialization as a pair of „.c/.h” files per peripheral”.

Ja generalnie zaznaczam tę opcję w każdym projekcie, ponieważ pozwala ona zachować porządek w kodzie (mamy oddzielne pliki dla każdego układu peryferyjnego, a nie wszystko w pliku main.c). W przypadku aplikacji walidacyjnej, brak zaznaczenia tego pola spowoduje, że będziemy mieli problemy z kompilacją projektu, ponieważ jedna z funkcji aplikacji wywołuje inicjalizację portu UART, którego używamy do komunikacji. Bez zaznaczenia pola „Generate peripheral initialization…” funkcja ta nie będzie widoczna poza plikiem main i kompilator wyrzuci nam błąd.

Teraz możemy wygenerować projekt, skompilować go i wgrać program na płytkę. Dzisiaj nie będziemy zajmować się tym, jak aplikacja do walidacji jest zbudowana. Po prostu ma działać 🙂

Jeżeli mamy już program na płytce, wracamy do konfiguratora CubeMX i przechodzimy do zakładki z naszą siecią. W zasadzie proces walidacji jest bardzo podobny do trybu „on desktop”. Wybieramy rodzaj wejść jako „Random numbers” lub podajemy ścieżki do plików z naszymi wejściami i wyjściami. Następnie klikamy „Validate on target”.

Pojawi nam się okno z konfiguracją używanego portu i prędkości transmisji. Jeżeli automatycznie wybrało nam zły port COM, możemy przełączyć tryb na „Manual” i zmienić go ręcznie. Istnieje też opcja automatycznej kompilacji i wgrania programu za pomocą tego okna, choć nie zawsze to działa poprawnie (może robię coś po prostu źle).

Klikamy OK. proces walidacji powinien się rozpocząć. Podobnie jak w przypadku walidacji „on desktop”, po chwili otrzymujemy raport.

W naszym przypadku błąd L2 wynosi 0,000000446. Jest więc ok. 2 razy większy niż w przypadku walidacji na komputerze, ale nadal bardzo mały.

Analogicznie jak w przypadku pierwszego trybu walidacji, w celu porównania przeprowadziłem walidację dla różnych metod kompresji (None, 4 oraz 8) i typu danych wejściowym. Wyniki zamieściłem w tabeli poniżej.

Typ kompresjiUzyskany stopień kompresjiWykorzystana pamięć FlashWykorzystana pamięć RAMBłąd L2 dla random numbersBłąd L2 dla custom data
None05,19 kB388 B0,0000004460,000000251
42,373,19 kB388 B0,0051941710,003035516
86,36964 B388 B0,0542498830,036548771

Wnioski są w zasadzie podobne jak w przypadku walidacji „on desktop”. Wykonanie walidacji za pomocą liczb losowych jako wejścia oraz pliku z danymi są porównywalne. Dodatkowo, porównując wyniki otrzymane dla obu typów walidacji, możemy zauważyć, że błędy są bardzo podobne. Można więc uznać, że w przypadku tego projektu wystarczy walidacja wykonana na komputerze, aby sprawdzić dokładność działania sieci.

Podsumowanie

Pakiet X-Cube-AI udostępnia ciekawe narzędzie do wykonaniu procesu walidacji. Pozwala nam porównać dokładność działania sieci w modelu oryginalnym (stworzonym i wyuczonym na komputerze) z modelem zoptymalizowany. Dostępne są różne warianty – możemy sprawdzić sieć na komputerze lub wykonać walidację na docelowym mikrokontrolerze. Do sprawdzenia dokładności działania sieci możemy użyć zarówno danych losowych, jak i przygotowanych przez nas dedykowanych danych do używanego modelu. Na koniec warto jeszcze raz podkreślić – szczególnie w przypadku użycia kompresji warto wykonać proces walidacji i sprawdzić, jak duży błąd powstaje.

Do pobrania

Dodaj komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *