Comment classifier des images sur une Raspberry pi 3? TensorFlow Lite

Bonjour à tous,

Dans mon précédent post, j’explique comment installer TensorFlow 2 sur Raspberry Pi (RPI).

Je me suis rendu compte qu’en fait, il suffit d’installer TensoFlow Lite pour faire de la classification d’image à partir de réseaux de neurones pré-entraînés.

L’avantage, c’est que l’installation est beaucoup plus « lite » et que c’est très simple.

Tout est expliqué (en Anglais), là : TensorFlow Lite Python classification example with Pi Camera .

Et l’installation de TensorFlow Lite est expliquée ici : Python quickstart .

Le seul « trick » que je pourrais ajouter, c’est que perso, ce coup là j’ai utilisé Miniconda pour me créer un environnement virtuel avec Python 3.6 . J’en parle un peu dans mon précédent post. Dans ce cas, « pip install numpy » (dans les requirements.txt) ne marche pas, alors que « conda install numpy » fonctionne.

On peut lancer le code pour la classification automatique d’image :

python3 classify_picamera.py --model /tmp/mobilenet_v1_1.0_224_quant.tflite --labels /tmp/labels_mobilenet_quant_v1_224.txt

C’est vraiment super !!!

Pour comprendre, TensorFlow Lite prend quelques centaines de millisecondes pour classifier une image provenant du flux vidéo, tandis que TensorFlow mettra plusieurs secondes. Cela est dû en partie au fait que le modèle Lite est quantifié sur 8 bits (sauf erreur de ma part). Au lieu de nombres à virgule flottante (float) codés sur 32 bits, on utilise des entiers sur 8 bits, ce qui réduit la taille (en octets) du modèle et surtout accélère considérablement le temps de calcul. Les résultats sont un peu moins précis en principe.

Voici une version un peu modifiée de la démo classify_image.py qui permet de classifier une seule image :

curl -O https://storage.googleapis.com/download.tensorflow.org/models/tflite/mobilenet_v1_1.0_224_quant_and_labels.zip
unzip mobilenet_v1_1.0_224_quant_and_labels.zip
python classify_image.py --model mobilenet_v1_1.0_224_quant.tflite --labels labels_mobilenet_quant_v1_224.txt --image monimage.jpg

Les deux premières lignes téléchargent et dé-zippent le modèle. « classify_picamera.py » est remplacé par « classify_image.py ». Notez l’option supplémentaire –image qui permet de fournir un fichier image au lieu d’utiliser la camera du RPI.

Et voilà!!!

Comment installer TensorFlow version 2 sur Raspberry Pi : la compilation croisée ?

classifier des images Sur ma Raspberry pi 3 avec un réseau de neurones profond sous Python 3

L’objectif est de classer des images depuis une Raspberry 3, en utilisant la camera « rapstill » dédiée. Une application potentielle est la prise de photos, en envoyant à un serveur distant uniquement les images d’animaux (par exemple). Nous souhaitons, pour cela, utiliser des outils du « Deep Learning », avec des réseaux de neurones profonds pour la classification des images.

A noter que la Raspberry 3 B+ a des ressources limitées en terme de mémoire vive [1 Go de RAM]. De plus, son processeur de type ARM est différent de celui sur un PC (x86).

premier essai d’installation de tensorflow et de keras

On travaille sous python 3.x sur une Raspberry Pi 3 B+.

Keras est un paquet Python qui permet de créer, d’entraîner et de tester des réseaux de neurones profonds (DNN = Deep Neural Network). Keras est intéressant car il y est facile et rapide de mettre en œuvre des DNNs par rapport aux alternatives. A la base, Keras est une couche haut niveau qui utilise des logiciels d’optimisation comme TensorFlow ou Theano. Dans cet article, on se concentre sur TensorFlow avec la « sur-couche » Keras « au-dessus ».

L’installation de TensorFlow version 1, sur la Raspberry, se fait avec l’outil « pip ». Malheureusement, ça bloque côté Keras et en particulier sur la compilation du paquet « scipy » version 1.4.1 (scientific python).
Pour compiler scipy depuis les sources, sur la Raspberry, il est conseillé d’augmenter la taille du swap (définition du swap, comment augmenter sa taille), mais les 1Go de RAM ne suffisent pas.

Le paquet compile pendant une heure et demi, puis plus rien : pas de message d’erreur, mais il ne se passe plus rien. En googlant un peu, je me rends compte que je ne suis pas le seul à galérer sur le problème.

J’abandonne momentanément mon objectif.

TensorFlow 2

A travers d’autres projets, je commence à utiliser TensorFlow dans sa version 2. Je code par exemple une factorization en matrices non négatives (NMF) en utilisant TensorFow (TF) comme un outil d’optimisation performant. Génial.
Le truc vraiment génial, c’est que TensorFlow 2 intègre entièrement Keras.

Je comprends que si j’arrive à installer TensorFlow 2 sur la Raspberry Pi (RPI), j’ai gagné la partie, ou du moins je marque un bon point.

classification d’images de la base imagenet

Parallèlement, sur mon PC de bureau, je m’intéresse à la classification d’images avec TF 2/ Keras. Mieux vaut tard que jamais! J’utilise la base d’images ImageNet, qui est géniale car elle contient 1000 classes d’objets visuels. Pour la classification, j’utilise Inception v3, qui est intégré à TF 2 (tf.keras.applications.InceptionV3). C’est un gros réseau de neurones profond.
Les résultats sont bluffants.
En passant, je remarque qu’il existe une version light du modèle Inception v3 (entre autres!) avec TF Lite, ou du moins la possibilité d’en créer.
Je range ça quelque part dans ma mémoire.

Pour la petite histoire, J’ai montré les performances de classification avec la base ImageNet et Inception, à ma compagne le soir même. Pas vraiment enthousiaste. Moi je trouve ça génial. Je sais que c’est un des premiers gros succès du Deep Learning (apprentissage profond).
Pour se faire une idée, lorsque je joue à pile ou face, j’ai deux cas. Le hasard me donne une probabilité de 1/2 = 50% par face.
Donc si je suis capable de prédire un peu mieux le résultat (par exemple si la pièce est bizarrement faite et que le jeu est pipé, c’est un peu tordu mais bref), prédire ne serait-ce qu’à 51% d’accuracy, je fait mieux que le hasard et ça déjà c’est très fort. ça ne paraît pas comme ça, mais ça fait une vraie différence. Au passage, l’accuracy est un terme anglais qui désigne le pourcentage d’items correctement classés.

Dans la base de données ImageNet,  il y a 1000 classes (explore), regroupées de manière hiérarchique dans les macro-classes suivantes :

  • Plant, flora, plant life,
  • Geological formation, formation,
  • Natural object,
  • Sport, athletics,
  • Artifact, artefact,
  • Fungus,
  • Person, individual, someone, somebody, mortal, soul,
  • Animal, animate being, beast, brute, creature, fauna,
  • Misc.

Pour 1000 classes, le hasard c’est 1/1000, soit 0.1 %. Avec le Deep Learning, on atteint des résultats de l’ordre de 70 à 80% d’accuracy, sur un ensemble de TEST (c-a-d différent de l’ensemble d’apprentissage). Passer de 0.1% à 70%, c’est hallucinant!

Exemple artichaut ! (image trouvée sur le net)

Résultat avec Inception v3

artichoke,		probability = 92.3%
cardoon,		probability = 0.4%
jack-o'-lantern,	probability = 0.1%
grocery_store,		probability = 0.1%
Dutch_oven,		probability = 0.0%
retour au Raspberry
les versions de Python

Il est possible d’installer Miniconda sur la RPI, à la main. C’est une version light d’Anaconda et qui permet de créer des environnements virtuels pour python de manière simple. Avec un environnement virtuel, on peut installer python et pleins de paquets/modules, modifier des bouts de code, faire port-nawak. ça n’est pas grave. Il suffit d’effacer l’environnement et le système est indemne. C’est le principe de la virtualisation.
Avec Miniconda pour la RPI, la version de Python est 3.4. Or TF 2 nécessite une version de Python supérieure ou égale à 3.5.
Il est possible d’installer Python 3.6 avec Berryconda.
Pour cela, taper dans un terminal de votre Raspberry:
conda config --add channels rpi
puis pour créer l’environnement avec Python 3.6
conda create -n py36 python=3.6
Pour activer environnement virtuel avec python 3.6
conda activate py36
pour en sortir
conda deactivate [et pas deSactivate]

J’ai fait le choix d’installer localement Python 3.7, non disponible avec Miniconda.
Pour cela, j’ai compilé les sources sur la RPI. On va suivre l’article Installing Python 3.7.2 on Raspbian :
Dans un terminal, installer les paquets nécessaire à la compilation
sudo apt-get update -y
sudo apt-get install build-essential tk-dev libncurses5-dev libncursesw5-dev libreadline6-dev libdb5.3-dev libgdbm-dev libsqlite3-dev libssl-dev libbz2-dev libexpat1-dev liblzma-dev zlib1g-dev libffi-dev -y

Télécharger les sources [note: la marche à suivre est la même pour une autre version de Python, en fournissant l’url adéquate pour wget]
wget https://www.python.org/ftp/python/3.7.2/Python-3.7.2.tar.xz
tar xf Python-3.7.2.tar.xz
cd Python-3.7.2

Les compiler : 1ère option, globale
./configure
make
make install
2ème option, locale.
créer un répertoire  « py37 » dans « /home/pi » puis
./configure --prefix=/home/pi/py37
make
make install

Dans le second cas, pour utiliser python3 et pip3, c-a-d pour activer python 3.7, il faudra taper dans la console:
export PATH=/home/pi/py37/bin:$PATH
et utiliser pip3 et python3
Note: on pourrait placer une fois pour toute la ligne "export ..." à la fin du fichier "/home/pi/.bashrc"
Si cela vous paraît obscure, utilisez la première solution (globale).

Le coup de bol

En cherchant à installer TF 2 sur Raspberry 3, je suis tombé, avec un peu de chance, car il est tard, sur le repo github de Leonardo Lontra alias lhelontra. [github est un dépot de programmes/codes sources, énorme et très très utilisé.]

Le code source « https://github.com/lhelontra/tensorflow-on-arm » permet de faire la compilation croisée.
Cela signifie qu’on va pouvoir compiler TF sur une machine puissante, comme mon PC de bureau et le résulat sera utilisable sur la RPI et non sur mon PC. On parle de cross-compilation ou compilation croisée. Contrairement au Rapsberry, mon PC a 8 Go de mémoire et un processeur i5 avec 4 coeurs (c’est un PC, sous linux, datant de 2016).

Bon je spoile : la compilation croisée a duré 7 heures et ça a marché!!! Je viendrais tout de suite à la marche à suivre.

Mais en écrivant ces lignes, je m’APRECOIS qu’il y a des versions cross-compilées déjà disponibles dans le repo github.
Quel imbécile je fais!

Alors ce qu’on peut faire, c’est allumer son RPI et lancer un navigateur web et un terminal.
Dans le repo (https://github.com/lhelontra/tensorflow-on-arm), il suffit de cliquer sur l’onglet « releases » (voir image ci-dessous) ou bien taper dans la barre de navigation https://github.com/lhelontra/tensorflow-on-arm/releases .


Ensuite, en dessous de TENSORFLOW 2.0, on clique sur « tensorflow-2.0.0-cp37-none-linux_armv7l.whl » et on l’enregistre.


dans Le nom de ce fichier Wheel, « tensorflow-2.0.0 » c’est pour TF 2.0.0 (!), « cp37 » pour Python 3.7 et « linux_armv7 » c’est pour une architecture linux avec un processeur ARM 7, qui correspond à l’architecture et le processeur du Raspberry pi 3. Pour comprendre, sur un PC le processeur peut-être un i3 ou un i5 ou un pentium. Dans tous les cas, c’est un processeur « x86 ».

Installation de tensorflow 2 sous RPI

On ouvre un terminal dans le Raspberry et on se place là où tensorflow-2.0.0-cp37-none-linux_armv7l.whl a été téléchargé (en général, /home/pi/Downloads),
taper
cd /home/pi/Downloads
puis
pip3 install tensorflow-2.0.0-cp37-none-linux_armv7l.whl
Et c’est tout! Job’s done.

La compilation croisée

SUR NOTRE SUPER PC, sous LINUX :

On va installer « DOCKER » (outil de virtualisation pour le système en entier). Cela permettra d’éviter des conflits entre des librairies ou des composants manquants par exemple. J’ai fait un essai sans docker et ça a planté au bout de 20 minutes. Donc avec Docker c’est mieux.
Pour installer Docker (voir https://docs.docker.com/install/linux/docker-ce/debian/).
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io
Perso, j’ai installé docker avec dpkg, pour une raison qui m’échape (il était vraiment tard!), mais les commandes ci-dessus doivent fonctionner.

ENSUITE,
On télécharge le code source du repo de lhelontra, avec git:
sudo apt-get install git -y [on installe l’outil git si nécessaire]
git clone https://github.com/lhelontra/tensorflow-on-arm.git
cd tensorflow-on-arm

On lit ce qui est indiqué dans la section « Cross-compilation » du repo de lhelontra :

On ajoute l’architecture ARM aux repos debian:
sudo dpkg --add-architecture armhf
la seconde ligne est un peu problématique parce qu’on veut ajouter la ligne
deb [arch=armhf] http://httpredir.debian.org/debian/ buster main contrib non-free
dans le fichier « /etc/apt/sources.list »
La solution choisie, bien que très mal, est de passer en ROOT avant de taper la commande :
sudo su -
echo "deb [arch=armhf] http://httpredir.debian.org/debian/ buster main contrib non-free" >> /etc/apt/sources.list
exit

Ensuite
cd build_tensorflow/
sudo docker build -t tf-arm -f Dockerfile .      [utiliser sudo et ne pas oublier le .]

Avant de lancer la dernière commande, on peut éditer le fichier de configuration « rpi.conf » qui se trouve dans le sous-répertoire « configs ».
On vérifie la ligne
TF_VERSION= »v2.0.0″ [version de tensorflow]

On lance la compilation, en remarquant qu’on peut choisir la version de Python (--env TF_PYTHON_VERSION=3.7)
sudo docker run -it -v /tmp/tensorflow_pkg/:/tmp/tensorflow_pkg/ --env TF_PYTHON_VERSION=3.7 tf-arm ./build_tensorflow.sh configs/rpi.conf

La compilation peut durer plusieurs heures (7 heures pour moi), donc à lancer la nuit de préférence.
On obtient finalement un fichier « tensorflow-2.0.0-cp37-none-linux_armv7l.whl » dans le répertoire /tmp/tensorflow_pkg/

On le recopie ensuite sur le Raspberry Pi.
Une fois sur le RPI, il restera à faire un « pip3 install tensorflow-2.0.0-cp37-none-linux_armv7l.whl » pour l’installation sur le RPI, comme indiqué plus haut.

L’intérêt de discuter de la compilation croisée, outre de comprendre un peu le dessous des cartes, c’est que ça peut être utilisé pour créer le fichier wheel pour une autre architecture comme le Beagle Bone Black par exemple (choisir le fichier de config « beagle_black.conf »), pour laquelle il n’y a pas de « release ».

Pour finir, ce post décrit comment installer TensorFlow 2 sur une Rapberry pi 3. Dans sa version la plus simple, il suffit d’installer, sur le RPI, Python 3.7 et de télécharger le fichier wheel adéquat pour TF 2 depuis https://github.com/lhelontra/tensorflow-on-arm/releases .
On peut aussi cross-compiler sur un PC plus puissant, sous linux, avec pour cible d’autres appareils comme le Beagle Bone Black, ou pour utiliser une autre version de Python (>=3.5) pour la RPI.

Et voilà!