Capitolo 1. Introduzione
Questo articolo fornisce istruzioni dettagliate su come iniziare a sviluppare le proprie applicazioni di Machine Learning (ML) utilizzando System on Modules di Variscite. Mostra come creare un’immagine utilizzando il BSP Yocto Linux con una raccolta di strumenti di sviluppo, utilità e librerie per la creazione di applicazioni ML dall’ambiente di sviluppo software NXP eIQ™ ML, come eseguire gli esempi predefiniti creati con l’immagine e, infine, come scrivere un semplice esempio di ML da zero.
1.1. Panoramica dell’ambiente di sviluppo del software di machine learning eIQ™
eIQ™ consente agli utenti di sviluppare facilmente un’applicazione completa a livello di sistema per risolvere i problemi di ML relativi a visione, audio, dati di serie temporali e così via. Esempi comuni sono il riconoscimento facciale, la stima della posa, il riconoscimento dei gesti, l’interpretazione degli accenti vocali, ecc.
Lo stack software più recente di eIQ™ include uno strumento di flusso di lavoro ML chiamato eIQ™ Toolkit , che può essere utilizzato per saperne di più sul ML e per addestrare il proprio modello ML attraverso il eIQ Portal ; include anche eIQ™ Inference che abilita il supporto per motori di inferenza, neurali compilatori di rete e librerie ottimizzate come TensorFlow Lite, Arm NN, ONNX Runtime, PyTorch, OpenCV e DeepViewRT.
Per maggiori informazioni su eIQ™, visita:
1.2. Prerequisiti
1.2.1 SoM Variscite supportato
Le DART-MX8M-PLUS e VAR-SOM-MX8M-PLUS sono basate sul processore NXP i.MX 8M Plus, che include un’unità di elaborazione neurale (NPU); un acceleratore AI/ML dedicato. La NPU aiuta a raggiungere prestazioni elevate durante il processo di inferenza nelle applicazioni ML.
Sebbene questo articolo si concentri sui moduli basati sul processore i.MX 8M Plus, altri moduli basati sulle famiglie NXP i.MX 8 e i.MX 8M possono essere utilizzati anche per applicazioni ML. In questi casi, la GPU o la CPU viene utilizzata per il processo di inferenza invece della NPU.
1.2.2. Yocto Linux BSP con abilitazione eIQ™
Per creare un’immagine con i motori e le librerie di inferenza eIQ™:
1. Segui le sezioni 1 e 3 nella guida appropriata «Build Yocto from source code» in variwiki.com per configurare il tuo host di build e recuperare i sorgenti Yocto per la versione SOM e Yocto che desideri utilizzare.
Ad esempio:
https://variwiki.com/index.php?title=Yocto_Build_Release&release=RELEASE_HARDKNOTT_V1.0_DART-MX8M-PLUS
…
$ repo init -u https://github.com/varigit/variscite-bsp-platform.git -b <tag_name> -m <manifest_name> ①
$ repo sync -j$(nproc) ②
❶E.g., replace <tag_name> with fsl-hardknott; <manifest_name> with imx-5.10.35-2.0.0-var01.xml
❷ La fase di sincronizzazione dei repo potrebbe richiedere un po’ di tempo per completare ☕
2. Prepara l’ambiente per creare l’immagine per il modulo scelto:
$ MACHINE=<module_name> DISTRO=fsl-imx-xwayland . var-setup-release.sh -b build_xwayland ①
❶ E.g., replace <module_name> with imx8mp-var-dart
3. Usa l’immagine imx-image-full per creare i pacchetti eIQ™ ML:
$ bitbake imx-image-full ①
❶ Il completamento di questo passaggio potrebbe richiedere diverse ore a seconda delle specifiche del computer ☕
4. Esegui il flashing dell’immagine completa sulla scheda SD:
- L’immagine creata si trova nella seguente cartella:
🗀 ${BUILD}/tmp/deploy/images/<module_name>
$ zcat imx-image-full-<module_name>.wic.gz | sudo dd of=/dev/sd<x> bs=1M status=progress conv=fsync ①
❶E.g., replace <module_name> with imx8mp-var-dart; <x> with b
⚠️ ATTENZIONE.Utilizza i comandi dmesg o lsblk per controllare il nome corretto del dispositivo della scheda SD.
Capitolo 2. Applicazioni predefinite di eIQ™ Machine Learning
A causa di un gran numero di sottocategorie ML, questo articolo descrive solo un esempio della sottocategoria di apprendimento supervisionato, che è il problema di classificazione delle immagini. Per sapere come funziona il problema di classificazione, eseguiremo un esempio da eIQ™ che utilizza un modello di avviamento addestrato fornito da TensorFlow e il motore di inferenza di TensorFlow Lite costruito insieme al BSP Yocto Linux.
2.1. TensorFlow Lite
Il motore di inferenza e la libreria di eIQ™ più popolari e ben supportati è TensorFlow Lite sviluppato da Google. Mentre TensorFlow è una popolare piattaforma open source per Machine Learning che può essere utilizzata sia per la formazione di rete che per l’inferenza, TensorFlow Lite è un insieme di strumenti specificamente progettati per convertire ed eseguire inferenze da modelli TensorFlow su dispositivi embedded con latenza inferiore e dimensioni binarie più piccole.
2.1.1 Panoramica sulla classificazione delle immagini
La classificazione delle immagini è un problema di classificazione della sottocategoria di apprendimento supervisionato, che può essere utilizzata per identificare ciò che un’immagine rappresenta senza fare affidamento su regole hardcoded. Per farlo funzionare, dobbiamo addestrare un modello di classificazione delle immagini per riconoscere varie classi di immagini. Ad esempio, possiamo addestrare un modello a riconoscere molti oggetti, come veicoli, persone, semafori, tipi di frutta o animali e così via.
Per addestrare un modello di classificazione delle immagini, la formazione deve essere alimentata con immagini e le relative etichette. Richiede centinaia o migliaia di immagini per etichetta in modo che il modello possa imparare in modo efficiente a prevedere se le nuove immagini appartengono a una delle classi su cui è stato addestrato. Il processo con cui il modello fa una previsione su una nuova immagine di input è chiamato inferenza.
Il processo di addestramento di un nuovo modello richiede molto tempo, a seconda di diversi aspetti come il modo in cui viene definita la rete neurale e la quantità di dati utilizzati per addestrare il modello.
Il modello utilizzato in questo articolo è stato precedentemente addestrato e testato da TensorFlow. Come accennato nel primo capitolo di questo articolo, è anche possibile creare, ottimizzare, eseguire il debug, convertire ed esportare il proprio modello ML utilizzando il portale eIQ™ di NXP.
Quando forniamo una nuova immagine come input di dati al modello, emetterà la probabilità che l’immagine rappresenti ciascuno degli oggetti su cui è stata addestrata. Un esempio di output può essere quello riportato nella Tabella 1 qui sotto:
Tabella 1. Esempio di risultati di probabilità
Nome oggetto (Label) | Probabilità |
Dog | 0.91 |
Cat | 0.07 |
Rabbit | 0.02 |
Il modello di classificazione delle immagini viene fornito con il file delle etichette corrispondente, che contiene l’elenco degli oggetti su cui è stato addestrato il modello (ad esempio, vedere tensorflow/lite/java/ovic/src/testdata/labels.txt nel seguente esempio codice sorgente), e ogni numero nell’output corrisponde a un’etichetta in il file delle etichette. Nell’esempio precedente, associando l’output alle tre etichette su cui è stato addestrato il modello, mostra un’alta probabilità che l’immagine in questo caso rappresenti un cane.
2.1.2. Esempio di classificazione delle immagini
L’immagine completa creata con i pacchetti eIQ™ fornisce un esempio di classificazione delle immagini scritto in C++ e uno simile scritto in Python. L’API C ++ di TensorFlow fornisce un’opzione per scegliere l’unità di calcolo per eseguire l’inferenza, mentre i collegamenti Python non forniscono questa opzione, quindi gli esempi scritti in Python eseguono solo l’inferenza sulla NPU.
Questa sezione spiega come eseguire l’esempio predefinito scritto in C++. La prossima sezione spiega come eseguire l’esempio predefinito scritto in Phyton, dove imparerai come scrivere un esempio da zero usando i collegamenti Python di TensorFlow Lite.
L’esempio C ++ viene fornito con un modello iniziale addestrato, un file di etichette e un esempio di immagine da utilizzare come input per il processo di inferenza – vedere la tabella 2 di seguito:
Tabella 2. Dettagli esempio di classificazione delle immagini
Nome di esempio | Lingua | Modello predefinito | Etichette predefinite | Input predefinito |
label_image | C++/Python | mobilenet_v1_1.0_224 _quant.tflite |
labels.txt | grace_hopper.bmp |
• Avvia la scheda e vai alla seguente cartella in cui si trova l’esempio di classificazione delle immagini:
$ cd /usr/bin/tensorflow-lite-<version>/examples ①
❶ E.g., replace <version> with 2.4.1
• Usa i seguenti argomenti per utilizzare diversi file di dati di input di modelli / etichette / immagini:
$ ./label_image -m <model_file_name.tflite> -l <labels_file_name.txt> -i <image_file_name.extension>
Se non viene specificato alcun argomento, l’esempio utilizza gli argomenti predefiniti nella Tabella 2.
Esempio in C++ (CPU)
1. Eseguire l’esempio dell’immagine dell’etichetta usando l’argomento «-a» con un valore «0″ per eseguire l’inferenza sulla CPU:
$ ./label_image -a 0
- L’output di una classificazione di successo dovrebbe essere simile al seguente:
Figura 1. Esecuzione di un esempio di classificazione delle immagini TensorFlow Lite (inferenza CPU)
🕒 Tempo di inferenza sulla CPU: 40,496 millisecondi.
Esempio in C++ (NPU)
1. Eseguire l’esempio dell’immagine dell’etichetta usando l’argomento «-a» con un valore «1″ per eseguire l’inferenza sulla NPU:
$ ./label_image -a 1
- L’output di una classificazione di successo dovrebbe essere simile al seguente:
Figura 2. Esecuzione di un esempio di classificazione delle immagini TensorFlow Lite (inferenza NPU)
🕒 Tempo di inferenza su NPU: 2.812 millisecondi.
Questo messaggio indica che l’inferenza è in esecuzione su NPU:
“INFO: Applied NNAPI delegate.”
Il codice sorgente per l’esempio label_image è disponibile nel repository tensorflow-imx:
Capitolo 3. Sviluppo di applicazioni eIQ™ ML
Questa sezione è una guida passo passo per lo sviluppo di un semplice esempio di classificazione delle immagini utilizzando un modello iniziale, un file di etichette e un’immagine come input di dati. Questo esempio è scritto in Python utilizzando l’API Python TensorFlow Lite.
I passaggi seguenti mostrano come aprire e ridimensionare l’immagine in base alla dimensione di input del modello, come caricare l’immagine come dati di input attraverso il processo di inferenza sulla NPU e infine come analizzare l’output per ottenere i risultati di probabilità.
Il codice sorgente per questo esempio di classificazione delle immagini è disponibile all’indirizzo:
Nel repository di cui sopra, puoi trovare altri esempi, come:
Classificazione di file immagine, file video e streaming video in tempo reale.
Rilevamento di file immagine, file video e flusso video in tempo reale (che restituisce l’etichetta di classificazione insieme alla posizione dell’oggetto nell’immagine e disegna un rettangolo attorno ad esso).
Applicazione dell’interfaccia utente, ecc.
3.1. Classificazione delle immagini da zero
3.1.1. Iniziare
1. Crea una directory e recupera il modello iniziale di classificazione delle immagini e un’immagine gratuita da utilizzare come input di dati:
$ mkdir ~/example && cd ~/example
$ wget https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v1_1.0_224_quant_and_labels.zip
$ wget https://raw.githubusercontent.com/varigit/var-demos/master/machine-learning-demos/tflite/classification/media/image.jpg
Questa immagine è solo un esempio, sentiti libero di usare qualsiasi altra immagine.
a. Estrai il modello nella directory:
$ unzip mobilenet_v1_1.0_224_quant_and_labels.zip
-
- Rimuovi i file ridondanti:
$ rm -rf __MACOSX/ mobilenet_v1_1.0_224_quant_and_labels.zip
2. Crea il file .py per iniziare a scrivere il codice sorgente:
$ touch ~/example/image_classification.py
3. La struttura delle cartelle dovrebbe essere simile alla seguente:
.
├── image_classification.py
├── image.jpg
├── labels_mobilenet_quant_v1_224.txt
└── mobilenet_v1_1.0_224_quant.tflite
0 directories, 4 files
3.1.2. Modifica image_classification.py e scrivi il codice sorgente
1. Innanzitutto, importa le librerie Time, NumPy, Pillow e TensorFlow Lite:
1 from time import time
2
3 import numpy as np
4 from PIL import Image
5 from tflite_runtime.interpreter import Interpreter
2. Apri e leggi le righe dal file delle etichette del modello di classificazione:
6 with open('labels_mobilenet_quant_v1_224.txt') as f:
7 labels = f.read().splitlines()
3. Utilizza il modulo Interpreter per caricare il modello di classificazione delle immagini e allocarne i tensori:
8 interpreter = tf.Interpreter(model_path="mobilenet_v1_1.0_224_quant.tflite")
9 interpreter.allocate_tensors()
4. Ottieni i dettagli dai tensori di input e output del modello di classificazione delle immagini:
10 input_details = interpreter.get_input_details()
11 output_details = interpreter.get_output_details()
5. Apri l’immagine e ridimensionala in base alle dimensioni di input del modello:
12 with Image.open("image.jpg") as im:
13 _, height, width, _ = input_details[0]['shape']
14 image = im.resize((width, height))
15 image = np.expand_dims(image, axis=0)
6. Per caricare l’immagine ridimensionata come input di dati nella NPU, impostare il tensore di input:
16 interpreter.set_tensor(input_details[0]['index'], image)
7. Chiama il metodo invoke per avviare l’inferenza sulla NPU:
17 interpreter.invoke() ①
18
19 start = time()
20 interpreter.invoke() ②
21 final = time()
❶ La prima chiamata del metodo invoke richiede più tempo del solito a causa dei passaggi di inizializzazione;
❷ Per ottenere il tempo effettivo impiegato dalla NPU per eseguire l’inferenza, chiamare nuovamente il metodo invoke.
Le fasi di inizializzazione sono anche chiamate fase di riscaldamento. Sono necessari solo una volta, all’inizio dell’applicazione.
8. Ottieni i dettagli di output dopo aver eseguito l’inferenza sulla NPU:
22 output_details = interpreter.get_output_details()[0]
9. Ottieni le tre probabilità più rilevanti come spiegato nella sezione 2.1.1 Panoramica sulla classificazione delle immagini :
23 output = np.squeeze(interpreter.get_tensor(output_details['index']))
25 results = output.argsort()[-3:][::-1]
10. Stampa le etichette e le relative probabilità:
26 for i in results:
27 score = float(output[i] / 255.0)
28 print("[{:.2%}]: {}".format(score, labels[i]))
29
11. Infine, stampa il tempo di inferenza:
30 print("INFERENCE TIME: {:.6f} seconds".format(final-start))
3.1.3 Prova l’esempio sul modulo scelto
1. Copia la cartella esempio nella scheda di destinazione:
$ scp -r ~/example root@<target-ip>:/home/root
- Sulla lavagna, esegui i seguenti comandi:
# cd /home/root/example
# python3 image_classification.py
-
-
- L’output di una classificazione di successo dovrebbe essere simile al seguente:
-
Figura 3. Input di esempio di classificazione delle immagini TensorFlow Lite (inferenza NPU)
🕒 Tempo di inferenza su NPU: 2,9 millisecondi.
Come si può vedere, il modello ha previsto un’alta probabilità (91,37%) che l’immagine rappresenti un’auto sportiva.
Questo esempio può essere ulteriormente utilizzato come base per qualsiasi applicazione relativa a problemi di classificazione delle immagini. Ad esempio, puoi modificare il codice sorgente per usare un file video o un flusso video live da una telecamera, invece di un input di file immagine, usando OpenCV e GStreamer, come fatto nel repository var- demos menzionato sopra.