Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Méthodes prédictives Discussion :

Apprentissage par renforcement sur réseaux de neurones


Sujet :

Méthodes prédictives

  1. #1
    Membre habitué
    Apprentissage par renforcement sur réseaux de neurones
    Bonjour à tous,

    Dans le cadre de mon "auto-formation" dans le domaine de l'IA et plus particulièrement des réseaux de neurones (j'apprécie le bio-mimétisme), je souhaite pouvoir développer un agent capable d'apprendre par renforcement.

    Je me suis alors lancé dans l'idée de créer un petit "jeux" assez simple où, dans un environnement dynamique et, à terme, non déterministe, l'agent doit collecter des points au sein d'un milieu hostile ; une sorte de mix entre un jeu de snake et un pacman en somme. En entrée, l'agent reçoit les positions et le type de tous les éléments présents dans son champ de vision, et en sortie deux valeurs réelles comprises entre -1 et 1 (un actionneur pour la rotation, un actionneur pour la translation).

    Je me suis donc penché un peu sur le Q-Learning, couplé aux réseaux de neurones, mais rapidement, je m’aperçoit que ce n'est peut-être pas vraiment la meilleur solution pour mon problème. En effet, les actionneurs de mon agent sont la rotation et la translation, donc, techniquement, même si je limite l'environnement à une simple fenêtre, de 800 * 600, cela fait déjà au minimum 480000 états possibles pour l'agent, et en théorie, il existe une infinité d'actions possibles pour chaque entrée...

    Je me demandais alors si oui ou non le Q-Learning était une solution viable pour mon problème, et, dans tous les cas, quels autres algorithmes d'apprentissage pouvaient s'avérer être de bonnes pistes, compte tenu du fait que je tiens vraiment à généraliser au maximum via réseaux de neurones.


    D'avance, merci pour vos retours !

  2. #2
    Membre habitué
    Bonjour BioKore,

    Je ne sais pas quel algorithme utiliser pour ton besoin présent, par contre j'ai un doute sur le choix que tu as fait pour tes données en entrée.

    En entrée, l'agent reçoit les positions et le type de tous les éléments présents dans son champ de vision
    J'aurai plutôt eu tendance à gérer en entrée la perception de l'agent, qu'est-ce qui est dans le champ de vision par exemple.

    Cordialement,

  3. #3
    Membre habitué
    Bonjour,

    Merci pour ce retour. J'ai un peu avancé sur ma compréhension du Q-Learning, mais même si le caractère "grand" de la dimension de mon espace d'état est finalement géré et généralisé grâce au réseau de neurones, le caractère "infini" de mon espace d'actions, lui, reste un problème....

    En ce qui concerne ta question sur ce qui est présent dans le champ de vision de l'agent, pour le moment, il s'agit simplement de tout ce qui est à l'écran, soit : la position des "cibles" (les trucs à récupérer) et la position des monstres. Je n'ai pas encore implémenté l'aspect "champ de vision" ; je pense faire ça ultérieurement, une fois que j'aurais trouvé une réponse au sujet de l'apprentissage...

    Je ne comprends vraiment pas ton retour :
    J'aurai plutôt eu tendance à gérer en entrée la perception de l'agent, qu'est-ce qui est dans le champ de vision par exemple.
    Car finalement, si je lui donne en entrée les positions et le type de chaque élément visible, cela revient un peu à ce que tu proposes non ?

    Merci.

  4. #4
    Membre habitué
    Car finalement, si je lui donne en entrée les positions et le type de chaque élément visible, cela revient un peu à ce que tu proposes non ?
    Alors ce que je te propose concernant les entrées est l'exact opposé de ce que tu veux faire. En effet, tu veux que ton agent ait une certaine omnipotence de tous les éléments qu'il doit récupérer.

    Moi je te propose, et ça n'engage que moi, de donner une vision du monde limité à ton agent. Non seulement il ne saura pas où seront les éléments a récupérer mais il ne saura pas dans un premier temps les distinguer par rapport à d'autres éléments qu'il pourrait rencontrer, un élément nocif par exemple. Tu peux donner des codes couleur différents a un élément a récupérer et à un élément à ne pas récupérer.

    Il y a plusieurs avantages à procéder ainsi. D'abord tu ne t'inquiètes plus de la taille de ton monde virtuel. Ensuite, et contrairement à ce que tu obtiendrais avec l'omnipotence, si tu entraines ton agent avec des éléments à des dispositions précises, changer leur dispositions ne rendra pas l'agent inopérant.

  5. #5
    Membre habitué
    Bonjour, et merci pour ce retour.

    Cette vision m'a l'air intéressante, mais je ne suis pas sure de tout comprendre. En fait, ton idée c'est de dire à l'agent : "" découvre le monde tout seul et tu te rendras compte tout seul que "manger" les objets verts est une bonne chose et "se faire manger" par les objets rouges est une mauvaise chose "". C'est bien ça ?

    Je pense comprendre en partie ton idée, et cela me parait pas mal, mais je ne vois vraiment pas trop comment formuler la chose....
    Au risque de paraître lourd, saurais-tu détailler un peu plus ton idée ?

    Pour info, le monde dans lequel évolue l'agent est en évolution permanente, d'où l'idée de vouloir lui faire comprendre ce qu'il faut et ne faut pas faire ; l'entraînement DOIT donc se faire dans ce type d'environnement.

    Pour en revenir à mon problème initial et au code tel que je le conçois actuellement, je pense avoir trouvé une idée, je vous laisse me dire si celle-ci est viable ou pas :

    Entraînement :
    Un premier réseau de neurone pour apprendre les relations des Q-Values. En entrée (pour le moment) les positions de tous les éléments sur l'écran + une action aléatoire.
    On propage, on effectue l'action, on rétro propage avec la récompense obtenue à l'état 's+1'
    On reboucle tant que l'erreur entre la récompense prédite par le réseau et la récompense réelle est supérieure à x%.

    Une fois l’entraînement fait, on peut utiliser la méthode Q-Learning générale (Q[s,a] = r + gama * max(Q[s+1, ar])) où le max Q(s+1,ar) est trouvé en faisant varier l'action 'ar' sur 500 valeurs d'actions aléatoires.

    Comme ça, ça devrait pouvoir marcher, en partie, mais je me rend compte de plusieurs choses :
    - pas d'apprentissage online pur (dans ce cas précis) --> mais là c'est avant tout mes compétences de développeur qui limitent la chose
    - solution pas nécessairement optimale car les actions sont choisies sur 500 possibilités aléatoires (arbitraire, j'aurais pu mettre 2000) ce qui limite le champ.
    - je ne saurais pas quoi dire, mais quelque chose la dedans me chiffonne... In fine, ce que je veux de mon agent, c'est de récupérer ce qu'il perçois, de le traiter pour sortir une action optimale vis-à-vis d'un objectif donné, soit un réseau avec en entrée, situation actuelle + ordre, et en sortie on récupère une action optimale.


    Aussi, je pensais peut-être essayer de trouver un moyen de limiter l'espace des actions par des actions plus macro. Par exemple, au lieu de dire qu'une action est "tourne de 2° et avance avec un facteur de 0.34", lui dire "rapproche toi de tel objet" ou "évite absolument tel objet". Mais là aussi, il faudrait que j’entraîne des réseaux spécifiques à chaque action finalement. Bref, c'est une idée que j'essaierais de développer plus tard.


    Merci.

  6. #6
    Membre habitué
    Bonjour à tous,

    Bon, bien que le sujet n'ait pas l'air d'attirer les foules, je vais tout de même continuer d'exposer mon projet et mes problèmes au fil du temps ici...

    Pour résumer : j'ai créé un petit jeu avec SFML (en C++ donc), dans lequel nous avons des humains, des zombies, et des objets à récupérer. L'objectif final pour moi est d'apprendre aux humains à récupérer les objets répartis aléatoirement au milieu d'un champ remplis de zombies ; un objet récupéré = +5 points. Bien entendu, si un humain se fait attraper par un zombie, son score retourne à 0 et il est réinitialisé aléatoirement sur la carte.
    En parallèle, les zombies doivent apprendre à attraper des humain (et eux ne peuvent pas être réinitialisés). Un humain attrapé offre un score de 10 + score de l'humain en question.

    Étant assez machiavélique, je décide alors dans un premier temps, d'apprendre aux zombies d'attraper des humains.

    L'environnement est représenté par des positions réelles comprises entre 0 et 800 sur les X (largeur horizontale de fenêtre) et entre 0 et 600 sur les Y (hauteur verticale de fenêtre).


    Ici, tous les points jaunes représentent les humains et les zombies (oui, je n'ai pas encore trop compris comment changer la couleur des éléments dans le constructeur compte tenu de l’héritage de classe, mais bon, ça viendra).

    Chaque zombie possède un réseau de neurones pour déterminer les Q-Values de chaque état du jeu. En entrée, le réseau prends donc en compte les positions de chaque humain sur la carte, et en sortie, il restitue 9 Q-Values correspondant à la récompense estimée pour chaque action possible. Ces actions sont "NOTHING, UP, DOWN, RIGHT, LEFT, UP_RIGHT, UP_LEFT, DOWN_RIGHT, DOWN_LEFT". Les actions RIGHT et LEFT déterminent en fait l'angle du vecteur position (un peu comme la souris dans un FPS). UP et DOWN donnent la valeur de la translation suivant le vecteur donné.

    L'apprentissage du réseau se fait par Batch (Experience Replay sur 32 états aléatoires [s, a, r, s']), et les Q-Values "réelles" à apprendre pour chaque batch sont obtenues via :
    Q[s,a*] <- r(s') + gama * max(Q[s', a*]) où r = reward (10 + score si on attrape un humain, -0.01 sinon), gama = 0.86 (pour éviter les divergences)

    Quand au Q[s,a*], il s'agit en fait de la Q-Value de chaque action possible dans l'état 's', calculée via le réseau.

    Quant aux actions, elles sont définies par le indexMax(Q[s,a*]) à hauteur de 20% et aléatoires sinon (on favorise l'exploration).


    Bon, je ne détaillerais pas plus, pour le moment, le fonctionnement global, mais dans l'idée générale, ce fonctionnement parait-il correct ? J'ai déjà implémenté la chose mais il me reste une petite erreur aléatoire à corriger avant de pouvoir dire si oui ou non cela fonctionne. A première vue, sur 1 minute de jeu, absolument aucun progrès n’apparaît ; de plus, les déplacements aléatoires font que, étant donné la taille de l'environnement (fenêtre) l'agent a tendance à se déplacer très lentement. Selon vous, parait-il viable de procéder ainsi ou vaut-il mieux trouver une approche fondamentalement différente ?

    Quoi qu'il en soit, en tout premier lieu, je dois corriger cette erreur de segmentation aléatoire qui fait très certainement partie de mon Experience Replay...


    Merci d'avance !

  7. #7
    Membre habitué
    Bonjour,

    Je n'ai malheureusement pas réussi à avancer correctement sur mon projet ; je me retrouve toujours avec un agent dont les mouvements sont erratiques même après 10 minutes d'apprentissage à 200 fps.... Le problème étant que je ne sais pas, du coup, si mon code fonctionne ou pas... Une idée pour pouvoir vérifier ça ?

    Pour info, je viens de trouver cette vidéo qui illustre plutôt bien le résultat que je souhaite atteindre :



    Si quelqu'un a des conseils à me fournir ou a déjà réalisé ce genre de projet (Deep Q-Learning).... Je suis preneur de toute information !


    Merci.

  8. #8
    Membre habitué
    Bonjour BioKore,

    Dans cet exemple, l'agent a une vision limité de son univers. De ce que j'ai compris en te lisant tu es resté sur une vision de toutes les positions des éléments du jeu.
    Pour le Deep QLearning je n'ai pas d'info so sorry.

    Cordialement,

  9. #9
    Membre habitué
    Bonjour et merci pour ce retour.

    Donc selon toi, le mode de perception de l'environnement joue u rôle direct sur la qualité de l'apprentissage ? Je vais voir si je peux implémenter des capteurs similaires à ceux de la vidéo... Mais j'ai bien peur de la complexité du code nécessaire pour...

    Je vais tester. Merci !

  10. #10
    Membre habitué
    Donc selon toi, le mode de perception de l'environnement joue un rôle direct sur la qualité de l'apprentissage ?
    Oui, complètement. J'ai beau tourner dans tous les sens, je ne vois pas comment un agent pourrais obtenir un comportement cohérent en connaissant les positions de tous les éléments. Éventuellement tu arriverais à quelque chose en donnant les positions relatives par rapport à l'agent mais ça resterais très compliqué.

    Je vais voir si je peux implémenter des capteurs similaires à ceux de la vidéo... Mais j'ai bien peur de la complexité du code nécessaire pour...
    Ça me semble assez simple au contraire. Je ferais ça en deux étapes :

    - Déterminer les cercles qui se trouvent dans le rayon de perception de l'agent. Calculer la distance entre deux points c'est très simple et niveau programmation c'est faire une boucle sur tous les éléments.
    - Déterminer l'intersection d'une droite avec un cercle. Là aussi c'est une boucle mais seulement sur les éléments dans le rayon de perception et niveau math ça devrait le faire (mais au cas où : Intersection droite cercle).

    Tu vois d'autres problèmes que je n'ai pas mentionné ?

  11. #11
    Membre habitué
    Merci pour ce retour !

    Dans mon cas, l'agent voit les positions de tous les éléments, mais aussi la sienne.... Mais c'est vrai que, finalement, il ne sait pas forcément que c'est la sienne (même si j'estime qu'il devrais être capable de s'en rendre compte).
    Mais, dans tous les cas, je serais d'accord avec toi : le système de "moustaches" me parait bien plus robuste, facile à exploiter et à instancier (dans le sens conceptuel, pas de la programmation).

    Je m’oriente donc définitivement vers cette option.

    Le calcul de la distance, je sais faire, c'est bon, mais pour les intersections, c'est autre chose. L'aspect mathématique de la chose ne me dérange pas (au contraire), mais au niveau de l'implémentation, c'est là où je me pose plus de questions (par ou commencer ?). Mais bon, je vais me lancer, et je trouverais bien une solution, avec l'aide du forum !
    A ce sujet, j'ai ouvert un post, qui apportera les réponses à mes questions je l'espère.

    en ce qui concerne les autres problèmes que tu n'as pas mentionné, ils viendrons certainement par la suite quand j'aurais commencé à essayer d'implémenter la chose. Ces derniers viendront alimenter ce fil au fur-et-à-mesure.

    D'ailleurs, j'ai déjà une question un peu anticipée (qui fait redondance avec l'autre post mais tant-pis), c'est comment savoir quel et le type de classe que le capteur touche ? Par exemple, est-ce que l'objet touché est de type "wall" ou de type "food", "human" etc ? Telle que je me l'imagine, il faudrait que je fasse une classe globale dont hérite tous les objets possible du "jeu" pour pouvoir la prendre en paramètre dans une fonction unique (genre typeObjetDetecte(const classe_Globale &src)) non ?

  12. #12
    Membre habitué
    Ne sachant pas ce que tu ne sais pas et n'ayant pas fait de c++ depuis quelques années maintenant, le plus simple serait que tu postes les problèmes techniques que tu rencontreras au fur et à mesure que tu les rencontres.

    Sinon, ce type de projet est particulièrement intéressant à coder parce que le résultat est souvent étonnant.
    Je te souhaites de beaucoup t'amuser ^^.

  13. #13
    Membre habitué
    Bonjour à tous,

    Cela fait un petit moment que je n'ai pas fait part de mes avancées... La raison à ceci est que j'ai passé du temps (beaucoup trop !) juste pour implémenter une classe gérant l'algèbre tensoriel nécessaire au positionnement des capteurs par rapport à l'agent (en mouvement). Ce code, bien qu'étant fonctionnel à l'heure actuel reste néanmoins mal implémenté et peu pratique à l'utilisation, ce qui vient "polluer" le reste de mon programme... Bref, comme certains sur le forum me l'on déjà conseillé, je pense donc partir sur l’utilisation de la bibliothèque GLM. Étant donné la nature de mon projet et ayant déjà une idée des suivants, je pense devoir travailler sur le même type de support pendant un moment donc autant avoir quelque-chose de propre dès maintenant. Je compte donc me passer de SFML pour voir du côté de freeglut3 + Mesa (OpenGL). --> Fausse bonne idée selon vous ? Je cherche vraiment à fair au plus simple.

    Pour ce qui est du fond du projet, il reste le même : avoir un DQN+ER viable (ce dernier est déjà créé, il n'attend qu'à être testé), et le faire évoluer vers un DDQN+PER. Bref, un beau rêve mais que je compte bien finaliser une fois que le "support" (jeu ?) sur lequel le tester sera transparent pour moi.

    Si, à tout hasard, vous avez d'autres idées qu'un environnement graphique pour pouvoir tester un tel type de réseau, n'hésitez pas à m'en faire part. Si je peux me passer de la charge de travail nécessaire pour gérer ce support, ce serait vraiment super.


    D'avance, merci !

###raw>template_hook.ano_emploi###