Neuronal Computing

TP « neural computing » (4A)

FIchiers à downloader


Préambule important :


  • TP à réaliser en binôme au maximum, vous
    pouvez faire le TP tout seul si vous le désirez. Aucun de
    groupe de 3 (ou plus) ne sera accepté !

     

     

  • Vous devez absolument suivre scrupuleusement les indications
    de ce document, car votre travail sera noté par un programme
    (le programme « test » qui vous est fournit),
    ainsi un programme qui plante, ou simplement qui utilise mal les
    formats imposés donnera lieu à la note 0! Vous avez
    les données et les programmes pour tout tester, faites le!
  • Votre programme ne doit pas planter (utilisez valgrind
    pour vérifier votre utilisation de la mémoire), un
    programme qui plante -> 0. Attention, un programme avec des
    erreurs de pointeurs peut très bien marcher sur une machine
    et pas sur une autre, ou même marche un jour et planter le
    lendemain … Il n’y aura pas de réclamation possible dans ce
    cas, à vous de vérifier que votre programme ne
    comporte pas d’erreur de ce type, en utilisant valgrind.

     

     

  • Votre programme doit être léger (par opposition
    à ce que j’appelle la « Loi
    de Lourd
    ») : ça veux dire s’exécuter
    suffisamment rapidement et utiliser une quantité mémoire
    raisonnable. Si vous ne partez pas dans des « délires »
    cette contrainte n’en est pas vraiment une, mais je préfère
    prévenir depuis qu’un binôme de 2A m’ont « fièrement »

    rendu un programme censé faire un système d’écriture
    intuitive pour téléphone mobile, nécessitant
    1H30 pour composer le message « bonjour » …
    Clairement vous me faites un truc pareil en 4A , c’est 0, direct et
    non négociable.

  • J’encourage fortement les échanges d’idée,
    surtout sur ce type de TP. Cependant notez que l’échange
    d’idée s’arrête là ou commence la copie de codes
    ! J’utiliserai Baldr

    pour traquer les tentatives de fraudes.

 

Et maintenant qu’on en a finit avec les avertissements d’usage,
attaquons le plus intéressant …

 

Le Sujet

 

Introduction

 

Dans un jeux vidéo classique commandé par un clavier
ou un joystick, les données sont simple à interpréter,
c’est une simple variable qui est initialisé par une librairie
de gestion du joystick. Dans le cadre d’utilisation d’une Wiimote

les données sont d’un autre type, il s’agit d’une suite de
mesure d’accélération sur 3 axes. Voici ce que cela
donne graphiquement :

 

Voici trois occurences d’un même mouvement (un « oui »),
vu sous deux angles différents.

 

 

Et voici sous deux angles différents, les données
correspondant à trois mouvements de type « non »

 

 

 

Chaque graphique représente 3 répétitions
d’un même geste (en 3 couleur différentes). L’image de
gauche correspond à un geste que j’appelle un « oui »
(on incline verticalement la wiimote comme si c’était la tête
d’une marionnette disant oui). L’image de droite correspond à
un « non » (on oriente la wiimote à

droite puis à gauche alternativement comme une marionnette
ferait non de la tête). Note : il ne s’agit pas de la mesure
des déplacement de la wiimote mais les accélérations
mesurée (accélération != mouvements).

 

Il est manifeste ces 2 graphiques sont facilement différentiable
visuellement. Si on regarde un troisième graphique il est
facile , visuellement, de dire si le mouvement correspondant est un
« oui » ou un « non ».
Par contre écrire un algorithme (une suite d’instruction)
faisant automatiquement ce type d’analyse serait excessivement
complexe à mettre en oeuvre. Surtout, il faudrait écrire
du code pour chaque nouveau type de geste que l’on veux être
capable de reconnaître automatiquement. C’est pour cela qu’on
va utiliser des réseaux neuronaux. La spécificité

des techniques neuronales est qu’ils apprennent par des exemples.
Cela nous donnera la possibilité d’aborder ce problème
élégamment On ne codera pas une solution au problème
de reconnaissance d’un geste mais plutôt une chaîne
d’analyse de données neuronales qui sera re-utilisable. Ainsi
une fois cette chaîne écrite, on pourra gérer de
nouveaux gestes sans ajouter de nouvelle lignes de codes au
programme. Il suffira « d’enregistrer » des
exemples de nouveaux gestes et de relancer le programme
d’apprentissage, ce qui ne nécessitera aucune écriture
de code supplémentaire …

 

 

L’objectif

 

L’objectif de ce TP est de faire un système de
reconnaissance de geste utilisant une Wiimote.
L’évaluation de ce TP se fera via le calcul d’une matrice
de confusion
, meilleur sera le système de reconnaissance
que vous aurez produit, meilleur sera votre note à ce TP. Pour
cela nous allons utiliser des librairies « open source »
:

 

     

     

  • La libwiimote
    : cette librairie permet d’accéder simplement aux données
    que produit la wiimote. Les seules qui vont nous intéresser
    ici sont les données de l’accéléromètre
    3D. Cela veux dire qu’on dispose de mesures d’accélération
    sur 3 axes, environ 100 fois par seconde. Pour le TP je vous
    fournirait les données directement sous forme de fichier donc
    vous n’aurez pas à vous occuper de cette partie. Si ce n’est
    qu’a vous intéresser de savoir comment sont produites ces
    données. Mais si vous voulez continuer après le TP ou
    simplement vouloir tester vous même votre détecteur de
    geste, vous aurez à installer cette librairie pour utiliser
    une wiimote avec votre PC. Cette librairie s’appuie sur la librairie
    bluez qui sert à

    communiquer en « bluetooth » avec la wiimote.

  • La librairie FANN :
    pour « Fast Artificial Neural Network », cette
    librairie permet de programmer simplement des réseaux
    neuronaux. Cette librairie que nous allons utiliser pour former le
    coeur de notre système de reconnaissance. Cette librairie est
    normalement déjà installé sur les machines de
    TP.

     

     

 

Dans le cadre du TP nous n’auront besoin que de FANN. Vu que nous
avons un temps limité je vous fournis aussi quelques codes de
base. Nous n’auront pas besoin de tous ces codes dans le TP.
Typiquement la partie acquisition des données ne nous sera pas
utile dans le cadre de ce cours, mais je vous la met à
disposition, si vous avez envi de créer votre propre base de
donnée de mouvements.

 

Conseils pour aborder ce TP

 

  • Essayer d’abord de faire tourner cette chaîne de
    traitement sans aucune modification et essayez de bien comprendre
    toutes les informations la composant.

     

     

  • Essayez ensuite d’apporter des modifications aux endroits
    proposés dans le but d’améliorer le système de
    reconnaissance. Ce faisant vérifiez bien que les nouvelles
    sorties des programmes modifiés respectent bien les formats.
    Ensuite déroulez toute la chaîne de traitement avec vos
    modifications et vérifiez (avec le programme « test »
    que cela améliore vraiment le système de
    reconnaissance.

     

     

  • ATTENTION ! lors du rendu par mail, pensez bien à
    envoyer :

      • votre fichier C de paramétrisation en attachement (1
        seul fichier), avec en commentaire sur la première ligne de
        votre code les noms composant le binôme. Le nom du
        fichier doit être le nom de base de votre mail (par exemple
        : « dupond.c » si votre mail est
        dupond@et.esiea.fr .)

         

         

      • votre fichier de réseau neuronaux (le résultat
        du programme « train »). Le nom du
        fichier doit être le nom de base de votre mail.
        (« dupond.net » si on reprend l’exemple du
        point au-dessus).
      • Vérifiez bien qu’il s’agit bien des bonnes versions
        de ces fichiers, car vous allez en générer un bon
        paquet et les erreurs seront fréquentes, à vous
        d’être rigoureux dans vos noms de fichier ainsi que dans le
        déroulement de la chaîne de traitement. Je vous
        conseille très fortement de dérouler completement la
        chaîne de traitement du début à la fin jusqu’à

        l’étape finale de test, avant d’envoyer votre travail.

 

Base de code

 

Voici la base de code que je vous fournit pour ce TP, seul les
programmes « param » et éventuellement

« train » sont à modifier. La suite de
logiciels, telle que fourni en l’état, est peu efficace car la
paramétrisation est « simplissime ». À
vous de l’améliorer. Le niveau de validation (en terme de
pourcentage de reconnaissance) minimum du module sera donné
une fois qu’on aura un peu progressé sur le problème.

 

 

Téléchargez l’archive attaché à ce
mail et installez la dans un répertoire, pour compiler les
codes C suivez les instructions en entête des fichiers. Il y a
un fichier « log.txt » qui vous montre les
étapes de base sur un ensemble de donnée de test.

 

wii_move

 

wii_move : ce programme vous
permet d’enregistrer des mouvements fait avec une wiimote. C’est avec
ce programme qu’on a crée les données de ce TP.

 

 

Il s’utilise en ligne de commande comme
cela :

 

 

 ./wii_move WII_ADDR username move1 move2 move3 [...]

Le premier argument (WII_ADDR) est l’adresse physique de la wiimote, elle s’obtient en lançant la commande :

 hcitool scan

et en appuyant simultanément sur les boutons 1 et 2 de la wiimote, au bout de quelques seconde l’adresse de la wiimote s’affiche (ça ressemble à quelque chose du style : 00:19:1D:D5:0E:CF).
Il se peut que le service bluetooth ne soit pas démarré sur votre machine, faites alors (avant toutes les autres opérations), votre mot de passe vous sera demandé :
Le second paramètre est le nom de la personne qui fait les mouvements avec la wiimote, c’est une information importante dans la mesure ou les gestes dépendent de ceux qui les fonts… On peut même imaginer un système qui essaye de reconnaître non seulement les gestes, mais aussi qui les fait… Bref à notre niveau ce n’est pas primordial mais ça peut être utile plus tard…

Tous les paramètres suivants sont une liste de noms de gestes. Ces mots seront affichés dans un ordre aléatoire, il suffira alors de les exécuter avec la wiimote dans la main et la gâchette enfoncé (bouton « B ») tout au long du mouvement. A la fin de l’enregistrement de chaque mouvement la wiimote vibre légèrement pour indiqué que l’enregistrement du mouvement effectué est terminé. Ce programme crée à la fin de chaque mouvement un fichier dont le nom se compose comme ceci : « username_moveName_nbr.txt » (nom de l’utilisateur, puis le nom du mouvement, et enfin un compteur).
Cela fait un fichier par mouvement, le contenu des fichiers ressemble à ceci :

 

BEGIN
0.962   0.000   -0.308  0
0.462   0.200   -0.308  20
0.077   0.360   -0.192  30
-0.231  0.520   -0.192  40
-0.538  0.640   -0.269  44
-0.808  0.720   -0.154  62
-0.923  0.800   0.000   72
-1.115  0.800   0.115   81
-1.115  0.800   0.346   85
-1.115  0.720   0.462   103
END

Les mots clé, BEGIN et END sont là pour indiquer le début et la fin d’un mouvement, les données s’interprètent ligne par ligne, les trois premières colonnes correspondent aux accélérations mesurées sur les axes x, y, z, la quatrième colonne est le temps en microsecondes, mesuré depuis le moment où la gâchette (bouton « B ») à été enfoncé.
param

Préambule : Nous verrons en cours pourquoi nous ne pouvons pas directement utiliser directement les sorties de la wiimote en entrée du réseaux de neurones, et nous verrons en TP des pistes pour trouver une bonne paramétrisation. Pour le moment ce programme n’est qu’une coquille pratiquement vide, les paramètres extraits dans ce code ne sont que : le minimum, la moyenne et le maximum des accélérations sur les 3 axes. C’est clairement insuffisant : on ne peut résumer un mouvement complexe par ces simples trois paramètres. Ce sera à vous de trouver une paramétrisation plus fine, qui donnera de meilleurs résultats.

param : Ce programme est au coeur de ce TP, c’est celui qui transforme les sorties « brut » des accéléromètres de la wiimote en des entrées « compréhensible » par le réseau de neurones. Il s’utilise en entrée/sortie standard :

 

     cat *_jump_*.txt | ./param 4 2 >> trainData.pat

Voilà comment interpréter cette ligne de commande : on prend tous les fichiers de type «*_jump_*.txt», on passe ces fichiers « au travers » l’application « param ». Celle-ci transforme les données brut, de manière à ce qu’elles soient utilisables par notre réseau de neurones, et les ajoute dans le fichier « trainData.pat ». Elle va écrire des données au format FANN. Ce format exige les informations suivantes pour chaque exemple :

*

Les données à mettre en entrée du réseau de neurones (les données de la wiimote) : il s’agit d’une suite de nombres, un vecteur.

*

comment classer ces données : la sortie attendu correspondant à l’entrée fournie. Cette information se fourni aussi sous forme de vecteur, il y a autant de composantes dans le vecteur qu’il y a de classes à reconnaître. Ce vecteur doit être à -1 sur toutes les composantes , sauf la composante correspondante à l’exemple traité( ou elle doit être à 1).

La ligne de commande précédente on créer des exemples pour le mouvement « jump » et il s’agit du mouvement numéro 3 sur un total de 4 mouvements différents. (Attention c’est le mouvement 3 et non pas 2 car on commence à compter à 0).

Voici un exemple d’un couple entrée/sortie au format FANN :

-0.577000 -0.040947 0.692000 -2.200000 -0.690823 0.200000 -0.654000 0.814953 2.462000
-1.000000 -1.000000 1.000000 -1.000000

La première ligne est constituée de données de la wiimote (transformé par le programme « param »).

La deuxième ligne correspond (puisqu’on fait de l’apprentissage supervisé) à la sortie attendue (ici le troisième ([2]) type de mouvement sur 4 possibles).

Un fichier de donnée d’apprentissage comporte toute une liste suite de couples exemples de ce type (parfois appelé « pattern »), avec en plus, une première ligne indiquant le nombre de couples total qu’il y a dans le fichier, ainsi que le nombre de composantes sur le vecteur d’entrée et de sortie. Cette entête sera en général créée « à la main » après avoir constitué le fichier d’exemples, car il est plus facile de savoir à posteriori combien d’exemples on utilisera…

Ici l’entête d’un tel fichier serait :

24 9 4

24 paires d’exemple, le réseau de neurones à 9 entrée et 4 sorties.

Et voici le début d’un fichier complet d’entraînement au format FANN

24 9 4
-0.577000 -0.040947 0.692000 -2.200000 -0.690823 0.200000 -0.654000 0.814953 2.462000
-1.000000 -1.000000 1.000000 -1.000000
-1.154000 -0.045991 0.769000 -3.800000 -0.718428 1.400000 -1.423000 0.791240 4.231000
-1.000000 -1.000000 1.000000 -1.000000
-1.269000 -0.079980 0.692000 -3.440000 -0.748824 1.120000 -1.038000 0.595402 3.654000
-1.000000 -1.000000 1.000000 -1.000000
[...]

Pour constituer un ensemble d’apprentissage il faudra donc utiliser ce type de commandes avec les données dont vous disposez et avec votre version amélioré du programme « param ». Je vous conseille éventuellement de faire un script qui enchaîne ces traitements, car sinon vous aurez vite fait de mélanger vos données, ce qui évidement n’aidera pas le réseau de neurones à fonctionner correctement …

BuildTrainData

Ce script permet d’automatiser la création d’ensembles d’apprentissage. Il utilise le programme « param » : Il compte combien il y a d’exemples, combien il y a de classes différentes , etc … Voir le fichier « log.txt » pour voir comment il s’utilise par l’exemple. Pour pouvoir utiliser ce script il faudra changer les droits du fichier pour le rendre executable.

     chmod u+x buildTrainData.pl

train

train : ce programme effectue l’ « entraînement » d’un réseau de neurones. En voici un exemple d’appel :

 ./train trainData.pat testData.pat neuralNetworkOutput

Il demande l’entraînement d’un réseau de neurones, sur les données « trainData.pat ». Il affiche au fur et à mesure de l’apprentissage le taux d’erreur sur les données d’apprentissage, ainsi que le taux d’erreur sur des données de test (« testData.pat »). C’est en surveillant ces 2 suites de valeurs qu’on surveillera Principalement pour éviter le phénomène de sur-apprentissage vu en cours. Typiquement si le taux d’erreur descend sur l’ensemble d’apprentissage mais remonte sur l’ensemble de test, c’est qu’on est en sur-apprentissage et qu’un tel réseau fonctionnera très mal en réalité. C’est pourquoi ce programme ne produit pas un seul réseau final en sortie mais enregistre le réseau au fur et à mesure de sa convergence en concaténant un numéros à la fin du nom donné en dernier paramètre. Cela permet de choisir à quel moment le réseau semble offrir les meilleur performance en généralisation, c’est à dire quand le taux d’erreur est au plus bas sur l’ensemble « testData.pat ».

Voici un exemple de sortie du programme train :

Epochs            1. lr=0.700 trainError: 0.989182 : testError : 0.989392 :
Epochs           10. lr=0.700 trainError: 0.979252 : testError : 0.976601 :
Epochs           20. lr=0.700 trainError: 0.900293 : testError : 0.880573 :
Epochs           30. lr=0.700 trainError: 0.734298 : testError : 0.727524 :
Epochs           40. lr=0.700 trainError: 0.677639 : testError : 0.656639 :
Epochs           50. lr=0.700 trainError: 0.569507 : testError : 0.546091 :
Epochs           60. lr=0.700 trainError: 0.538132 : testError : 0.522665 :
[...]

Je pense que l’augmentation des perfomance de reconnaissance du système se fera principalement en améliorant la partie paramétrisation (programme « param »), cependant je pense qu’il y a aussi une marge d’amélioration intéressante en modifiant ce programme. On peut modifier :

*

La topologie du réseau de neurones utilisé. (nombre et arrangement des neurones dans le réseau). J’ai mis par défaut 1 seule couche caché composé de 6 neurones (en plus de ceux défini par le fichier de données sur les couches d’entrée et sortie).
*

Le protocole d’apprentissage (nombre d’itérations, paramètres d’apprentissage, etc …) est aussi définit dans ce programme.

Vous pouvez donc modifier ce programme selon vos intuitions, mais attention veillez toujours à le tester via le programme test (non modifié) que je vous fournis, car c’est celui que j’utiliserai pour évaluer votre travail.
test

Attention : utilisez bien « ./test » et non « test » qui est une commande unix.

Ce programme permet de tester en détail l’efficacité d’un couple réseau de neurones / paramétrisation. Il calcule la matrice de confusion du système de reconnaissance. C’est ce que vous allez utiliser pour analyser les erreurs de votre système de reconnaissance de geste. C’est ce que j’utiliserai pour évaluer la qualité de votre travail. Il s’agit donc là de quelque chose de très important… Voilà comment il s’utilise :

     ./test validationData.pat neuralNetworkOutput4500.net

Il prend en paramètre un fichier de données d’exemple. Idéalement il faudrait que ce soit des données jamais utilisés au préalable. Ce fichier (« validationData.pat ») est le résultats de données « brut » paramétrés par le (votre) programme « param ». Tester un réseau de neurones ou n’importe quel système d’apprentissage avec des données utilisées lors de l’apprentissage est une erreur grave, car elle amène à surestimer la qualité du réseau. (un peu comme mettre le sujet de l’éval’ de l’an passé à un examen ;-) , c’est maladroit …). C’est pourquoi on façonnera notre système avec 3 ensembles de donnés :

*

un ensemble d’entraînement : pour construire le réseau

*

un ensemble de test : pour éviter le sur-apprentissage

*

un ensemble de validation : pour mesurer la réellement qualité du système. C’est cet ensemble que nous utiliseront

Voici un exemple de sortie de ce programme :

wassner@v1009:src$./test validateData.pat totoNN400.net
confusion matrix :

(13.00) 1.00 3.00 0.00
2.00 (13.00) 0.00 1.00
0.00 1.00 (2.00) 9.00
0.00 0.00 2.00 (15.00) 

normalised confusion matrix :

(0.76) 0.06 0.18 0.00
0.12 (0.81) 0.00 0.06
0.00 0.08 (0.17) 0.75
0.00 0.00 0.12 (0.88) 

mean perf = 0.656556

C’est cette dernière valeur : « mean perf » (moyenne de la diagonale) qui sera utilisée pour noter votre travail. J’utiliserai un ensemble de donnés dont vous ne disposez pas pour évaluer votre travail, ce sera bien sûr des données du même type. Cela m’assurera que ce qui est mesuré c’est bien la capacité de généralisation de votre réseau, et non un apprentissage « par coeur » des données d’exemple.
runNN

Vous n’aurez à priori pas besoin de ce programme pour le TP, mais si vous disposez d’une wiimote et d’un ordinateur équipé bluetooth, je pense que vous aurez envi d’essayer votre programme en vrai. Pour faire le traitement complet il faut enchaîner le programme d’acquisition (wii_move), puis la paramétrisation (param), et enfin le réseau de neurones (runNN).

./wii_move 00:19:1D:D5:0E:CF | ./param | ./runNN wii320.net

Note : de même que lors de la phase d’enregistrement des données, il faut tenir la gâchette (bouton « B ») enfoncé lors du mouvement.
Chaîne de traitement

Si on résume, vous devez enchaîner une chaîne de traitement composé de 3 programmes :

*

la paramétrisation (param)

*

l’apprentissage (train)

*

l’évaluation (test)

Cela va vous amener à manipuler des fichiers, des formats et concepts intermédiaires. Il vous faudra être très sérieux dans la gestion de ces données, et prendre un maximum de notes sur tout ce que vous appliquez à vos données, pour être capable de vous souvenir où vous en êtes dans vos modifications…
Conclusion

Il s’agit d’un TP qui peut paraître difficile au premier abord. Je pense sincèrement qu’il n’est pas si difficile que ça si on suit bien la progression cours, TD, puis TP. Je donnerai des indices et de conseils durant les heures de TP. Dans la mesure ou je vous fournit une chaîne de traitement complète que nous n’aurez qu’à modifier, je pense que cela ne demandera que très peu de codage, et plus de réflexion … Je vous avez une semaine de délais après la dernière heure de cours ou TP pour rendre ce projet par mail. ce qui vous laissera le temps de réfléchir posément au problème pour essayer d’améliorer au mieux la chaîne de traitement. Cette note sera pondérée par votre note d’évaluation.

Vous pouvez bien sûr continuer ce projet en dehors de ce cours. Ce serait vraiment sympat’ de créer un jeu autour de ces fonctionnalités, je suis prèt à vous aider dans ce but. Si cela vous intéresse venez me voir on essayera de trouver un cadre pédagogique pour dégager le temps nécessaire à un tel projet.

Laisser un commentaire

Your email address will not be published. Required fields are marked *