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 :
|
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
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à!
