07 mai 2014

Réseaux de neurones 2

Ce billet est la suite de celui-ci qu'il est préférable de lire avant mais c'est vous qui voyez.

Après quelques heures passées sur l'apprentissage du langage Go, je me suis résolu à revenir à mes fondamentaux: le langage C. Cela fait 20 ans que je n'ai pas codé sérieusement, et j'ai eu peur de perdre trop de temps à m'initier à un nouveau langage. Ce qui suit va faire sourire tous les développeurs actuels et définitivement me décrédibiliser auprès d'eux...

Il y a 20 ans, j'étais chercheur et je programmais sur une station de calcul Apollo, dans un environnement de développement équivalent à vi (sous Domain/OS). J'appelais quelques routines graphiques de base, à une époque où l'environnement graphique informatique était en pleine révolution. Mes langages favoris étaient le langage OCCAM et le langage C.

Lorsque de chercheur, je suis devenu professeur en école d'ingénieurs, j'ai enseigné le langage C. La mode était alors au Turbo C de Borland. Mon enseignement n'incluait pas la partie graphique. Mes étudiants se contentaient très bien des tableaux de pointeurs de fonctions de structures doublement chaînées, et des envois de données sur le réseau.

Me voici donc aujourd'hui (enfin, il y a quelques mois), à me demander ce qui pouvait être utilisé comme IDE aujourd'hui, avec tous les progrès informatiques. Je me suis dit qu'un environnement multiplateformes pourrait être intéressant, pour profiter du meilleur des univers Windows ou GNU/Linux.

J'ai choisi Code::Blocks.

Me voici donc en train de compiler quelques programmes simples trouvés sur les différents sites d'initiation à cet IDE. Je redécouvre alors la joie de compiler un code source, d'éditer les liens avec les bibliothèques standards, et de voir les premiers "Hello world" à l'écran. J'ai eu une petite pensée pour Dennis MacAlistair Ritchie...

Très vite, je me suis retrouvé à écrire quelques procédures de calcul concernant les réseaux de neurones. J'ai créé mon premier réseau, mes premières structures, mes premiers malloc (et à chaque malloc son free correspondant ;-).

Comme 20 ans auparavant, j'ai vite trouvé l'affichage standard limité: il me fallait tracer des courbes, des nuages de points, des évolutions de critères en cours de minimisation. Il me fallait appeler quelques fonctions graphiques...

Et là... Grosse déception !

En 20 ans de foisonnement d'interfaces graphiques et d'amélioration de processeurs spécialisés, aucune bibliothèque graphique SIMPLE n'a l'air de s'être imposée. Un truc du genre: j'ouvre une fenêtre, je dessine un pixel dedans quand je veux et basta. Si je suis sous Windows, ça m'ouvre une fenêtre Windows, si je suis sous GNU/Linux, et bien ça m'ouvre une fenêtre GNU/Linux... Bon, j'avoue que je n'ai pas beaucoup cherché, et je compte un peu sur vous pour me montrer la voie si je me suis fourvoyé.

J'ai choisi la bibliothèque graphique SDL parce que pas mal de sites ont l'air de dire que c'est très bien pour s'initier. Ça tombe bien, parce que je ne souhaite pas devenir un professionnel du graphisme, je veux juste dessiner quelques courbes.

Ce qui m'a un peu surpris, c'est de devoir "bidouiller" Code:Blocks pour que mes premiers programmes utilisant SDL puissent fonctionner (je n'ai pas conservé les messages d'erreur, mais j'ai ramé). Heureusement, pas mal de monde utilise le combo Code::Blocks + SDL et la communauté publie des tutos bien faits.

Me voici donc en train de faire mes premières courbes. Bon, mes programmes sont devenus beaucoup moins lisibles maintenant que je les ai truffé d'appels à des routines graphiques plus ou moins claires, mais j'ai compris les bases du truc. Jusqu'au jour où j'ai voulu tracer une courbe dans une nouvelle fenêtre... En effet, SDL ne permet pas d'ouvrir plusieurs fenêtres. Mais heureusement SDL2 peut le faire! Sauf qu'il faut tout réécrire car les concepts graphiques n'ont rien à voir. Je me suis donc tapé le guide de migration SDL1.2 vers SDL2.0 dans la même journée que l'apprentissage de SDL1.2. Je râle, je râle, mais je remercie tous les développeurs qui consacrent leur vie à créer tous ces outils (et les manuels qui vont avec). Je sais maintenant manipuler (un peu) les pointeurs de fenêtres et de Renderer.

Comme SDL2 est sortie en août 2013, j'ai un peu galéré à trouver comment adapter Code::Blocks pour faire fonctionner mes premiers programmes SDL2 (mais j'ai trouvé!). Et j'ai pleuré des larmes de joie quand j'ai vu mes premières courbes tracées dans deux fenêtres séparées.

J'ai ensuite pu attaquer les choses sérieuses avec la mise au point des routines d'optimisation. J'en ai déjà expliqué une partie dans ce billet. Mes premiers programmes ont consisté à mettre au point les routines suivantes:
- calcul du gradient par rétropropagation de l'erreur
- méthode d'optimisation par descente de gradient à pas constant
- amélioration de la méthode précédente avec calcul économique d'un pas variable (méthode de Wolfe et Powell)
- amélioration de la méthode précédente avec calcul itératif de l'inverse du Hessien (méthode de Broyden, Fletcher, Goldfarb et Shanno).

Je suis toujours bluffé par l'accélération foudroyante des méthodes quasi-newtoniennes pour s'approcher du minimum de la fonction.

J'en suis là aujourd'hui.
J'ai un programme illisible qui fonctionne malgré tout parfaitement: je peux créer un réseau de neurones complètement connecté qui peut apprendre virtuellement n'importe quel ensemble d'apprentissage, dès lors que celui-ci est constitué d'un nombre fini de couples {entrées connues, sorties désirées}. Je suis à la recherche d'un problème pas trop complexe, en évitant si possible tous les problèmes de classification (type mémorisations de visage ou reconnaissance de caractères). J'aimerais plutôt un problème de modélisation, comme par exemple la prédiction des éruptions du "Old Faithful" (si quelqu'un a des données récentes sur ce geyser, avec températures, pression, etc.).

Il me faut du temps pour rendre mes routines plus lisibles, pour sauvegarder les coefficients calculés, pour tester d'autres environnements, pour créer un tableur Excel et OpenOffice, pour trouver un problème intéressant à ma portée...

Il me faut aussi comprendre comment faire pour exploiter toute la mémoire de ma machine. Je n'arrive pas encore à créer des matrices de grandes tailles (du genre 10000x10000 réels double précision). Je suis pour l'instant limité à un réseau d'au maximum 50 neurones et 1224 connexions.

Mais 50 neurones, c'est déjà beaucoup ;-)








15 commentaires:

  1. Bonjour,

    Il semble que nous partagions les mêmes centres d'intérêts aussi voici ce que j'utilise de mon coté.

    Plutôt que de coder une librairie, je me suis penché sur l'utilisation de ANN (http://leenissen.dk/fann/wp/).

    Pour la partie X11, j'ai trouvé FLTK (http://www.fltk.org/index.php)

    Cordialement.

    Jean-Philippe

    PS: autre méthode que je regarde concernant l'AI : les SVM (http://fr.wikipedia.org/wiki/Machine_à_vecteurs_de_support)


    RépondreSupprimer
    Réponses
    1. FANN est très intéressant, mais dans mon cas ne permet pas de coder les réseaux que j'utilise. En effet, j'utilise un réseau sans couche, et où le neurone numéro n reçoit des informations de tous les neurones précédents. De plus, je souhaite fabriquer un outil très spécialisé, beaucoup plus que ne l'est FANN.

      Ceci dit, je vais regarder de plus près les structures utilisées dans FANN pour voir si je peux remplacer mes matrices de coefficients qui s'avèrent trop lourdes pour un nombre de neurones élevé.

      Concernant FLTK, c'est malheureusement codé en C++...

      Enfin, sur les SVM, je ne souhaite clairement pas travailler sur des problèmes de classification, mais bien sur de la modélisation...

      Merci pour les liens !

      Supprimer
  2. Pour la partie graphique regardez Processing. Simple et efficace. Bonne reprise ! ;-)

    RépondreSupprimer
    Réponses
    1. Çà doit être bien... quand on fait du JAVA ;-)

      Supprimer
  3. C'est marrant qu'utilisant Code::Blocks tu n'es pas essayé wxWidgets.
    Perso (http://frouin.me/software/) j'ai codé ce genre de chose en C++ avec wxWidgets le rendu est visible ici : http://frouin.me/images/softs/MLP.png
    Et cela tournait indépendamment sous Win ou Lin
    Bonne continuation et merci pour ton blog bien agréable à lire !

    RépondreSupprimer
    Réponses
    1. C'est du C++ et je ne code qu'en C... Désolé.

      Supprimer
  4. Je me suis toujours dit qu'il serait possible de prédire la disponibilité de vélos aux bornes Vélib (ou Vcub à Bordeaux etc), en utilisant plusieurs paramètres type météo, température, heure (plus difficilement prévisible évènements type concerts/grève etc).

    C'est un ensemble à priori fini de couple, et ça pourrait rendre beaucoup de services ;)

    RépondreSupprimer
    Réponses
    1. Il me faudrait pouvoir télécharger les données...
      Mais je cherche plutôt un problème de modélisation physique où l'humain n'interviendrait pas.

      Supprimer
    2. Les données sont relativement simple a récupérer (en tout cas pour le Vcub de Bordeaux, ça je peux te le faire ;)).
      Mais ouaip c'est un problème très dépendant des humains pour le coup

      Supprimer
  5. Je travaille actuellement sur la conception d'un simulateur e circuits électroniques. En tant qu'ingenieur "hardware", je n'ai fait d'informatique que depuis que je programme des microcontroleurs. Autant dire que les interfaces graphiques, c'est vraiment pas mon truc.

    Pour mon simulateur, j'ai choisi l'affichage dans un programme externe : Matlab (pour les gens riches) ou LTSpice (pire ceux qui se contentent d'outils gratuits). Dans le premier cas, il s'agit d'un simple fichier texte à écrire, dans le second, un petit logiciel de conversion est nécessaire pour passer du texte à des graphiques (logiciel disponible gratuitement sur le Yahoo Group de LTSpice).

    Je ne sais pas si l'affichage graphique proposé par ces logiciels est adapté à vos besoins, mais si ils font l'affaire, cela pourrait vous simplifier la vie.

    (By the way, LTSpice, bien que logiciel pour Windows uniquement, tourne de manière très fluide sous Linux + Wine)

    RépondreSupprimer
  6. Bonjour,

    J'ai suivi il y a quelques années la même démarche. J'ai aussi fini avec CodeBlocks. Ce qui m'a le plus impressionné c'est plutôt le versionning. Avez vous regardé du coté de Svn, Git et GitHub. Encore un pan de l'espace à découvrir. Mais sur ces points la il faut reconnaître que les avancées sont impressionnantes. Fini les recherches de bugs dans des piles d'archives zip ou de répertoires plus ou moins agencés.

    RépondreSupprimer
  7. Honnêtement, je ne suis pas convaincu du choix du C. Je comprends l'envie de ne pas devoir apprendre encore une tonne d'autre choses, mais je pense qu'un usage limité du C++ (en, gros, on garde la structure d'un programme en C, on ne défini pas ses propres classes..., mais on utilise juste vector pour gérer des tableaux de taille variable ou string pour des chaînes de caractères) peut s'apprendre en 1h pour qui connait le C, et permet d'éviter de devoir faire attention à tout un tas de détails, et donc de se concentrer sur ce qui fait l'intérêt du programme. Après, il sera toujours temps d'en découvrir plus au besoin.

    Pour les graphiques, toujours si on part dans l'idée de faire un code compilé en C++ mais écrit à la mode C, le plus simple que j'ai vu (y compris en terme d'installation) est http://cimg.sourceforge.net/ . Après, si on veut faire plus joli et plus animé, il y a la SFML (http://www.sfml-dev.org/resources-fr.php) ou cinder (http://libcinder.org/gallery/).

    RépondreSupprimer
    Réponses
    1. Ahh les toolkits graphiques...
      entre les GTK et Qt qui ne sont portables que sur les plateformes sur lesquelles ils sont portés (pas Haiku pour GTK par exemple), et les trucs liés à un langage comme Tk qui préfère TCL...
      Et il y a tout un spectre entre ceux comme FLTK qui réimplémentent tout avec un support minimum de l'OS, et à l'autre bout WxWidget qui tente de réutiliser au maximum les contrôles natifs de l'OS (ce qui est bien pour plein de raisons (accessibilité, look & feel...) mais complexifie l'utilisation.

      SDL quant à lui est au départ une bibliothèque plutôt orientée jeux vidéo, où l'usage de la métaphore WIMP (windows, icons, menus, pointer) est rarement utile, et de plus était destiné à être très portable.

      Sinon j'ai découvert IUP il y a peu, que quelqu'un a porté sous Haiku :
      http://www.tecgraf.puc-rio.br/iup/
      C'est assez peu utilisé mais développé par des scientifiques, et est disponible sur les plateformes courantes. Mais je n'ai pas testé.

      J'éviterai de répondre sur le langage, étant biaisé en faveur du C++ de par l'utilisation de Haiku dont toute l'API est écrite avec (ce qui pose aussi des problèmes comme le FBC, je n'ai pas dit qu'il était parfait).

      Et sur les éditeurs intégrés, j'ai bien trop l'habitude d'Emacs/vim/Pe/gedit au pire/... et de make & friends dans le terminal pour avoir quoi que ce soit à dire sur eux :-D

      Supprimer
  8. Si tu es prêt à passer au C++, Qt semble exactement correspondre à se que tu recherches.

    RépondreSupprimer
  9. Je suis un peu surpris de voir que personne n'a mentionné gnuplot ici, donc je le fais. C'est un programme annexe, ce qui permet de laisser votre code "propre" (sans appel à des routines graphiques de partout). gnuplot lui même est scriptable et accessible.

    RépondreSupprimer

Lectrice, admiratrice, avocate, magistrate, programmeuse, dessinatrice, chère consœur, femmes de tous les pays, lecteur, j'ai toute confiance en vous pour prendre bien soin de vérifier que votre prose est compatible avec les normes orthographiques et grammaticales en vigueur. Et si vous pouviez éviter les propos insultants ou haineux, je vous en serais reconnaissant.
N'hésitez pas à respecter ces quelques règles qui peuvent même s'appliquer en dehors de ce blog.

Les commentaires sur ce blog sont modérés. Votre message apparaîtra sur le blog dès que le modérateur l'aura approuvé. Merci de votre patience.