Java tutorial
/*********************************************************************** This file is part of KEEL-software, the Data Mining tool for regression, classification, clustering, pattern mining and so on. Copyright (C) 2004-2010 F. Herrera (herrera@decsai.ugr.es) L. Snchez (luciano@uniovi.es) J. Alcal-Fdez (jalcala@decsai.ugr.es) S. Garca (sglopez@ujaen.es) A. Fernndez (alberto.fernandez@ujaen.es) J. Luengo (julianlm@decsai.ugr.es) This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see http://www.gnu.org/licenses/ **********************************************************************/ package keel.Algorithms.Neural_Networks.IRPropPlus_Clas; import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; import java.io.FileReader; import java.io.IOException; import java.io.InputStream; import java.io.Reader; import java.util.ArrayList; import java.util.List; import java.util.Properties; import java.util.StringTokenizer; import keel.Algorithms.Neural_Networks.NNEP_Clas.problem.classification.softmax.SoftmaxClassificationProblemEvaluator; import keel.Algorithms.Neural_Networks.NNEP_Common.NeuralNetCreator; import keel.Algorithms.Neural_Networks.NNEP_Common.NeuralNetIndividualSpecies; import keel.Algorithms.Neural_Networks.NNEP_Common.data.AttributeType; import keel.Algorithms.Neural_Networks.NNEP_Common.data.CategoricalAttribute; import keel.Algorithms.Neural_Networks.NNEP_Common.data.DatasetException; import keel.Algorithms.Neural_Networks.NNEP_Common.data.IAttribute; import keel.Algorithms.Neural_Networks.NNEP_Common.data.IMetadata; import keel.Algorithms.Neural_Networks.NNEP_Common.data.IntegerNumericalAttribute; import keel.Algorithms.Neural_Networks.NNEP_Common.data.KeelDataSet; import keel.Algorithms.Neural_Networks.NNEP_Common.data.RealNumericalAttribute; import keel.Algorithms.Neural_Networks.NNEP_Common.neuralnet.INeuralNet; import keel.Algorithms.Neural_Networks.NNEP_Common.problem.ProblemEvaluator; import keel.Algorithms.Neural_Networks.NNEP_Common.util.random.RanNnepFactory; import net.sf.jclec.IConfigure; import net.sf.jclec.IEvaluator; import net.sf.jclec.IPopulation; import net.sf.jclec.IProvider; import net.sf.jclec.ISpecies; import net.sf.jclec.base.AbstractIndividual; import net.sf.jclec.util.intset.Interval; import net.sf.jclec.util.random.IRandGen; import net.sf.jclec.util.random.IRandGenFactory; import org.apache.commons.configuration.XMLConfiguration; /** * <p> * @author Written by Pedro Antonio Gutierrez Penia (University of Cordoba) 5/11/2007 * @author Modified by Juan Carlos Fernandez Caballero (University of Cordoba) 5/11/2007 * @version 0.1 * @since JDK1.5 */ public class KEELIRPropPlusWrapperClas implements IPopulation<AbstractIndividual<INeuralNet>> { /** * <p> * Wrapper of iRProp+ algorithm for KEEL * </p> */ ///////////////////////////////////////////////////////////////// // --------------------------------------------------- Properties ///////////////////////////////////////////////////////////////// /** Generated by Eclipse */ private static final long serialVersionUID = 3487472700821000039L; ///////////////////////////////////////////////////////////////// // ------------------------------------- Configuration properties ///////////////////////////////////////////////////////////////// /** Random generators factory */ protected static IRandGenFactory randGenFactory = null; /** Individual species */ protected static ISpecies<AbstractIndividual<INeuralNet>> species = null; /** Individuals evaluator */ protected static IEvaluator<AbstractIndividual<INeuralNet>> evaluator = null; /** Individuals provider */ protected static IProvider<AbstractIndividual<INeuralNet>> provider = null; /** Wrapped algorithm */ protected static IRPropPlus algorithm = null; /** Console reporter */ protected static IRPropPlusReporterClas consoleReporter = new IRPropPlusReporterClas(); ///////////////////////////////////////////////////////////////// // ------------------------- Implementing ISystem and IPopulation ///////////////////////////////////////////////////////////////// /** * <p> * Factory method. * * @return A new instance of a random generator * </p> */ public IRandGen createRandGen() { return randGenFactory.createRandGen(); } /** * <p> * Access to system evaluator. * * @return System evaluator * </p> */ public IEvaluator<AbstractIndividual<INeuralNet>> getEvaluator() { return evaluator; } /** * <p> * Access to current generation. * * @return Current generation * </p> */ public int getGeneration() { return 0; } /** * <p> * Access to population inhabitants. * * @return Population inhabitants * </p> */ public List<AbstractIndividual<INeuralNet>> getInhabitants() { return null; } /** * <p> * Access to system species. * * @return System species * </p> */ public ISpecies<AbstractIndividual<INeuralNet>> getSpecies() { return species; } ///////////////////////////////////////////////////////////////// // ----------------------------------------------- Public methods ///////////////////////////////////////////////////////////////// /** * <p> * Main method * </p> */ public static void main(String[] args) { configureJob(args[0]); executeJob(); } ///////////////////////////////////////////////////////////////// // ---------------------------------------------- Private methods ///////////////////////////////////////////////////////////////// /** * <p> * Configure the execution of the algorithm. * * @param jobFilename Name of the KEEL file with properties of the * execution * </p> */ @SuppressWarnings("unchecked") private static void configureJob(String jobFilename) { Properties props = new Properties(); try { InputStream paramsFile = new FileInputStream(jobFilename); props.load(paramsFile); paramsFile.close(); } catch (IOException ioe) { ioe.printStackTrace(); System.exit(0); } // Files training and test String trainFile; String testFile; StringTokenizer tokenizer = new StringTokenizer(props.getProperty("inputData")); tokenizer.nextToken(); trainFile = tokenizer.nextToken(); trainFile = trainFile.substring(1, trainFile.length() - 1); testFile = tokenizer.nextToken(); testFile = testFile.substring(1, testFile.length() - 1); // Configure schema byte[] schema = null; try { schema = readSchema(trainFile); } catch (IOException e) { e.printStackTrace(); } catch (DatasetException e) { e.printStackTrace(); } // Auxiliar configuration file XMLConfiguration conf = new XMLConfiguration(); conf.setRootElementName("algorithm"); // Configure randGenFactory randGenFactory = new RanNnepFactory(); conf.addProperty("rand-gen-factory[@seed]", Integer.parseInt(props.getProperty("seed"))); if (randGenFactory instanceof IConfigure) ((IConfigure) randGenFactory).configure(conf.subset("rand-gen-factory")); // Configure species NeuralNetIndividualSpecies nnspecies = new NeuralNetIndividualSpecies(); species = (ISpecies) nnspecies; if (props.getProperty("Transfer").equals("Product_Unit")) { conf.addProperty("species.neural-net-type", "keel.Algorithms.Neural_Networks.IRPropPlus_Clas.MSEOptimizablePUNeuralNetClassifier"); conf.addProperty("species.hidden-layer[@type]", "keel.Algorithms.Neural_Networks.NNEP_Common.neuralnet.ExpLayer"); conf.addProperty("species.hidden-layer[@biased]", false); } else { conf.addProperty("species.neural-net-type", "keel.Algorithms.Neural_Networks.IRPropPlus_Clas.MSEOptimizableSigmNeuralNetClassifier"); conf.addProperty("species.hidden-layer[@type]", "keel.Algorithms.Neural_Networks.NNEP_Common.neuralnet.SigmLayer"); conf.addProperty("species.hidden-layer[@biased]", true); } int neurons = Integer.parseInt(props.getProperty("Hidden_nodes")); conf.addProperty("species.hidden-layer.minimum-number-of-neurons", neurons); conf.addProperty("species.hidden-layer.initial-maximum-number-of-neurons", neurons); conf.addProperty("species.hidden-layer.maximum-number-of-neurons", neurons); conf.addProperty("species.hidden-layer.initiator-of-links", "keel.Algorithms.Neural_Networks.IRPropPlus_Clas.FullRandomInitiator"); conf.addProperty("species.hidden-layer.weight-range[@type]", "net.sf.jclec.util.range.Interval"); conf.addProperty("species.hidden-layer.weight-range[@closure]", "closed-closed"); if (props.getProperty("Transfer").equals("Product_Unit")) { conf.addProperty("species.hidden-layer.weight-range[@left]", -0.1); conf.addProperty("species.hidden-layer.weight-range[@right]", 0.1); } else { conf.addProperty("species.hidden-layer.weight-range[@left]", -5.0); conf.addProperty("species.hidden-layer.weight-range[@right]", 5.0); } conf.addProperty("species.output-layer[@type]", "keel.Algorithms.Neural_Networks.NNEP_Common.neuralnet.LinearLayer"); conf.addProperty("species.output-layer[@biased]", true); conf.addProperty("species.output-layer.initiator-of-links", "keel.Algorithms.Neural_Networks.IRPropPlus_Clas.FullRandomInitiator"); conf.addProperty("species.output-layer.weight-range[@type]", "net.sf.jclec.util.range.Interval"); conf.addProperty("species.output-layer.weight-range[@closure]", "closed-closed"); conf.addProperty("species.output-layer.weight-range[@left]", -5.0); conf.addProperty("species.output-layer.weight-range[@right]", 5.0); if (species instanceof IConfigure) ((IConfigure) species).configure(conf.subset("species")); // Configure evaluator evaluator = (IEvaluator) new SoftmaxClassificationProblemEvaluator(); if (props.getProperty("Transfer").equals("Product_Unit")) conf.addProperty("evaluator[@log-input-data]", true); conf.addProperty("evaluator[@normalize-data]", true); conf.addProperty("evaluator.error-function", "keel.Algorithms.Neural_Networks.NNEP_Clas.problem.errorfunctions.LogisticErrorFunction"); conf.addProperty("evaluator.input-interval[@closure]", "closed-closed"); conf.addProperty("evaluator.input-interval[@left]", 0.1); conf.addProperty("evaluator.input-interval[@right]", 0.9); conf.addProperty("evaluator.output-interval[@closure]", "closed-closed"); conf.addProperty("evaluator.output-interval[@left]", 0.0); conf.addProperty("evaluator.output-interval[@right]", 1.0); if (evaluator instanceof IConfigure) ((IConfigure) evaluator).configure(conf.subset("evaluator")); // Configure provider provider = new NeuralNetCreator(); KEELIRPropPlusWrapperClas system = new KEELIRPropPlusWrapperClas(); provider.contextualize(system); // Configure iRProp+ algorithm algorithm = new IRPropPlus(); conf.addProperty("algorithm.initial-step-size[@value]", 0.0125); conf.addProperty("algorithm.minimum-delta[@value]", 0.0); conf.addProperty("algorithm.maximum-delta[@value]", 50.0); conf.addProperty("algorithm.positive-eta[@value]", 1.2); conf.addProperty("algorithm.negative-eta[@value]", 0.2); conf.addProperty("algorithm.cycles[@value]", Integer.parseInt(props.getProperty("Epochs"))); if (algorithm instanceof IConfigure) ((IConfigure) algorithm).configure(conf.subset("algorithm")); // Read data ProblemEvaluator<AbstractIndividual<INeuralNet>> evaluator2 = (ProblemEvaluator<AbstractIndividual<INeuralNet>>) evaluator; evaluator2.readData(schema, new KeelDataSet(trainFile), new KeelDataSet(testFile)); nnspecies.setNOfInputs(evaluator2.getTrainData().getNofinputs()); nnspecies.setNOfOutputs(evaluator2.getTrainData().getNofoutputs() - 1); algorithm.setTrainingData(evaluator2.getTrainData()); // Read output files tokenizer = new StringTokenizer(props.getProperty("outputData")); String trainResultFile = tokenizer.nextToken(); trainResultFile = trainResultFile.substring(1, trainResultFile.length() - 1); consoleReporter.setTrainResultFile(trainResultFile); String testResultFile = tokenizer.nextToken(); testResultFile = testResultFile.substring(1, testResultFile.length() - 1); consoleReporter.setTestResultFile(testResultFile); String bestModelResultFile = tokenizer.nextToken(); bestModelResultFile = bestModelResultFile.substring(1, bestModelResultFile.length() - 1); consoleReporter.setBestModelResultFile(bestModelResultFile); } /** * <p> * Executes the algorithm * </p> */ private static void executeJob() { // Provide a random individual List<AbstractIndividual<INeuralNet>> nnind = provider.provide(1); // Evaluate it System.out.println("\n\nGenerated Individual\n--------------------\n" + consoleReporter.renderNeuralNetIndividual(nnind.get(0), evaluator)); // Exponents weights have a reduced step size if (nnind.get(0).getGenotype() instanceof MSEOptimizablePUNeuralNetClassifier) algorithm.setReducedStepSize( obtainReducedStepSize((MSEOptimizablePUNeuralNetClassifier) nnind.get(0).getGenotype())); else algorithm.setReducedStepSize(null); // Apply iRPropAlgorithm nnind.get(0).setGenotype((INeuralNet) algorithm.optimize((IOptimizableFunc) nnind.get(0).getGenotype())); // Evaluate it System.out.println("Optimized Individual\n--------------------\n" + consoleReporter.renderNeuralNetIndividual(nnind.get(0), evaluator)); // Print Results consoleReporter.algorithmFinished(nnind.get(0), (ProblemEvaluator<AbstractIndividual<INeuralNet>>) evaluator); } /** * <p> * Reads schema from the KEEL file * * @param jobFilename Name of the KEEL dataset file * </p> */ private static byte[] readSchema(String fileName) throws IOException, DatasetException { KeelDataSet dataset = new KeelDataSet(fileName); dataset.open(); File file = new File(fileName); List<String> inputIds = new ArrayList<String>(); List<String> outputIds = new ArrayList<String>(); Reader reader = new BufferedReader(new FileReader(file)); String line = ((BufferedReader) reader).readLine(); StringTokenizer elementLine = new StringTokenizer(line); String element = elementLine.nextToken(); while (!element.equalsIgnoreCase("@data")) { if (element.equalsIgnoreCase("@inputs")) { while (elementLine.hasMoreTokens()) { StringTokenizer commaTokenizer = new StringTokenizer(elementLine.nextToken(), ","); while (commaTokenizer.hasMoreTokens()) inputIds.add(commaTokenizer.nextToken()); } } else if (element.equalsIgnoreCase("@outputs")) { while (elementLine.hasMoreTokens()) { StringTokenizer commaTokenizer = new StringTokenizer(elementLine.nextToken(), ","); while (commaTokenizer.hasMoreTokens()) outputIds.add(commaTokenizer.nextToken()); } } // Next line of the file line = ((BufferedReader) reader).readLine(); while (line.startsWith("%") || line.equalsIgnoreCase("")) line = ((BufferedReader) reader).readLine(); elementLine = new StringTokenizer(line); element = elementLine.nextToken(); } IMetadata metadata = dataset.getMetadata(); byte[] schema = new byte[metadata.numberOfAttributes()]; if (inputIds.isEmpty() || outputIds.isEmpty()) { for (int i = 0; i < schema.length; i++) { if (i != (schema.length - 1)) schema[i] = 1; else { IAttribute outputAttribute = metadata.getAttribute(i); schema[i] = 2; consoleReporter.setOutputAttribute(outputAttribute); } } } else { for (int i = 0; i < schema.length; i++) { if (inputIds.contains(metadata.getAttribute(i).getName())) schema[i] = 1; else if (outputIds.contains(metadata.getAttribute(i).getName())) { IAttribute outputAttribute = metadata.getAttribute(i); schema[i] = 2; consoleReporter.setOutputAttribute(outputAttribute); } else schema[i] = -1; } } StringBuffer header = new StringBuffer(); header.append("@relation " + dataset.getName() + "\n"); for (int i = 0; i < metadata.numberOfAttributes(); i++) { IAttribute attribute = metadata.getAttribute(i); header.append("@attribute " + attribute.getName() + " "); if (attribute.getType() == AttributeType.Categorical) { CategoricalAttribute catAtt = (CategoricalAttribute) attribute; Interval interval = catAtt.intervalValues(); header.append("{"); for (int j = (int) interval.getLeft(); j <= interval.size() + 1; j++) { header.append(catAtt.show(j) + (j != interval.size() + 1 ? "," : "}\n")); } } else if (attribute.getType() == AttributeType.IntegerNumerical) { IntegerNumericalAttribute intAtt = (IntegerNumericalAttribute) attribute; header.append("integer[" + (int) intAtt.intervalValues().getLeft() + "," + (int) intAtt.intervalValues().getRight() + "]\n"); } else if (attribute.getType() == AttributeType.DoubleNumerical) { RealNumericalAttribute doubleAtt = (RealNumericalAttribute) attribute; header.append("real[" + doubleAtt.intervalValues().getLeft() + "," + doubleAtt.intervalValues().getRight() + "]\n"); } } header.append("@data\n"); consoleReporter.setHeader(header.toString()); dataset.close(); return schema; } /** * <p> * Mark exponents of a MSEOptimizablePUNeuralNetClassifier as reduced * * @param neuralNet MSEOptimizablePUNeuralNetClassifier to analyze * @return boolean[] Reduced Step Size Array * </p> */ private static boolean[] obtainReducedStepSize(MSEOptimizablePUNeuralNetClassifier neuralNet) { int inputs = neuralNet.getInputLayer().getMaxnofneurons(); int outputs = neuralNet.getOutputLayer().getMaxnofneurons(); int hiddenNeurons = neuralNet.getNofhneurons(); boolean[] reduced = new boolean[inputs * hiddenNeurons + outputs * (hiddenNeurons + 1)]; // For each hidden neuron for (int i = 0; i < hiddenNeurons; i++) { // Base index int baseIndex = outputs + i * (inputs + outputs); for (int j = 0; j < inputs; j++) reduced[baseIndex + j] = true; // Base index baseIndex += inputs; for (int j = 0; j < outputs; j++) reduced[baseIndex + j] = false; } for (int j = 0; j < outputs; j++) reduced[j] = false; return reduced; } }