2016-12-09 1 views
2

J'ai créé un réseau de neurones simple avec 3 couches selon cet exemple de python: Link (PS: Vous devez faire défiler vers le bas jusqu'à la partie 2)rétropropagation ne fonctionne pas: Neural Network Java

Ceci est mon implémentation Java du code:

private void trainNet() 
{ 
    // INPUT is a 4*3 matrix 
    // SYNAPSES is a 3*4 matrix 
    // SYNAPSES2 is a 4*1 matrix 
    // 4*3 matrix DOT 3*4 matrix => 4*4 matrix: unrefined test results 
    double[][] layer1 = sigmoid(dot(inputs, synapses), false); 

    // 4*4 matrix DOT 4*1 matrix => 4*1 matrix: 4 final test results 
    double[][] layer2 = sigmoid(dot(layer1, synapses2), false); 

    // 4*1 matrix - 4*1 matrix => 4*1 matrix: error of 4 test results 
    double[][] layer2Error = subtract(outputs, layer2); 

    // 4*1 matrix DOT 4*1 matrix => 4*1 matrix: percentage of change of 4 test results 
    double[][] layer2Delta = dot(layer2Error, sigmoid(layer2, true)); 

    // 4*1 matrix DOT 3*1 matrix => 4*1 matrix 
    double[][] layer1Error = dot(layer2Delta, synapses2); 

    // 4*1 matrix DOT 4*4 matrix => 4*4 matrix: percentage of change of 4 test results 
    double[][] layer1Delta = dot(layer1Error, sigmoid(layer1, true)); 

    double[][] transposedInputs = transpose(inputs); 
    double[][] transposedLayer1 = transpose(layer1); 

    // 4*4 matrix DOT 4*1 matrix => 4*1 matrix: the updated weights 
    // Update the weights 
    synapses2 = sum(synapses2, dot(transposedLayer1, layer2Delta)); 

    // 3*4 matrix DOT 4*4 matrix => 3*4 matrix: the updated weights 
    // Update the weights 
    synapses = sum(synapses, dot(transposedInputs, layer1Delta)); 

    // Test each value of two 4*1 matrices with each other 
    testValue(layer2, outputs); 
} 

le point, somme, soustrayez et transposés fonctions, je me suis créé et je suis sûr qu'ils font parfaitement leur travail.

Le premier lot d'entrées me donne une erreur d'environ 0,4 ce qui est correct, car les poids sont de valeur aléatoire. Lors de la deuxième exécution, la marge d'erreur est plus petite, mais seulement de très peu (0,001)

Après 500 000 lots (soit 2 000 000 de tests au total), le réseau n'a toujours pas donné de valeur correcte! J'ai donc essayé d'utiliser une plus grande quantité de lots. En utilisant 1 000 000 de lots (soit 4 000 000 de tests au total), le réseau génère 16 900 résultats corrects.

Quelqu'un pourrait-il me dire ce qu'il se passe?

Ce sont les poids utilisés:

Première couche:

  • 2,038829298171684 2,816232761170282 1,6740269469812146 1,634422766238497
  • 1,5890997594993828 1,7909325329112222 2,101840236824494 1,063579126586681
  • 3,761238407071311 3,757148454039234 3,7557450538398176 3,6715972104291605

Deuxième couche:

  • -0,019603811941904248
  • 218,38253323323553
  • 53,70133275445734
  • -272,83589796861514

    EDIT: Merci à lsnare pour me montrant en utilisant une bibliothèque serait plus facile!

Pour les personnes intéressées ici est le code de travail en utilisant la bibliothèque de math.nist.gov/javanumerics:

private void trainNet() 
{ 
    // INPUT is a 4*3 matrix 
    // SYNAPSES is a 3*4 matrix 
    // SYNAPSES2 is a 4*1 matrix 
    // 4*3 matrix DOT 3*4 matrix => 4*4 matrix: unrefined test results 
    Matrix hiddenLayer = sigmoid(inputs.times(synapses), false); 

    // 4*4 matrix DOT 4*1 matrix => 4*1 matrix: 4 final test results 
    Matrix outputLayer = sigmoid(hiddenLayer.times(synapses2), false); 

    // 4*1 matrix - 4*1 matrix => 4*1 matrix: error of 4 test results 
    Matrix outputLayerError = outputs.minus(outputLayer); 

    // 4*1 matrix DOT 4*1 matrix => 4*1 matrix: percentage of change of 4 test results 
    Matrix outputLayerDelta = outputLayerError.arrayTimes(sigmoid(outputLayer, true)); 

    // 4*1 matrix DOT 1*4 matrix => 4*4 matrix 
    Matrix hiddenLayerError = outputLayerDelta.times(synapses2.transpose()); 

    // 4*4 matrix DOT 4*4 matrix => 4*4 matrix: percentage of change of 4 test results 
    Matrix hiddenLayerDelta = hiddenLayerError.arrayTimes(sigmoid(hiddenLayer, true)); 

    // 4*4 matrix DOT 4*1 matrix => 4*1 matrix: the updated weights 
    // Update the weights 
    synapses2 = synapses2.plus(hiddenLayer.transpose().times(outputLayerDelta)); 

    // 3*4 matrix DOT 4*4 matrix => 3*4 matrix: the updated weights 
    // Update the weights 
    synapses = synapses.plus(inputs.transpose().times(hiddenLayerDelta)); 

    // Test each value of two 4*1 matrices with each other 
    testValue(outputLayer.getArrayCopy(), outputs.getArrayCopy()); 
} 
+0

Pouvez-vous ajouter vos fonctions dot, sum, subtract, transpose et sigmoid à des fins de clarification? – CraigR8806

Répondre

0

En général, lorsque le code écrit qui implique le calcul mathématique ou numérique avancé (comme l'algèbre linéaire Il est préférable d'utiliser les bibliothèques existantes écrites par des experts dans le domaine, plutôt que d'écrire vos propres fonctions. Les bibliothèques standard produiront des résultats plus précis et seront probablement plus efficaces. Par exemple, dans le blog que vous référencez, l'auteur utilise la bibliothèque numpy pour calculer les produits scalaires et la transposition des matrices.Pour Java, vous pouvez utiliser le package Java Matrix (JAMA) qui a été développé par le NIST: transposer une matrice http://math.nist.gov/javanumerics/jama/
Par exemple,:

double[4][3] in = {{0,0,1},{0,1,1},{1,0,1},{1,1,1}}; 
Matrix input = new Matrix(in); 
input = input.transpose(); 

Je ne suis pas sûr que cela résoudra votre problème complètement, mais j'espère que cela pourrait vous éviter d'écrire du code supplémentaire à l'avenir.

+1

Je ne peux pas vous remercier assez pour m'avoir signalé cela! Le problème était que mes méthodes fonctionnaient, mais elles ne vérifiaient pas assez l'erreur pour qu'une matrice m * n puisse être multipliée par une matrice p * q (p ≠ n). – Caske2000

+0

Content de vous aider! J'ai rencontré des problèmes similaires en essayant de mettre en œuvre des opérations matricielles moi-même :) – lsnare