package org.neuroph.nnet.learning;

import org.neuroph.core.Connection;
import org.neuroph.core.Layer;
import org.neuroph.core.Neuron;
import org.neuroph.core.Weight;

/**
 *
 * @author Mladen
 */
public class QuickPropagation extends BackPropagation {

    // ove dve konstante sam preuzeo iz radova koje si mi poslao - ne konstante vec d amogu da se setuju po potrebi
    private double maximumGrowthFactor = 1.75;
  //  private final static double shrinkFactor = maximumGrowthFactor / (1.0 + maximumGrowthFactor);
    // hes mapu koristim da cuvam vrednosti prethodnih iteracija - koristi training data

    @Override
    public void calculateWeightChanges(Neuron neuron) {
        double delta = neuron.getDelta();
        for (Connection con : neuron.getInputConnections()) {
            
            Weight w = con.getWeight();
            QuickPropData qpData = w.getTrainingData();

            double input = con.getInput();
            if (input == 0) continue;            
            
            double gradient = delta * input;            
            double previousWeightChange = qpData.previousWeightChange;  //  this is positive gradiend dE/dw  (ili ipak -dE/dw)
            
            // neuronError je delta  a ne gradijent
            //double previousError = qpData.previousError;                // delta    dE/dy * y'  - ovo bi morao da bude gradijent - ne sadrzi input
            double prevGradient = qpData.prevGradient;
            
            double currentWeightChange = 0;
            
            
                
            //1. tekuci gradijent i prethdoni gradijent  su istog znaka, i tekuci gradijent je manji od prethodnog gradijenta
            //∆w(t) = (S(t)/(S(t-1)-S(t))) * ∆w(t−1)
            //
            //
            //2. tekuci gradijent i prethdoni gradijent nisu istog znaka,  (i tekuci gradijent je manji od prethodnog gradijent - da li vazi i ovaj uslov, mislim d amora inace menja znak, ali izgleda da nema veze)
            //∆w(t) = (S(t)/(S(t-1)-S(t))) * ∆w(t−1)
            //
            //
            //3. tekuci gradijent i prethdoni gradijent su istog znaka, i tekuci delta je jednak ili veci od prethodnog delta 

            //1. tekuci delta i prethdoni delta su istog znaka, i tekuci delta je manji od prethodnog delta
            if ((prevGradient * gradient > 0) && (gradient < prevGradient)) {    // gradijenti istog znaka i tekuci gradijent je manji od prethodnog (1 slucaj)
                currentWeightChange = (gradient / (prevGradient - gradient)) * previousWeightChange; // quick prop  // ovde bi trebalo dodati epsilon
                // currentWeightChange = learningRate * error * input;
                if (Math.abs(currentWeightChange) >= Math.abs((maximumGrowthFactor * previousWeightChange))) {
                    currentWeightChange = maximumGrowthFactor * previousWeightChange;
                }
            }
             //3. tekuci delta i prethdoni delta su istog znaka, i tekuci delta je jednak ili veci od prethodnog delta 
            else if ((prevGradient * gradient > 0) && (gradient >= prevGradient)) { // gradijenti istog znaka i tekuci gradijent je veci od prethodnog (3 slucaj)
                currentWeightChange = maximumGrowthFactor * previousWeightChange; // ???
              //  currentWeightChange = previousWeightChange; // ???

            } else if (prevGradient * gradient < 0) { // gradijenti razlicitog znaka (2 slucaj)
                currentWeightChange = (gradient / (prevGradient - gradient)) * previousWeightChange; // quick prop 

                // sta kad ej negativno
                if (Math.abs(currentWeightChange) >= Math.abs((maximumGrowthFactor * previousWeightChange))) {
                    currentWeightChange = maximumGrowthFactor * previousWeightChange;
                }
            } else { // gradijent je 0, standardni backprop
                currentWeightChange = -learningRate * delta * input;
            }
            
            w.weightChange += currentWeightChange;
         //   System.out.println("currentWeightChange: " + currentWeightChange);
//            if (currentWeightChange > 10) {
//                System.out.println(getCurrentIteration() + " iteration : "+ currentWeightChange);
//            }
            qpData.previousWeightChange = currentWeightChange;
            qpData.prevGradient = gradient;
         //   qpData.previousError = delta;
            
        }
       
    }

    @Override
    protected void onStart() {
        super.onStart(); //To change body of generated methods, choose Tools | Templates.
        for (Layer layers : neuralNetwork.getLayers()) {
            for (Neuron neuron : layers.getNeurons()) {
                for (Connection connection : neuron.getInputConnections()) {
                    //connection.getWeight().setTrainingData(new QuickPropData());
                    Weight qpWeight = new Weight<>();
                    qpWeight.setTrainingData(new QuickPropData());
                    connection.setWeight(qpWeight);                    
                }
            }
        }

    }
    
    public static class QuickPropData {
        private double previousWeightChange;
        private double previousError; // we dont need this for weight
        private double prevGradient;
    }
    
    
}
// strata implementacija
//            if (previousWeightChange < 0) { // gradijenti su razliciti
//                if (error < 0) {
//                   w.weightChange += learningRate * error * input;
//                }
//                
//                if (error <= (shrinkFactor * previousError)) {
//                    w.weightChange += maximumGrowthFactor * previousWeightChange * input;
//                } else {
//                    w.weightChange += (error / (previousError - error)) * previousWeightChange * input;
//                }
//
//            } else if (previousWeightChange > 0) { // gradijenti su isti -mora i tekuci da bude manji od prethodnog
//                if (error > 0) {
//                    w.weightChange += learningRate * error * input ;
//                }
//                
//                if (error >= (shrinkFactor * previousError)) {
//                    w.weightChange += maximumGrowthFactor * previousWeightChange *  input;
//                } else {
//                    w.weightChange += (error / (previousError - error)) * previousWeightChange * input;
//                }
//            } else { // gradijent je 0, standardni backprop
//                w.weightChange += learningRate * error * input;
//            }
 

Ads help maintain this website.