keel.Algorithms.Neural_Networks.IRPropPlus_Clas.KEELIRPropPlusWrapperClas.java Source code

Java tutorial

Introduction

Here is the source code for keel.Algorithms.Neural_Networks.IRPropPlus_Clas.KEELIRPropPlusWrapperClas.java

Source

/***********************************************************************
    
   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;
    }
}