Aller au contenu


Photo
- - - - -

Réseau de neuronnes


5 réponses à ce sujet

#1 Liquidhuk

Liquidhuk

    Membre

  • Membres
  • 15 messages

Posté 02 août 2013 - 03:59

Bonjour

Après plusieurs semaines à suivre des cours et lire des thèses sur les réseaux de neurones, je me suis lancé dedans. J'aimerais dans un premier temps l'appliquer au jeu pong, histoire de me faire la main. J'ai codé en C++ un réseau de neurones de taille flexible et j'ai prévu plusieurs neurones différents pour faire des tests avec différentes fonctions de transfert. J'ai prévu de procéder par apprentissage supervisé (feed forward + back propagation, learning rate et momentum).

Après quelques tests (XOR, tests de valeurs), j'en ai conclu que le réseau fonctionnait correctement. Dans mon pong, le réseau est caractérisé de la manière suivante :
- Les deux paddle sont contrôlés par des réseaux de neurones
- 4 données sont attendues en entrée : position et direction de la balle
- Un résultat est attendu : position en Y du paddle
- Le réseau est constitué de trois couches de 4 / 10 / 1 neurones

Quand la balle touche un paddle :
- J'envoie en entrée du réseau du paddle opposé la position et la direction de la balle (après rebond)
- J'effectue le feedforward
- Je simule l'endroit où la balle doit atteindre le côté qui effectue le calcul
- J'effectue la backpropagation à l'aide de la simulation
- Je déplace le paddle à l'endroit indiqué par le réseau de neurone

Au final, le réseau converge très rapidement vers 1 et ne bouge plus ensuite. J'ai fait les tests avec des fonctions de transfert en tanh et sigmoïde et en modifiants les constantes de momentum et learning rate, sans résultat probant.

Quels tests pourrais-je faire pour comprendre ce qu'il se passe ? Quelle structure devrais-je utiliser (couches/neurones/fonction) ?

#2 R1D1

R1D1

    Modérateur et Membre passionné

  • Modérateur
  • PipPipPipPipPip
  • 1 211 messages
  • Gender:Male
  • Location:Autriche

Posté 02 août 2013 - 07:58

Salut,

Déjà, première question :
- pourquoi utiliser cette application pour tester ton réseau (pure curiosité de ma part) ?
Ma question venant du fait qu'il est bien plus "simple" d'entrainer un réseau de neurones (par exemple) avec une règle d'apprentissage par renforcement qu'une règle supervisée.

Ensuite :
- Qu'est-ce qui converge vers 1 ? La sortie ? Les poids ? On parle en général de convergence des poids (qui sont signe de l'apprentissage du réseau).
- Est-ce que tu as simplement testé ton cas (le pong) avec un simple réseau sans couche cachée ? Je doute que le problème soit vraiment non linéaire, dans la mesure où il s'agit d'apprendre des associations "pattern d'entrée/sortie".
R1D1 - Calculo Sed Ergo Sum -- en ce moment, M.A.R.C.E.L.
Avatar tiré du site bottlebot

#3 Liquidhuk

Liquidhuk

    Membre

  • Membres
  • 15 messages

Posté 03 août 2013 - 07:27

pourquoi utiliser cette application pour tester ton réseau (pure curiosité de ma part) ?

Tout simplement parce que mon coeur balance entre programmation de jeux vidéos et robotique. J'essaie d'appliquer ce que j'apprends aux deux, historie de trouver mon bonheur partout ! Le pong est certainement le jeu le plus simple à coder, donc voilà :)/> !

J'ai déjà joué avec ce code en changeant la structure du réseau pour le tester, mais je voulais aller un peu plus loin avant de l'utiliser avec des capteurs/actionneurs.

Qu'est-ce qui converge vers 1 ? La sortie ? Les poids ? On parle en général de convergence des poids (qui sont signe de l'apprentissage du réseau).

La sortie converge vers 1 au lieu de changer de valeur à chaque rebond.

Est-ce que tu as simplement testé ton cas (le pong) avec un simple réseau sans couche cachée ? Je doute que le problème soit vraiment non linéaire, dans la mesure où il s'agit d'apprendre des associations "pattern d'entrée/sortie".

Dans tous ce que j'ai pu lire ou regarder, je n'ai jamais trouvé d'indications ou de règles plus précises que "trouver par tâtonnement" la bonne structure à utiliser pour un réseau de neurones. Je n'ai pas essayé sans couche cachée, je vais le faire :)/>

#4 Liquidhuk

Liquidhuk

    Membre

  • Membres
  • 15 messages

Posté 03 août 2013 - 10:05

J'ai essayé sans couche cachée, toujours pas de résultat.

Par contre, l'erreur moyenne en sortie est extrêmement grande (x10^61), je ne comprends pas bien pourquoi. En réduisant le smoothingFactor dans le code ci-dessous, l'erreur tend plus vite vers une valeur convenable (entre 150 et 900) mais le résultat en sortie du réseau ne bouge toujours pas...

// On calcule la somme des erreurs en sortie

    Layer &outputLayer = m_layers.back();
    m_error = 0.0;

    for (unsigned n = 0; n < outputLayer.size() - 1; ++n)
	{
        double delta = targetVals[n] - outputLayer[n]->getOutputVal();
        m_error += delta * delta;
    }
    m_error /= outputLayer.size() - 1; // On fait la moyenne des erreurs en sortie
    m_error = sqrt(m_error); // On prend la racine carée

    // On calcule la moyenne des RMS

    m_recentAverageError =
            (m_recentAverageError * m_recentAverageSmoothingFactor + m_error)
            / (m_recentAverageSmoothingFactor + 1.0);

Pourtant si l'erreur est réduite, c'est que le résultat se rapproche de l'objectif...

#5 alexso

alexso

    Membre

  • Membres
  • 33 messages

Posté 31 août 2013 - 02:47

salut, je me permet juste un ou deux petits commentaires:

ton nombre de neurone en hidden layer est monstrueux au regard d'un problème linéaire
qui plus est sur ce type de problématique ton réseau ne devrait commettre aucune si ce n'est une erreur systématique(peut un pourcentage d'une de tes entrées, une variable mal manipulée ...)

bon courage

Alex

#6 R1D1

R1D1

    Modérateur et Membre passionné

  • Modérateur
  • PipPipPipPipPip
  • 1 211 messages
  • Gender:Male
  • Location:Autriche

Posté 11 septembre 2013 - 12:08

Bon, je t'avoue que le délai dans ma réponse vient du fait que j'ai du mal à voir comment tu veux faire les choses. Ca ne me semble pas très intuitif.

Reprenons un peu le problème. Tu veux, à partir de la position et l'orientation de la balle, déterminer la position de ton palet pour l'intercepter.
Commençons par raisonner dans un espace discret et binaire. Tu peux encoder l'information de position sur un certain nombre de neurones (par exemple 3x2 : gauche milieu droite sur X, arrière centre avant pour Y). Seul deux neurones sont activés, et on néglige les positions trop proches (si tu décales la balle de 1 cm dans un sens ou l'autre, ça change peu l'endroit où tu dois placer ton palet étant donné la taille de celui-ci). De la même manière, tu peux encoder l'orientation en discrétisant les valeurs d'angles en "vers la gauche, tout droit, vers la droite", et en plaçant un 1 sur le neurone qui correspond globalement à la bonne direction. Tout cela mis ensemble nous fait déjà une entrée de 9 neurones avec 3 "uns" qui se baladent.
De la même manière, tu peux encoder la position en X de ton palet (Y étant la profondeur de la table dans mon cas) en un certain nombre de neurones. Pourquoi pas 5. Ca n'a d'importance que pour la précision que tu peux obtenir.

Nous avons donc un réseau avec une entrée X de taille 9 / une sortie Y de taille 5. Entre ces 9/5 neurones, les 45 poids (W) qui connectent les 9 entrées aux 5 sorties. Là encore, pour rester simple, prenons une règle de mise-à-jour supervisée simple :
W(i, j) <= W(i, j) + delta(i, j)
delta(i, j) = alpha * x(j) * ( d(i) - y(i) )

alpha : facteur d'apprentissage (0.1 par exemple)

Un prototype à apprendre pourrait être : si la balle est à l'arrière gauche et dirigée vers la droite, mettre le paddle tout à droite. Ce qui correspond à Xd = (1 0 0 ; 1 0 0 ; 0 0 1) et Yd = (0 0 0 0 1). Lors du calcul de ton réseau à l'entrée Xd, il va te sortir un certain Y, par exemple (0 1 0 0 0) (résultat de l'initialisation aléatoire par exemple).
Tu vas donc calculer la mise à jour pour chacun de tes poids. Tout les poids pour lesquels x(j) = 0 ne seront pas mis à jour, il reste donc les W(*, 0), les W(*, 3) et les W(*, 8). Pour tout ces poids là, on calcule l'erreur. Elle est nulle sauf pour W(1, [0, 3, 8]) et W(4, [0, 3,8]), soit les 6 poids qui correspondent aux neurones de la sortie différents de ceux voulus (Yd). Les premiers vont être mis à jour de -alpha, les seconds de +alpha. Selon l'entrée et l'erreur, chaque poids va être mis à jour en fonction de la valeur vers laquelle il doit tendre.
J'imagine que tu as déjà compris ce mécanisme avec les exemples plus simples que tu as traité, mais c'est en tout cas une solution simple qui devrait fonctionner pour ton problème. En donnant à ton réseau une certaine quantité d'exemples d'apprentissage, il devrait être capable de jouer correctement en fonction du savoir de celui qui a fait la base d'apprentissage.
Pour faire tourner cet algo en conditions "réelles", tu peux recoder un petit simulateur qui calcule le rebond sur le paddle et la nouvelle entrée pour le réseau adverse ... ah, ça c'est déjà fait. :)

Dis-moi si ma réponse t'apporte quelque chose ou pas, histoire qu'on trouve ce qui te bloque.
R1D1 - Calculo Sed Ergo Sum -- en ce moment, M.A.R.C.E.L.
Avatar tiré du site bottlebot



Répondre à ce sujet



  


0 utilisateur(s) li(sen)t ce sujet

0 members, 0 guests, 0 anonymous users