Vraag Backpropagation-training zit vast


Ik probeer een neuraal netwerk in Javascript te implementeren en de specificaties van mijn project geven er de voorkeur aan dat de implementatie afzonderlijke objecten heeft voor elk knooppunt en elke laag. Ik ben vrij nieuw in het programmeren van neurale netwerken, en ik ben een paar haken en ogen aan het treffen tijdens de back-propagatietraining van het netwerk. Ik kan geen verklaring vinden waarom het algoritme voor achterwaartse propagatie het netwerk niet goed traint voor elk trainingsvak.

Ik heb zelf een aantal tutorials op een aantal sites gevolgd en zorg ervoor dat ik deze zo nauw mogelijk volg: http://galaxy.agh.edu.pl/~vlsi/AI/backp_t_en/backprop.html backpropagation

Hier is een link naar de originele code: http://jsfiddle.net/Wkrgu/5/

Dit is wat ik probeer te doen, en voor zover ik kan vertellen, is hier wat ik kan interpreteren gebeurt: Na het berekenen van de afgeleide waarden en de fout voor elk knooppunt / neuron, implementeer ik deze functie:

// Once all gradients are calculated, work forward and calculate
// the new weights. w = w + (lr * df/de * in)
for(i = 0; i < this._layers.length; i++) {

    // For each neuron in each layer, ...
    for(j = 0; j < this._layers[i]._neurons.length; j++) {
    neuron = this._layers[i]._neurons[j];
    // Modify the bias.
    neuron.bias += this.options.learningRate * neuron.gradient;

    // For each weight, ...
    for(k = 0; k < neuron.weights.length; k++) {

        // Modify the weight by multiplying the weight by the
        // learning rate and the input of the neuron preceding.
        // If no preceding layer, then use the input layer.
        neuron.deltas[k] = this.options.learningRate * neuron.gradient * (this._layers[i-1] ? this._layers[i-1]._neurons[k].input : input[k]);
        neuron.weights[k] += neuron.deltas[k];
        neuron.weights[k] += neuron.momentum * neuron.previousDeltas[k];

        }
        // Set previous delta values.
    neuron.previousDeltas = neuron.deltas.slice();
    }
}

De eigenschap gradient is gedefinieerd als:

error = 0.0;

// So for every neuron in the following layer, get the 
// weight corresponding to this neuron.
for(k = 0; k < this._layers[i+1]._neurons.length; k++) {

    // And multiply it by that neuron's gradient
    // and add it to the error calculation.
    error += this._layers[i+1]._neurons[k].weights[j] * this._layers[i+1]._neurons[k].gradient;
}

// Once you have the error calculation, multiply it by
// the derivative of the activation function to get
// the gradient of this neuron.
neuron.gradient = output * (1 - output) * error;

Mijn gok is dat ik gewichten te snel bijwerk of dat ik ze bijwerk door ze volledig met de verkeerde waarden te vermenigvuldigen. In vergelijking met de formules die ik over het onderwerp kan vinden, heb ik het gevoel dat ik ze behoorlijk goed volg, maar ik doe duidelijk iets heel verkeerd.

Wanneer ik deze trainingsgegevens gebruik, krijg ik de volgende resultaten:

a.train([0,0], [0]);
a.train([0,1], [1]);
a.train([1,0], [1]);

console.log(a.input([0,0])); // [ 0.9960981505402279 ]
console.log(a.input([1,0])); // [ 0.9957925569461975 ]
console.log(a.input([0,1])); // [ 0.9964499429402672 ]
console.log(a.input([1,1])); // [ 0.996278252201647 ]

BIJWERKEN: Hier is een link naar de vaste code: http://jsfiddle.net/adamthorpeg/aUF4c/3/ Opmerking: traint niet totdat de fout aanvaardbaar is voor elke invoer, dus soms krijgt u nog steeds onnauwkeurige resultaten zodra deze een aanvaardbare fout voor één ideale waarde bereikt. Om het volledig te trainen, moet de training worden voortgezet totdat alle fouten aanvaardbaar zijn. 


10
2018-02-26 22:30


oorsprong


antwoorden:


Ik vond het antwoord op mijn probleem. Het antwoord is tweeledig:

Ten eerste leed het netwerk aan het probleem van "catastrofaal vergeten". Ik was het aan het trainen op één ideaal waarde / input paar per keer in plaats van door elk paar te fietsen en het één baan per keer te trainen.

Ten tweede, in de rij:

neuron.deltas[k] = this.options.learningRate * neuron.gradient * (this._layers[i-1] ? this._layers[i-1]._neurons[k].input : input[k]);

Ik vermenigvuldigde de leersnelheid en de gradiënt (afgeleide berekening) met de inputwaarde van het vorige neuron, in plaats van de outputwaarde van het vorige neuron, wat de input zou zijn voor de gewichtsberekening. Vandaar dat de juiste code voor die regel had moeten zijn:

neuron.deltas[k] = this.options.learningRate * neuron.gradient * (this._layers[i-1] ? this._layers[i-1]._neurons[k].output : input[k]);

Deze bron was van onschatbare waarde: http://blog.zabarauskas.com/backpropagation-tutorial/


4
2018-03-03 16:56