Bonjour, je suis nouveau sur le Forum mais je pense être a la bonne porte pour ma problématique et d'autres futures.
Mon problème est le suivant :
J'ai réalise un petit réseau de neurones, 4 neurones en entrées, 4 neurones caches, 2 neurones pour les sorties.
C'est programmé en C#.
Je ne sais pas du tout d'ou vient mon problème c'est pourquoi je suis ici, donc quand j’effectue l'apprentissage par rétro propagation, les neurones de la couche cachée prennent tous la même valeur. Est-ce normal?
J'ai l'impression que mes poids ne prennent pas les bonnes valeurs.
Et en fin de compte quand j’entraîne une entrée, puis une autre, cela balance mais ne trouve jamais d'équilibre, si une entrée me trouve le bon résultat après apprentissage, toutes les autres ne le feront plus.
Je débute en réseau de neurones, soyez indulgent, je ne sais pas du tout comment m'y prendre pour l'apprentissage, dois-je itéré un grand nombre de fois pour la même entrée ou modifier l’entrée a chaque itération? même mes livres ne sont pas clair a ce sujet, ou peut être ai-je un problème au niveau du code?
Ma procédure d'apprentissage : je donne une entrée, je propage les données dans le réseau et calculs des gradients avec l'erreur et mise a jour des poids ect...
Merci de m'avoir lu.
Voici le code :
[Serializable]
public class NeuralNetwork
{
//Couches de neurones
float[] input;
public float[] Input
{
get{ return input;}
}
[SerializeField]float[] hidden;
[SerializeField]float[] output;
public float[] Output
{
get{ return output;}
}
float[,] wh;
public float[,] Wh
{
get{ return wh;}
}
float[,] wo;
public float[,] Wo
{
get{ return wo;}
}
float alpha = 0.5f;
[SerializeField]float[] target = new float[] {0,1};
public float[] Target
{
get{return target;}
}
int iter = 0;
public int Iter
{
get{ return iter;}
}
public NeuralNetwork()
{
Reset ();
Debug.Log ("NeuralManager Network Created");
}
public void Reset()
{
input = new float[] {0, 0, 0, 0};
hidden = new float[] {0, 0, 0, 0};
output = new float[] {0, 0};
//Initialisation des poids a 0.5
wh = new float[4,4];
for (int i = 0; i < 4; i++)
{
for (int j = 0; j < 4; j++) {
wh [i, j] = 0.5f;
}
}
wo = new float[2,4];
for (int i = 0; i < 2; i++)
{
for (int j = 0; j < 4; j++) {
wo [i, j] = 0.5f;
}
}
}
float Sigmoide(float _x)
{
return 1f / (1f + Mathf.Pow ((float)System.Math.E, (-1f * _x)));
}
public void Propagate()
{
//Propage de l'entree vers l'intermediaire
float[] xh = new float[] {0,0,0,0};
for (int h = 0; h < hidden.Length; h++) {
for (int i = 0; i < input.Length; i++) {
xh [i] += wh [i, h] * input [h];
}
}
//Application de la fonction d'activation, ici sigmoide
for (int h = 0; h < hidden.Length; h++) {
hidden [h] = Sigmoide(xh [h]);
}
//Propage de la couche cachee vers la sortie
float[] xo = new float[] {0,0};
for (int o = 0; o < output.Length; o++) {
for (int h = 0; h < hidden.Length; h++) {
xo [o] += wo [o, h] * hidden [h];
}
}
//Application de la fonction d'activation, ici sigmoide
for (int o = 0; o < output.Length; o++) {
output [o] = Sigmoide(xo [o]);
}
}
public void Learn()
{
//calcul de l'erreur pour chaque sorties
float[] error = new float[2];
for (int o = 0; o < output.Length; o++) {
error [o] = target [o] - output [o];
}
//Creation d'un tableau qui contient les gradient d'erreur pour la couche sortie
float[,] wog = new float[2,4];
for (int o = 0; o < output.Length; o++) {
for (int h = 0; h < hidden.Length; h++) {
wog [o, h] = -error [o] * output [o] * (1 - output [o]) * hidden [h];
}
}
//Calculs des gradients couche cache
float[,] whg = new float[4,4];
for (int i = 0; i < input.Length; i++) {
for (int h = 0; h < hidden.Length; h++) {
float err = 0;
for (int o = 0; o < 2; o++) {
err += wo[o,i] * error [o];
}
whg [i, h] = -err * hidden [i] * (1 - hidden [i]) * input [h];
}
}
//Mise a jour des poids sortie
for (int o = 0; o < output.Length; o++) {
for (int h = 0; h < hidden.Length; h++) {
wo [o, h] -= alpha * wog [o, h];
}
}
//Mise a jour des poids caches
for (int h = 0; h < hidden.Length; h++) {
for (int i = 0; i < input.Length; i++) {
wh [h, i] -= alpha * whg [h, i];
}
}
}
public void LearningProcess(int _amount)
{
for (int i = 0; i < _amount; i++) {
Propagate ();
Learn ();
}
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 4; j++) {
Debug.Log(wo [i, j]);
Debug.Log(wh [i, j]);
}
}
}
public IEnumerator LearningAutomate()
{
bool notEnding = true;
while (notEnding) {
NeuralManager.Instance.ResetUI ();
iter++;
notEnding = false;
for (int j = 0; j < 16; j++) {
//yield return new WaitForSeconds(0.5f);
switch (j)
{
case 0:
input = new float[] {0,0,0,0};
target = new float[] {0,0};
break;
case 1:
input = new float[] {1,0,0,0};
target = new float[] {1,0};
break;
case 2:
input = new float[] {0,1,0,0};
target = new float[] {1,0};
break;
case 3:
input = new float[] {0,0,1,0};
target = new float[] {1,0};
break;
case 4:
input = new float[] {0,0,0,1};
target = new float[] {1,0};
break;
case 5:
input = new float[] {1,1,0,0};
target = new float[] {0,1};
break;
case 6:
input = new float[] {0,1,1,0};
target = new float[] {0,1};
break;
case 7:
input = new float[] {0,0,1,1};
target = new float[] {0,1};
break;
case 8:
input = new float[] {1,0,1,0};
target = new float[] {0,1};
break;
case 9:
input = new float[] {0,1,0,1};
target = new float[] {0,1};
break;
case 10:
input = new float[] {1,0,0,1};
target = new float[] {0,1};
break;
case 11:
input = new float[] {0,1,1,1};
target = new float[] {1,1};
break;
case 12:
input = new float[] {1,1,1,0};
target = new float[] {1,1};
break;
case 13:
input = new float[] {1,0,1,1};
target = new float[] {1,1};
break;
case 14:
input = new float[] {1,1,0,1};
target = new float[] {1,1};
break;
case 15:
input = new float[] {1,1,1,1};
target = new float[] {0,0};
break;
}
Propagate ();
Learn ();
for (int i = 0; i < output.Length; i++) {
if (Mathf.Abs(target [i] - output [i]) > 0.2f)
notEnding = true;
}
}
yield return new WaitForEndOfFrame();
}
}
public void Set(float[] _inputs, float[] _target)
{
input = _inputs;
target = _target;
Debug.Log(target[0] + " " + target[1]);
}
}
-----