package org.neuroph.nnet.learning;

import java.util.Iterator;

import org.neuroph.core.NeuralNetwork;
import org.neuroph.core.data.DataSet;
import org.neuroph.core.data.DataSetRow;
import org.neuroph.core.learning.SupervisedLearning;
import org.neuroph.util.NeuralNetworkCODEC;

/**
 * This class implements a simulated annealing learning rule for supervised
 * neural networks. It is based on the generic SimulatedAnnealing class. It is
 * used in the same manner as any other training class that implements the
 * SupervisedLearning interface.
 * 

* Simulated annealing is a common training method. It is often used in * conjunction with a propagation training method. Simulated annealing can be * very good when propagation training has reached a local minimum. *

* The name and inspiration come from annealing in metallurgy, a technique * involving heating and controlled cooling of a material to increase the size * of its crystals and reduce their defects. The heat causes the atoms to become * unstuck from their initial positions (a local minimum of the internal energy) * and wander randomly through states of higher energy; the slow cooling gives * them more chances of finding configurations with lower internal energy than * the initial one. * * @author Jeff Heaton (http://www.jeffheaton.com) */ public class SimulatedAnnealingLearning extends SupervisedLearning { /** * The serial id. */ private static final long serialVersionUID = 1L; /** * The starting temperature. */ private double startTemperature; /** * The ending temperature. */ private double stopTemperature; /** * The number of cycles that will be used. */ private int cycles; /** * The current temperature. */ protected double temperature; /** * Current weights from the neural network. */ private double[] weights; /** * Best weights so far. */ private double[] bestWeights; /** * Construct a simulated annleaing trainer for a feedforward neural network. * * @param network The neural network to be trained. * @param startTemp The starting temperature. * @param stopTemp The ending temperature. * @param cycles The number of cycles in a training iteration. */ public SimulatedAnnealingLearning(final NeuralNetwork network, final double startTemp, final double stopTemp, final int cycles) { setNeuralNetwork( network ); this.temperature = startTemp; this.startTemperature = startTemp; this.stopTemperature = stopTemp; this.cycles = cycles; this.weights = new double[NeuralNetworkCODEC .determineArraySize(network)]; this.bestWeights = new double[NeuralNetworkCODEC .determineArraySize(network)]; NeuralNetworkCODEC.network2array(network, this.weights); NeuralNetworkCODEC.network2array(network, this.bestWeights); } public SimulatedAnnealingLearning(final NeuralNetwork network) { this(network, 10, 2, 1000); } /** * Get the best network from the training. * * @return The best network. */ public NeuralNetwork getNetwork() { return getNeuralNetwork(); } /** * Randomize the weights and thresholds. This function does most of the work * of the class. Each call to this class will randomize the data according * to the current temperature. The higher the temperature the more * randomness. * @param randomChance */ public void randomize(double randomChance ) { for (int i = 0; i < this.weights.length; i++) if (Math.random() < randomChance) { double add = 0.5 - (Math.random()); add /= this.startTemperature; add *= this.temperature; this.weights[i] = this.weights[i] + add; } NeuralNetworkCODEC.array2network(this.weights, getNetwork()); } /** * Used internally to calculate the error for a training set. * * @param trainingSet The training set to calculate for. * @return The error value. */ private double determineError(DataSet trainingSet) { double result = 0d; Iterator iterator = trainingSet.iterator(); while (iterator.hasNext() && !isStopped()) { DataSetRow trainingSetRow = iterator.next(); double[] input = trainingSetRow.getInput(); getNetwork().setInput(input); getNetwork().calculate(); double[] output = getNetwork().getOutput(); double[] desiredOutput = trainingSetRow .getDesiredOutput(); double[] patternError = getErrorFunction().addPatternError(desiredOutput, output); double sqrErrorSum = 0; for (double error : patternError) { sqrErrorSum += (error * error); } result += sqrErrorSum / (2 * patternError.length); } return result; } /** * Perform one simulated annealing epoch. */ @Override public void doLearningEpoch(DataSet trainingSet) { doLearningEpoch( trainingSet, 0.5 ); } public void doLearningEpoch(DataSet trainingSet, double randomChance) { System.arraycopy(this.weights, 0, this.bestWeights, 0, this.weights.length); double bestError = determineError(trainingSet); this.temperature = this.startTemperature; for (int i = 0; i < this.cycles; i++) { randomize( randomChance ); double currentError = determineError(trainingSet); if (currentError < bestError) { System.arraycopy(this.weights, 0, this.bestWeights, 0, this.weights.length); bestError = currentError; } else System.arraycopy(this.bestWeights, 0, this.weights, 0, this.weights.length); NeuralNetworkCODEC.array2network(this.bestWeights, getNetwork()); final double ratio = Math.exp(Math.log(this.stopTemperature / this.startTemperature) / (this.cycles - 1)); this.temperature *= ratio; } // the following line is probably wrong (when is reset() called?), but the result might not be used for anything this.previousEpochError = getErrorFunction().getTotalError(); // moved stopping condition to separate method hasReachedStopCondition() // so it can be overriden / customized in subclasses if (hasReachedStopCondition()) { stopLearning(); } } /** * Not used. */ @Override protected void calculateWeightChanges(double[] patternError) { } }

Ads help maintain this website.