/** * Copyright 2010 Neuroph Project http://neuroph.sourceforge.net * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.neuroph.samples.intronn; import java.text.NumberFormat; import java.util.Observable; import java.util.Observer; import org.neuroph.core.NeuralNetwork; import org.neuroph.core.learning.SupervisedLearning; import org.neuroph.core.learning.SupervisedTrainingElement; import org.neuroph.core.learning.TrainingSet; import org.neuroph.nnet.MultiLayerPerceptron; import org.neuroph.nnet.Neuroph; import org.neuroph.nnet.flat.FlatNetworkPlugin; import org.neuroph.nnet.learning.LMS; import org.neuroph.util.TransferFunctionType; /** * This example shows how to use Neuroph to predict sunspots. * * It demonstrates two very important machine learning techniques. * * First, time-window. Sunspots are organized into input windows used * to predict the next level of sunspot activity. This example uses a * 30 year window. Basically, 30 years of sunspot activity is used to * predict the 31st year. This 30 year window slides forward, one year * at a time. * * Second is normalization. The sunspots are normalized into a * range between 0.1 and 0.9. This is very close to the actual * 0 to 1 range of the sigmoid function. We stay away from the * extream edges of this range, thus using 0.1 and 0.9. * * This is an example from the book "Introduction to Neural Networks * for Java" by Jeff Heaton. This example has been contributed * to the Neuroph project by Jeff Heaton. * * http://www.heatonresearch.com/book/programming-neural-networks-java-2.html * * @author Jeff Heaton (http://www.heatonresearch.com * */ public class SunSpots implements Observer { public final static double[] SUNSPOTS = { 0.0262, 0.0575, 0.0837, 0.1203, 0.1883, 0.3033, 0.1517, 0.1046, 0.0523, 0.0418, 0.0157, 0.0000, 0.0000, 0.0105, 0.0575, 0.1412, 0.2458, 0.3295, 0.3138, 0.2040, 0.1464, 0.1360, 0.1151, 0.0575, 0.1098, 0.2092, 0.4079, 0.6381, 0.5387, 0.3818, 0.2458, 0.1831, 0.0575, 0.0262, 0.0837, 0.1778, 0.3661, 0.4236, 0.5805, 0.5282, 0.3818, 0.2092, 0.1046, 0.0837, 0.0262, 0.0575, 0.1151, 0.2092, 0.3138, 0.4231, 0.4362, 0.2495, 0.2500, 0.1606, 0.0638, 0.0502, 0.0534, 0.1700, 0.2489, 0.2824, 0.3290, 0.4493, 0.3201, 0.2359, 0.1904, 0.1093, 0.0596, 0.1977, 0.3651, 0.5549, 0.5272, 0.4268, 0.3478, 0.1820, 0.1600, 0.0366, 0.1036, 0.4838, 0.8075, 0.6585, 0.4435, 0.3562, 0.2014, 0.1192, 0.0534, 0.1260, 0.4336, 0.6904, 0.6846, 0.6177, 0.4702, 0.3483, 0.3138, 0.2453, 0.2144, 0.1114, 0.0837, 0.0335, 0.0214, 0.0356, 0.0758, 0.1778, 0.2354, 0.2254, 0.2484, 0.2207, 0.1470, 0.0528, 0.0424, 0.0131, 0.0000, 0.0073, 0.0262, 0.0638, 0.0727, 0.1851, 0.2395, 0.2150, 0.1574, 0.1250, 0.0816, 0.0345, 0.0209, 0.0094, 0.0445, 0.0868, 0.1898, 0.2594, 0.3358, 0.3504, 0.3708, 0.2500, 0.1438, 0.0445, 0.0690, 0.2976, 0.6354, 0.7233, 0.5397, 0.4482, 0.3379, 0.1919, 0.1266, 0.0560, 0.0785, 0.2097, 0.3216, 0.5152, 0.6522, 0.5036, 0.3483, 0.3373, 0.2829, 0.2040, 0.1077, 0.0350, 0.0225, 0.1187, 0.2866, 0.4906, 0.5010, 0.4038, 0.3091, 0.2301, 0.2458, 0.1595, 0.0853, 0.0382, 0.1966, 0.3870, 0.7270, 0.5816, 0.5314, 0.3462, 0.2338, 0.0889, 0.0591, 0.0649, 0.0178, 0.0314, 0.1689, 0.2840, 0.3122, 0.3332, 0.3321, 0.2730, 0.1328, 0.0685, 0.0356, 0.0330, 0.0371, 0.1862, 0.3818, 0.4451, 0.4079, 0.3347, 0.2186, 0.1370, 0.1396, 0.0633, 0.0497, 0.0141, 0.0262, 0.1276, 0.2197, 0.3321, 0.2814, 0.3243, 0.2537, 0.2296, 0.0973, 0.0298, 0.0188, 0.0073, 0.0502, 0.2479, 0.2986, 0.5434, 0.4215, 0.3326, 0.1966, 0.1365, 0.0743, 0.0303, 0.0873, 0.2317, 0.3342, 0.3609, 0.4069, 0.3394, 0.1867, 0.1109, 0.0581, 0.0298, 0.0455, 0.1888, 0.4168, 0.5983, 0.5732, 0.4644, 0.3546, 0.2484, 0.1600, 0.0853, 0.0502, 0.1736, 0.4843, 0.7929, 0.7128, 0.7045, 0.4388, 0.3630, 0.1647, 0.0727, 0.0230, 0.1987, 0.7411, 0.9947, 0.9665, 0.8316, 0.5873, 0.2819, 0.1961, 0.1459, 0.0534, 0.0790, 0.2458, 0.4906, 0.5539, 0.5518, 0.5465, 0.3483, 0.3603, 0.1987, 0.1804, 0.0811, 0.0659, 0.1428, 0.4838, 0.8127 }; /** * Starting year for sunspot data. */ public final static int STARTING_YEAR = 1700; /** * Size of our prediction window. */ public final static int WINDOW_SIZE = 30; /** * Start of training data. */ public final static int TRAIN_START = WINDOW_SIZE; /** * End of training data. */ public final static int TRAIN_END = 259; /** * Beginning of evaluation data. */ public final static int EVALUATE_START = 260; /** * End of evaluation data. */ public final static int EVALUATE_END = SUNSPOTS.length - 1; /** * This really should be lowered, I am setting it to a level here that will * train in under a minute. */ public final static double MAX_ERROR = 0.06; /** * Normalized sunspots. */ private double[] normalizedSunspots; /** * Closed loop sunspots. Closed loop means use the neural network output * as the input for the next prediction, rather than actual data. */ private double[] closedLoopSunspots; private double mean; /** * Normalize the sunspots. * @param lo Low range for normalization. * @param hi High range for normalization. */ public void normalizeSunspots(double lo, double hi) { double min = Double.MAX_VALUE; double max = Double.MIN_VALUE; for (int year = 0; year < SUNSPOTS.length; year++) { min = Math.min(min, SUNSPOTS[year]); max = Math.max(max, SUNSPOTS[year]); } normalizedSunspots = new double[SUNSPOTS.length]; closedLoopSunspots = new double[SUNSPOTS.length]; mean = 0; for (int year = 0; year < SUNSPOTS.length; year++) { normalizedSunspots[year] = closedLoopSunspots[year] = ((SUNSPOTS[year] - min) / (max - min)) * (hi - lo) + lo; mean += normalizedSunspots[year] / SUNSPOTS.length; } } /** * Generate the training data for the training sunspot years. * @return The training data. */ public TrainingSet generateTraining() { TrainingSet result = new TrainingSet(WINDOW_SIZE, 1); for (int year = TRAIN_START; year < TRAIN_END; year++) { double[] input = new double[WINDOW_SIZE]; double[] ideal = new double[1]; int index = 0; for (int i = year - WINDOW_SIZE; i < year; i++) { input[index++] = this.normalizedSunspots[i]; } ideal[0] = this.normalizedSunspots[year]; result.addElement(new SupervisedTrainingElement(input, ideal)); } return result; } /** * Predict sunspots. * @param network Neural network to use. */ public void predict(NeuralNetwork network) { NumberFormat f = NumberFormat.getNumberInstance(); f.setMaximumFractionDigits(4); f.setMinimumFractionDigits(4); System.out.println("Year\tActual\tPredict\tClosed Loop Predict"); for (int year = EVALUATE_START; year < EVALUATE_END; year++) { // calculate based on actual data double[] input = new double[WINDOW_SIZE]; for (int i = 0; i < input.length; i++) { input[i] = this.normalizedSunspots[(year - WINDOW_SIZE) + i]; } network.setInput(input); network.calculate(); double[] output = network.getOutput(); double prediction = output[0]; this.closedLoopSunspots[year] = prediction; // calculate "closed loop", based on predicted data for (int i = 0; i < input.length; i++) { input[i] = this.closedLoopSunspots[(year - WINDOW_SIZE) + i]; } network.setInput(input); network.calculate(); output = network.getOutput(); double closedLoopPrediction = output[0]; // display System.out.println((STARTING_YEAR + year) + "\t" + f.format(this.normalizedSunspots[year]) + "\t" + f.format(prediction) + "\t" + f.format(closedLoopPrediction)); } } public void run() { // uncomment the following line to use regular Neuroph (non-flat) processing Neuroph.getInstance().setFlattenNetworks(false); NeuralNetwork network = new MultiLayerPerceptron(TransferFunctionType.SIGMOID, WINDOW_SIZE, 10, 1); normalizeSunspots(0.1, 0.9); network.getLearningRule().addObserver(this); TrainingSet training = generateTraining(); network.learnInSameThread(training); predict(network); Neuroph.getInstance().shutdown(); } public static void main(String args[]) { SunSpots sunspot = new SunSpots(); sunspot.run(); } @Override public void update(Observable arg0, Object arg1) { SupervisedLearning rule = (SupervisedLearning)arg0; System.out.println( "Training, Network Epoch " + rule.getCurrentIteration() + ", Error:" + rule.getTotalNetworkError()); } }