/***********************************************************************
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. S�nchez (luciano@uniovi.es)
J. Alcal�-Fdez (jalcala@decsai.ugr.es)
S. Garc�a (sglopez@ujaen.es)
A. Fern�ndez (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/
**********************************************************************/
/**
* <p>
* @author Modified by Maria Dolores Perez Godoy (University of Jaen)
* @author Modified by Antonio J. Rivera Rivas (University of Jaen)
* @author Modified by Victor M. Rivas Santos (University of Jaen)
* @version 1.0
* @since JDK1.5
* </p>
*/
package keel.Algorithms.Neural_Networks.EvRBF_CL;
import org.core.*;
import java.io.*;
import java.util.*;
public class doEvRBF_Cl {
/**
* <p>
* This class allows the building of an Evolutionary Algorithm to generate
* RBF Neural Networks.
* This class contains a MAIN function that reads parameters, builds the net,
* and produces the results yielded by the net when is applied to the test
* data set.
* </p>
*/
/** Filename for training data set */
static String trnFile;
/** Filename for test data set */
static String tstFile;
/** Filename for results of RBFN on training set */
static String outTrnFile;
/** Filename for results of RBFN on test set */
static String outTstFile;
/** Filename for file where RBF will be written */
static String outRbfFile;
/** Rate of neurons */
static double neuronsRate;
/** rate of instances for validation */
static double validationRate;
/** rate of individuals to replace */
static double replacementRate;
/** rate of xOver operator */
static double xOverRate;
/** rate of mutator operators */
static double mutatorRate;
/** tournament size */
static int tournamentSize;
/** max number of generations */
static int maxGenerations;
/** Number of individuals */
static int popSize;
/** Seed for random generator initialization. */
static double seed;
/** Whether Seed must be used ir not */
static boolean reallySeed;
static double [][] X, Xtrn, Xval, Xtst;
static double [][] Y, Ytrn, Yval, Ytst;
static int [] auxY, auxYtrn, auxYval, auxYtst;
static RbfnPopulation population;
static int nEnt,nSal,i,j;
static int nTrn, nVal, nTst;
static int LMSLoops=1;
/** <p>Does nothing.</p> */
public doEvRBF_Cl() {}
/**
* <p>
* Splits the training ProcDataset into 2 data sets: one for training and another for validation
* </p>
* @param DData Original (complete) training data set
* @returns Nothing, but modifies XTrn, YTrn, XVal, YVal
*/
private static void set_training_validation( ProcDataset DData ) {
try {
DData.processClassifierDataset();
nEnt = DData.getninputs();
nSal = 1;//PD.getnvariables()-nEnt;
int ndatos = DData.getndata();
Xtrn=new double[ndatos][nEnt];
Xval=new double[ndatos][nEnt];
Ytrn=new double[ndatos][nSal];
Yval=new double[ndatos][nSal];
auxYtrn=new int[ndatos];
auxYval=new int[ndatos];
nTrn=nVal=0;
double [][] X, Y;
int [] auxY;
Y = new double [ndatos][1];
X = DData.getX();
auxY = DData.getC();
for (i = 0; i < ndatos; i++) {
Y[i][0]=auxY[i];
}
for ( i=0; i<ndatos; ++i ) {
int aleat=(int)Randomize.Randint( 1, (int)100 );
if ( aleat>=validationRate*100 ) {
Xtrn[nTrn]=X[i];
Ytrn[nTrn]=Y[i];
auxYtrn[nTrn]=auxY[i];
++nTrn;
} else {
Xval[nVal]=X[i];
Yval[nVal]=Y[i];
auxYval[nVal]=auxY[i];
++nVal;
}
}
} catch ( Exception e ) {
throw new InternalError(e.toString());
}
}
/**
* <p>
* Establishes the values for XTst and YTst
* </p>
* @param DData Original test data set
* @returns Nothing, but modifies XTst and Ytst
*/
private static void set_test( ProcDataset DData ) {
try {
DData.processClassifierDataset();
nTst= DData.getndata();
Xtst = DData.getX();
Ytst=new double[nTst][nSal];
nTst=Xtst.length;
auxYtst = DData.getC();
for (i = 0; i < nTst; i++) {
Ytst[i][0]=auxYtst[i];
}
} catch ( Exception e ) {
throw new InternalError(e.toString());
}
}
/**
* <p>
* Reads parameters from parameter file.</p>
* @param _fileName Name of file with parameters.
* @return True if everything goes right. False otherwise.
*/
private static boolean setParameters( String fileName ) {
try {
Hashtable parametros=RBFUtils.parameters( fileName );
RBFUtils.setVerbosity( parametros );
String tmp;
tmp=((String) ((Vector) parametros.get ( "inputData" )).get( 0 ));
trnFile=tmp.substring( 1, tmp.length()-1 ); // Character " must be removed.
tmp=(String) ((Vector) parametros.get ( "inputData" )).get( 2 );
tstFile=tmp.substring( 1, tmp.length()-1 ); // Character " must be removed.
tmp=(String) ((Vector) parametros.get ( "outputData" )).get( 0 );
outTrnFile=tmp.substring( 1, tmp.length()-1 ); // Character " must be removed.
tmp=(String) ((Vector) parametros.get ( "outputData" )).get( 1 );
outTstFile=tmp.substring( 1, tmp.length()-1 ); // Character " must be removed.
tmp=(String) ((Vector) parametros.get ( "outputData" )).get( 2 );
outRbfFile=tmp.substring( 1, tmp.length()-1 ); // Character " must be removed.
neuronsRate=(double) Double.parseDouble( (String) ((Vector) parametros.get ( "neuronsRate" )).get( 0 ));
validationRate=(double) Double.parseDouble( (String) ((Vector) parametros.get ( "validationRate" )).get( 0 ));
replacementRate=(double) Double.parseDouble( (String) ((Vector) parametros.get ( "replacementRate" )).get( 0 ));
xOverRate=(double) Double.parseDouble( (String) ((Vector) parametros.get ( "xOverRate" )).get( 0 ));
mutatorRate=(double) Double.parseDouble( (String) ((Vector) parametros.get ( "mutatorRate" )).get( 0 ));
popSize=(int) Double.parseDouble( (String) ((Vector) parametros.get ( "popSize" )).get( 0 ));
tournamentSize=(int) Double.parseDouble( (String) ((Vector) parametros.get ( "tournamentSize" )).get( 0 ));
maxGenerations=(int) Double.parseDouble( (String) ((Vector) parametros.get ( "maxGenerations" )).get( 0 ));
if ( parametros.containsKey ( "seed" ) ) {
reallySeed=true;
seed=(double) Double.parseDouble( (String) ((Vector) parametros.get ( "seed" )).get( 0 ));
} else {
reallySeed=false;
seed=(double) Math.random()*1e6;
}
RBFUtils.verboseln( "Training file : "+trnFile );
RBFUtils.verboseln( "Test file : "+tstFile );
RBFUtils.verboseln( "Ouput Training file: "+outTrnFile );
RBFUtils.verboseln( "Ouput Test file : "+outTstFile );
RBFUtils.verboseln( "Ouput RBF file : "+outRbfFile );
RBFUtils.verboseln( "Population size : "+popSize );
RBFUtils.verboseln( "Tournament size : "+tournamentSize );
RBFUtils.verboseln( "Max. generations : "+maxGenerations );
RBFUtils.verboseln( "Neurons rate : "+neuronsRate );
RBFUtils.verboseln( "Validation rate : "+validationRate );
RBFUtils.verboseln( "Replacement rate : "+replacementRate );
RBFUtils.verboseln( "XOver rate : "+xOverRate );
RBFUtils.verboseln( "Mutator rate : "+mutatorRate );
RBFUtils.verbose( "Seed : ");
if( reallySeed ) {
RBFUtils.verboseln( ""+seed);
} else {
RBFUtils.verboseln( "No seed, i.e., pure random execution (set to "+seed+")" );
}
RBFUtils.verboseln( "Verbosity : "+ RBFUtils.getVerbosity() );
return ( trnFile!="" && tstFile!="" && outTrnFile!="" && outTstFile!="" && neuronsRate>0) ;
} catch ( Exception e) {
throw new InternalError ( "Error reading parameters: Possibly, one of them is lacking;"+
" or the parameters file is not correctly formed\n"+ e.toString() );
}
}
/**
* <p>
* Prints help on screen when user executes with argument
* --help or -help or -h or -?
* </p>
* @return nothing
*/
private static void doHelp() {
System.out.println( "Usage: doEvRBF_Cl paramFile" );
System.out.println( " doEvRBF_Cl --help" );
System.out.println( " (doEvRBF_Cl can also be EvRBF_Cl.jar)" );
System.out.println( " Where: " );
System.out.println( " paramFile Name of file containing the parameters according to Keel format." );
System.out.println( " Example of parameter file: " );
System.out.println( " algorithm = evrbf_cl" );
System.out.println( " popSize = 20" );
System.out.println( " tournamentSize = 2" );
System.out.println( " maxGenerations = 100" );
System.out.println( " neuronsRate = 0.1" );
System.out.println( " validationRate = 0.15" );
System.out.println( " replacementRate = 0.3" );
System.out.println( " xOverRate = 0.9" );
System.out.println( " mutatorRate = 0.1" );
System.out.println( " verbose = true" );
System.out.println( " inputData = \"sintetica.trn\" \"sintetica.tst\" ");
System.out.println( " outputData = \"result1.trn\" \"result1.tst\" \"result1.rbf\" " );
System.out.println( "\n---\n"+
"Author: Victor Rivas (vrivas@ujaen.es)\n"+
"From: Univ. of Jaen (Spain)\n"+
"For: Keel Project.\n\n" );
}
/**
* <p>
* Main Function: reads the parameters, creates the population, evolves it, gets the best individual, writes results and finishes.
* </p>
* @param args the Command line arguments. Only one is processed: the name of the file containing the parameters
*/
public static void main(String[] args) throws IOException{
Rbfn red;
try {
// Help required
if ( args.length>0 ) {
if ( args[0].equals( "--help" ) || args[0].equals( "-help" ) ||
args[0].equals( "-h" ) || args[0].equals( "-?" )) {
doHelp();
return;
}
}
System.out.println( "- Executing doEvRBF_Cl "+args.length );
// Reading parameters
String paramFile=(args.length>0)?args[0]:"parametros.txt";
setParameters( paramFile );
System.out.println( " - Parameters file: "+paramFile );
// Random generator setup
Randomize.setSeed( (long) seed );
//Reading training and tests datasets
ProcDataset Dtrn = new ProcDataset(trnFile,true);
ProcDataset Dtst = new ProcDataset(tstFile,false);
if (Dtrn.datasetType()==1) { //Clasification dataset
System.out.println( "Classification Dataset");
//Split training and validation data sets
set_training_validation( Dtrn );
// Initialize, train and set fitness of population
population=new RbfnPopulation(popSize, Xtrn, nTrn,
nEnt, nSal, neuronsRate );
population.trainLMS( Xtrn, Ytrn, nTrn, LMSLoops, 0.3 );
population.setFitness_Cl( Xval, Yval, nVal, Dtrn.getnclasses()-1 );
population.sort_population();
// The evolutionary algorithm does start
for ( int ng=0; ng< maxGenerations; ++ng ) {
population.selectIndividuals( (int) (popSize*replacementRate), tournamentSize );
population.applyOperators( xOverRate, mutatorRate );
population.trainLMS_subPop( Xtrn, Ytrn, nTrn, LMSLoops, 0.3 );
population.setFitness_Cl_subPop( Xval, Yval, nVal, Dtrn.getnclasses()-1 );
population.replaceIndividuals((int) (popSize*replacementRate) );
System.out.println( " Generation "+(ng+1)+", fitness "+population.individual(0).getFitness() );
}
// Training the final population one more time
population.trainLMS( Xtrn, Ytrn, nTrn, LMSLoops, 0.3 );
population.trainLMS( Xval, Yval, nVal, LMSLoops, 0.3 );
//red.classificationTest(X,ndatos,yieldedResults,Dtrn.getnclasses()-1,0);
//Dtrn.creaResultadosClasificacion(outTrnFile,auxY,yieldedResults);
//TEST
set_test( Dtst );
//int [] yieldedResults = new int[nTst];
population.setFitness_Cl( Xtst, Ytst, nTst, Dtrn.getnclasses()-1 );
population.sort_population();
//System.out.println( "Last order: ");
//population.paint_sort( 5 );
// Process to reduce the number of neurons
Rbfn bestNet=(Rbfn) population.individual( 0 ).clone();
bestNet.setFitness_Cl( Xtst, Ytst, nTst, Dtrn.getnclasses()-1 );
String [] indexes;
boolean nextStep=true;
while( nextStep ) {
nextStep=false;
i=0;
indexes=bestNet.getIndexes();
while (i<indexes.length && indexes.length>1 ) {
Rbfn tmpNet=(Rbfn) bestNet.clone();
tmpNet.removeRbf(indexes[i]);
tmpNet.setFitness_Cl( Xtst, Ytst, nTst, Dtrn.getnclasses()-1 );
if( tmpNet.getFitness()>=bestNet.getFitness() ) {
bestNet=(Rbfn) tmpNet.clone();
nextStep=true;
indexes=bestNet.getIndexes();
} else {
++i;
}
}
}
//Writting Training results
Dtrn.processClassifierDataset();
int ndatos = Dtrn.getndata();
Y = new double [ndatos][1];
X = Dtrn.getX();
int [] auxY;
auxY = Dtrn.getC();
for (i = 0; i < ndatos; i++)
Y[i][0]=auxY[i];
//Building and training the net
//neurons = Dtrn.getnclasses();
int [] yieldedResults = new int[ndatos];
bestNet.classificationTest(X,ndatos,yieldedResults,Dtrn.getnclasses()-1,0);
Dtrn.generateResultsClasification(outTrnFile,auxY,yieldedResults);
//Writting test results
Dtst.processClassifierDataset();
ndatos = Dtst.getndata();
Y = new double [ndatos][1];
yieldedResults = new int[ndatos];
X = Dtst.getX();
auxY = Dtst.getC();
for (i = 0; i < ndatos; i++)
Y[i][0]=auxY[i];
bestNet.classificationTest(X,ndatos,yieldedResults,Dtrn.getnclasses()-1,0);
Dtst.generateResultsClasification(outTstFile,auxY,yieldedResults);
RBFUtils.createOutputFile( "", outRbfFile );
bestNet.paint( outRbfFile );
// System.output
System.out.println( " Indiv. "+0+":\t"+
bestNet.getFitness()+"\t-\t"+bestNet.rbfSize()+"" );
/*
for (i=0; i<popSize; ++i ) {
Dtst.creaResultadosClasificacion(outTstFile,auxYtst,yieldedResults);
RBFUtils.createOutputFile( "", outRbfFile );
//population[i].paint( outRbfFile );
}
*/
} // IF to test whether it is a classification problem or not
if (Dtrn.datasetType()==2) System.out.println( "Clustering");
System.out.println( "- End of doEvRBF_Cl. "+
"See results in output files named according to "+
paramFile+" parameters file." );
} catch ( Exception e ) {
throw new InternalError(e.toString());
}
}
}
/*
if (Dtrn.datasetType()==0) {//Modelling Dataset
//Training
System.out.println( "Modeling Dataset");
Dtrn.processModelDataset();
nEnt = Dtrn.getninputs();
nSal = 1;//PD.getnvariables()-nEnt;
ndatos = Dtrn.getndata();
Y = new double [ndatos][1];
X = Dtrn.getX();
double [] auxY;
auxY = Dtrn.getY();
for (i = 0; i < ndatos; i++)
Y[i][0]=auxY[i];
//Building and training the net
red=new Rbfn(X,ndatos,nEnt,nSal,neurons);
red.LMSTrain(X, Y, ndatos, LMSLoops, 0.3 );
double [] yieldedResults = new double[ndatos];
red.modellingTest(X,ndatos,yieldedResults);
Dtrn.creaResultadosModelado(outTrnFile,auxY,yieldedResults);
//TEST
ProcDataset Dtst = new ProcDataset(tstFile,false);
Dtst.processModelDataset();
nEnt = Dtst.getninputs();
nSal = 1;//PD.getnvariables()-nEnt;
ndatos = Dtst.getndata();
X = Dtst.getX();
auxY = Dtst.getY();
Y = new double [ndatos][1];
for (i = 0; i < ndatos; i++)
Y[i][0]=auxY[i];
yieldedResults = new double[ndatos];
red.modellingTest(X,ndatos,yieldedResults);
Dtst.creaResultadosModelado(outTstFile,auxY,yieldedResults);
RBFUtils.createOutputFile( "", outRbfFile );
red.paint( outRbfFile );
}
*/