Mes petits mangeurs ne mangent pas...

Quand l'intelligence part en cacahouète

a marqué ce sujet comme résolu.

Salut à tous,

Depuis quelque temps je m'intéresse à l'intelligence artificielle, et en particulier au réseau de neurones. Pour m'entrainer, j'ai créé un environnement où des mangeurs (équivalent à des poissons) doivent manger de la nourriture. Le monde est en 2D, il n'est pas infini (taille réglable). Chaque mangeur disposent d'un cerveau : son réseau de neurones. Mon mangeur se déplace dans la direction d'un angle en radians. Comme entrée au réseau de neurone, je met la position x et la position y du fruit le plus proche, ensuite je met le radian actuel de la bête. Ensuite j'ai deux couches cachées composées à chaque fois de 3 neurones. Pour ma sortie, j'ai aussi 3 neurones. Une indiquant si je dois tourner à droite, une autre qui indique si je dois tourner à gauche et enfin la dernière qui m'indique si je peux avancer. Quand je tourne à droite j'enlève $\frac\pi{3}$ à l'angle du mangeur et quand je tourne à droite j'ajoute $\frac\pi{3}$ à l'angle du mangeur.

Pour déterminer les poids, j'utilise un algorithme génétique. A chaque fois qu'un mangeur mange un fruit, son score augment de 1. Ansi je sélectionne que les 50% meilleurs mangeurs. Puis je les fait reproduire, je mélange les poids de la maman et du papa. J'ai une chance sur deux que l'allèle du papa soit pris, du coup une chance sur deux que l'allèle de la maman soit pris. Après s'applique la mutation. Pour accélérer l'algorithme, j'ai respecté le pattern MVC. Ainsi je peux faire 50 générations en 1 minutes.

Le problème est que malgré 50 générations, le meilleur score soit 1. Soit les mangeurs restent où ils sont. Soit elle avance, et ne font que ça…

J'ai testé beaucoup de choses comme la configuration, à la place de mettre la position du fruit la plus proche j'ai mis sa distance. J'ai testé aussi plein de nombre comme pour le nombre d'individu dans la population, la pourcentage de mutation, les poids…

Bref rien ne marche… J'aimerais un peu de vos lumières ;)

+0 -0

Pas mal de trucs :

  • Déjà, je suppose que tu veux plutôt faire $\frac{\pi}{3}$ et non l'inverse (pour 60 degrés).
  • Es-tu certain que les déplacements que tu autorise permettent bien d'atteindre la nourriture ? La nourriture est-elle renouvellée ou bien tt le monde crève de faim au bout de x itérations ?
  • Est ce que tu as bien vérifié que ton modèle de réseau neuronal est censé fonctionner, avant de lui appliquer un algo génétique ? (ie as-tu un exemple d'un tel réseau qui fonctionne?)
  • Quelle tailles de ta population as-tu testé (ordre de grandeur) ? Même question pour ta fonction de sélection, le calcul du fitness, le taux de mutation, etc.
  • Comment sont initialisés les réseaux de neurones ? Peux-tu observer une amélioration significative (même si insuffisante) du fitness, ou bien ça ne marche pas du tout ?
  • Tu « mélange » les poids comment exactement ?
  • Qu'entends-tu par : « Pour accélérer l'algorithme, j'ai respecté le pattern MVC » ??
+0 -0

Tu nous parle des poids mais pas des fonctions de transfert, tu as prit quoi ?

Kje

J'ai testé les fonctions Tangente et Sigmoid.

  • Déjà, je suppose que tu veux plutôt faire $\frac{\pi}{3}$ et non l'inverse (pour 60 degrés).

yoch

Ah oui, c'est bien ça. J'ai corrigé.

  • Es-tu certain que les déplacements que tu autorise permettent bien d'atteindre la nourriture ? La nourriture est-elle renouvelle ou bien tt le monde crève de faim ou bout de x itérations ?

yoch

Quand un mangeur touche une nourriture, elle réapparait aléatoirement. Par contre quand un mangeur sort de la zone prédéfinie son score passe à 0. La limite de déplacement entre chaque génération est environ 1000 déplacement (que ce soit gauche, droite ou avancer). J'ai testé aussi avec 100 ou 500 déplacements.

  • Est ce que tu as bien vérifié que ton modèle de réseau neuronal est censé fonctionner, avant de lui appliquer un algo génétique ? (ie as-tu un exemple d'un tel réseau qui fonctionne?)

yoch

Euh… o_O Je me suis un peu inspiré de ce projet : http://doublezoom.free.fr/programmation/AG_Exemple_Survival.php

  • Quelle tailles de ta population as-tu testé (ordre de grandeur) ? Même question pour ta fonction de sélection, le calcul du fitness, le taux de mutation, etc.

yoch

J'ai testé des populations allant de 50 jusqu'a 1000 individus. Mon taux de mutation est de 0.4%. La fitness est le nombre de fruit mangé.

  • Comment sont initialisés les réseaux de neurones ? Peux-tu observer une amélioration significative (même si insuffisante) du fitness, ou bien ça ne marche pas du tout ?

yoch

J'initialise les poids aléatoirement dans un intervalle de -150 jusqu'à 150 en premier temps puis je suis passé d'intervalle de -10 jusqu'à 10. Les poids sont des nombres à virgules. Je ne vois pas de réelle changement sur 250 générations.

  • Tu « mélange » les poids comment exactement ?

yoch

J'utilise un mélange uniforme.

  • Qu'entends-tu par : « Pour accélérer l'algorithme, j'ai respecté le pattern MVC » ??

yoch

Le pattern MVC sépare la partie graphique de la partie "traitement". Les mangeurs sont gérés indépendamment de la partie graphique ce qui accélère les générations.

Par contre quand un mangeur sort de la zone prédéfinie son score passe à 0.

C'est peut être un peu violent, tu devrais essayer avec un espace torique pour voir ce que ça donne.

Mon taux de mutation est de 0.4%.

Pourquoi cette valeur (j'imagine que c'est 0.4% par gène) ? En as-tu essayé d'autres ? Et quelle est ta fonction de mutation ? (aléatoire, inverse, autre) ?

J'initialise les poids aléatoirement dans un intervalle de -150 jusqu'à 150 en premier temps puis je suis passé d'intervalle de -10 jusqu'à 10. Les poids sont des nombres à virgules.

D'habitude, c'est entre 1 et -1.

Je ne vois pas de réelle changement sur 250 générations.

C'est clairement le plus problématique pour l'instant.

As-tu au moins de la diversité dans le fitness (écart min / max), ou même pas ? Si oui, tu peux essayer de rendre les critères de sélection moins agressifs, sinon il y a un probleme de fond quelque part.

J'utilise un mélange uniforme.

Puisque tu utilise des réels, tu peux éventuellement essayer des croisements plus évolués, comme le croisement barycentrique.

Le pattern MVC sépare la partie graphique de la partie "traitement". Les mangeurs sont gérés indépendamment de la partie graphique ce qui accélère les générations.

Ah. L'affichage importe peu, en fait, tant que ça ne fonctionne pas… Seul les graphes d’évolution du fitness sont intéressants a ce stade, AMHA.

Il n'y a que moi que ça choque que les entrées soient des valeurs absolues? Ou bien j'ai mal compris.

Habituellement, toutes les entrées sont invariantes par translation et rotation du système. Donc au lieux de donner x, y et l'angle (absolu, j'ai l'impression) du mangeur, il faudrait plutôt donner l'angle entre la direction du mangeur et la nourriture la plus proche et la distance entre la nourriture et le mangeur.

Je rejoins aussi yoch sur les valeurs : habituellement, on s'arrange pour que les entrées et les sorties soient entre -1 et 1 (ou plus couramment 0 et 1). Pour l'angle, ça semble assez simple. Pour la distance, tu peux utiliser une fonction type $\frac{1}{x}$ ou $e^{-x}$.

De même, j'ai l'impression que ton pas de temps n'est pas assez petit : tourner de $\frac{\pi}{3}$ à chaque tic, c'est juste énorme. Pour avoir un truc fonctionnel, il faut que l'on puisse raisonnablement assimiler ton système pas à pas à un système continu.

+1 -0

J'essaie de reformuler ton problème dans un langage non-informatique, parce que je pense que c'est là que se situe le problème.

Tu essaies de reproduire la sélection naturelle : les individus les plus costauds se reproduisent, et les plus faibles ne se reproduisent pas. Ici, tu n'as pas vraiment de notion de costaud et de faible. Tes poissons sont tous aussi intelligents et tous aussi habiles. Il n'y a pas de raison que la sélection naturelle donne la moindre amélioration de la population.

Tu pourrais essayer par exemple de créer différentes variétés de poissons au départ. Quand un poisson tourne à droite ou à gauche, la variété n°1 va tourner de 5°, la variété n°2 va tourner de 10%… , la variété n°12 va tourner de 6° … et la variété n°35 va tourner de 175° (donc faire quasiment demi-tour). Et à chaque nouvelle génération, le fils reprend la 'souplesse' du père ou de la mère, aléatoirement.

J'imagine qu'avec ce système, les variétés les moins adaptées vont finir par disparaître, alors que les variété les plus adaptées vont se reproduire.

En tout cas, je suis très curieux de connaître le résultat.

@elegance : Ici, l'"intelligence" se situe au niveau du réseau de neurones propre a chaque poisson. C'est lui qui décide du comportement du poisson face a son environnement, qui va donc être différent pour chaque poisson. En revanche, les poissons sont tous aussi "habiles" (comprendre ont les mêmes facultés physique), puisque le but n'est pas d’améliorer cet aspect la.

Bien sur, on pourrait introduire plus de variété dans la gamme de comportements disponibles, mais mieux vaut rester simple au départ si on veut obtenir quelque chose d’intéressant.

+0 -0

Moi j'ai une autre question, est-ce qu'un MLP a vraiment un intérêt ? Pourquoi avoir 2 couches cachées ? Et pourquoi tes couches ont une dimension de 3 seulement ? Il me semble qu'on aime bien réduire drastiquement le nombre de réseau drastiquement en passant d'une couche à une autre. Tu pourrais essayé de faire : 3 -> 20 -> 10 -> 3.

Edit : Tu pourrais aussi donner plus d'informations à chaque poisson en lui donnant les coordonnées de tout les fruits puisque ce nombre est constant. Ca permettrait d'appliquer plus intelligemment ce que j'ai dit avant :)

Je pense pas que ce soit le plus gros problème mais c'est très certainement beaucoup plus simple à essayé. Soit sûr que le problème vient de la génétique avant de la modifiée. Essaie différentes architectures de réseaux, peut être que ça changera quelque chose, peut être pas. Mais très simple à changer je pense

+0 -0

Par contre quand un mangeur sort de la zone prédéfinie son score passe à 0.

C'est peut être un peu violent, tu devrais essayer avec un espace torique pour voir ce que ça donne.

yoch

Oui je pense. Je peux peut-être rajouté une entrée pour dire qu'on est sortie de la zone.

Mon taux de mutation est de 0.4%.

Pourquoi cette valeur (j'imagine que c'est 0.4% par gène) ? En as-tu essayé d'autres ? Et quelle est ta fonction de mutation ? (aléatoire, inverse, autre) ?

yoch

Je l'ai mise un peu au hasard :euh: . J'ai essayé 0.9%, 10%. Mais rien ne change. Je parcours ma population et il y a tant de chance qu'un allèle soit modifié. Je met une valeur aux hasard.

Je ne vois pas de réelle changement sur 250 générations.

C'est clairement le plus problématique pour l'instant.

yoch

Au début j'ai testé avec cette lib et après j'ai fait mon propre réseau de neurone. Je me suis rendu compte qu'avec la solution faite maison, je consommé moins de mémoire (environ 10 mo pour la solution faite maison et 3 GB avec la lib pour environ 100 générations)

As-tu au moins de la diversité dans le fitness (écart min / max), ou même pas ? Si oui, tu peux essayer de rendre les critères de sélection moins agressifs, sinon il y a un probleme de fond quelque part.

yoch

Pour l'instant ma meilleure fitness est 4.

J'utilise un mélange uniforme.

Puisque tu utilise des réels, tu peux éventuellement essayer des croisements plus évolués, comme le croisement barycentrique.

yoch

C'est une bonne idée je regarderais.

Il n'y a que moi que ça choque que les entrées soient des valeurs absolues? Ou bien j'ai mal compris.

Habituellement, toutes les entrées sont invariantes par translation et rotation du système. Donc au lieux de donner x, y et l'angle (absolu, j'ai l'impression) du mangeur, il faudrait plutôt donner l'angle entre la direction du mangeur et la nourriture la plus proche et la distance entre la nourriture et le mangeur.

Berdes

Oui je pense que tu as raison, cela donne une valeur plus réel. Dans la vrai vie, on n'a pas les coordonnées du fromage dans le frigo mais on peut estimer sa distance.

Je rejoins aussi yoch sur les valeurs : habituellement, on s'arrange pour que les entrées et les sorties soient entre -1 et 1 (ou plus couramment 0 et 1). Pour l'angle, ça semble assez simple. Pour la distance, tu peux utiliser une fonction type $\frac{1}{x}$ ou $e^{-x}$.

De même, j'ai l'impression que ton pas de temps n'est pas assez petit : tourner de $\frac{\pi}{3}$ à chaque tic, c'est juste énorme. Pour avoir un truc fonctionnel, il faut que l'on puisse raisonnablement assimiler ton système pas à pas à un système continu.

Berdes

C'est un peu restrictif $\frac\pi{3}$ je suis passé à $\frac\pi{8}$. J'ai testé les fonctions que tu m'as donné, pareil pas de changement.

+0 -0

Tu pourrais essayer par exemple de créer différentes variétés de poissons au départ. Quand un poisson tourne à droite ou à gauche, la variété n°1 va tourner de 5°, la variété n°2 va tourner de 10%… , la variété n°12 va tourner de 6° … et la variété n°35 va tourner de 175° (donc faire quasiment demi-tour). Et à chaque nouvelle génération, le fils reprend la 'souplesse' du père ou de la mère, aléatoirement.

elegance

Je crois aussi que c'est une des solutions car dans les exemples que j'ai vu il n'y avait jamais une seule espèce ou sinon elle avait plusieurs objectifs.

Je suis en train d'en écrire une (un tuto en fait) qui s'inspire d'un dossier qu ej'ai fait. A la rigueur je peux te le donner ^^

Sinon en cherchant un peu en anglais tu trouves assez facilement de bonnes ressources (cherche "perceptron" par exemple). Il y a le cours d'Andrew Ng sur Coursera qui est vraiment bien :)

En fait, c'est pas comme ça qu'on entraîne un réseau de neurones. J'imagine que ta méthode pourrait marcher, mais elle est loin d'être optimale.

Normalement, tu dois disposer d'un jeu de données afin d'entraîner ton réseau. Dans ton cas, chaque instance de ton jeu de données devra être représenter par la position du mangeur, la position du fruit, le radian, et les sorties associées à ces valeurs.

La première étape de l'apprentissage consiste à affecter les poids de ton réseau au pif. Ensuite, tu donne chaque instance de ton ensemble d'apprentissage à ton réseau de neurones. Celui ci te sortira un mauvais résultat, et tu ajustera les poids en fonction de l'erreur obtenue. L'algorithme le plus simple pour mettre en place ce genre d'apprentissage est le "gradient descent".

Tu pourra trouver une très bonne introduction aux réseaux de neuronnes ici

En fait, c'est pas comme ça qu'on entraîne un réseau de neurones. J'imagine que ta méthode pourrait marcher, mais elle est loin d'être optimale.

Normalement, tu dois disposer d'un jeu de données afin d'entraîner ton réseau. Dans ton cas, chaque instance de ton jeu de données devra être représenter par la position du mangeur, la position du fruit, le radian, et les sorties associées à ces valeurs.

La première étape de l'apprentissage consiste à affecter les poids de ton réseau au pif. Ensuite, tu donne chaque instance de ton ensemble d'apprentissage à ton réseau de neurones. Celui ci te sortira un mauvais résultat, et tu ajustera les poids en fonction de l'erreur obtenue. L'algorithme le plus simple pour mettre en place ce genre d'apprentissage est le "gradient descent".

Tu pourra trouver une très bonne introduction aux réseaux de neuronnes ici

GaaH

Ce qui tu dis est une descente par gradient, je suis pas bien convaincu que ça marche dans mon cas.

Avez vous une bonne introduction aux réseaux de neurones quelque part ?

Il y a ce tuto sur Développez.com

J'ai corrigé pas mal de bug, du coup en ce moment mes scores sont entre 2 et 10. J'utilise une population de 52 individu, un taux de mutation de 0.7. J'utilise une fonction sigmoid avec une architecture de 4 entrées, puis 2 une couche cachée avec 4 neurones et 3 neurones à l'intérieur. Ma fitness augmente petit à petit.

+1 -0

Il faut prévoir toutes les trajectoires, puis c'est un peu complexe à mettre en oeuvre. De plus la nature fait bien les choses :)

Cirdo

Oui et non ^^

Le problème dans ton cas c'est que tu ne connais pas le "bon" résultat, en tout cas c'est pas si évident. Par contre ce que tu pourrais faire c'est faire un entraînement avec peut etre 15/20 valeurs que tu auras calculé pour orienté un peu ton espace et ensuite tu ajoute le random (avec une loi normale centrée sur tes poids) comme ça tu as un réseau de base à peu près orientée vers ce que tu souhaite mais qui ne fonctionne pas du tout.

Ensuite > En fait, c'est pas comme ça qu'on entraîne un réseau de neurones. J'imagine que ta méthode pourrait marcher, mais elle est loin d'être optimale.

Normalement, tu dois disposer d'un jeu de données afin d'entraîner ton réseau. Dans ton cas, chaque instance de ton jeu de données devra être représenter par la position du mangeur, la position du fruit, le radian, et les sorties associées à ces valeurs.

La première étape de l'apprentissage consiste à affecter les poids de ton réseau au pif. Ensuite, tu donne chaque instance de ton ensemble d'apprentissage à ton réseau de neurones. Celui ci te sortira un mauvais résultat, et tu ajustera les poids en fonction de l'erreur obtenue. L'algorithme le plus simple pour mettre en place ce genre d'apprentissage est le "gradient descent".

GaaH

Ca ne fonctionne pas pour tout. Clairement ce genre de problème est plus naturel à implémenter avec des algorithmes génétiques. Il y a des problèmes où il n'existe pas de jeu de donnée ou alors c'est difficile d'en créer un intéressant, clairement ici c'est le cas.

En fait, c'est pas comme ça qu'on entraîne un réseau de neurones. J'imagine que ta méthode pourrait marcher, mais elle est loin d'être optimale.

Normalement, tu dois disposer d'un jeu de données afin d'entraîner ton réseau.

GaaH

C'est la façon la plus connue de faire, mais les algorithmes génétiques sont également utilisés pour entraîner des réseaux de neurones, en particulier lorsque l'on ne dispose pas de données d'entrainement exploitables. Bref, tu devrais te renseigner un peu.

Connectez-vous pour pouvoir poster un message.
Connexion

Pas encore membre ?

Créez un compte en une minute pour profiter pleinement de toutes les fonctionnalités de Zeste de Savoir. Ici, tout est gratuit et sans publicité.
Créer un compte