/*********************************************************************** 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/ **********************************************************************/ package keel.Algorithms.PSO_Learning.REPSO; /** * <p>Title: Algorithm REPSO</p> * * <p>Description: It contains the implementation of the algorithm</p> * * * <p>Company: KEEL </p> * * @author Jose A. Saez Munoz * @version 1.0 */ import java.io.IOException; import java.util.Vector; import keel.Dataset.Attributes; import org.core.*; public class REPSO { static public myDataset train, val, test; String outputTr, outputTst, outputRules; //parameters private long semilla; private int NumParticles; private int NumAttributes; private int NumInstances; private double WeightsUpperLimit; private double maxUncoveredInstances; private double constrictionCoefficient; private int ConvergencePlatformWidth; private double vmax; private double vmin; private double w1, w2, w3; private double Interesenting; private double wmax, wmin; int maxIterations; private Crono cronometro; private Vector<Particle> ruleSet; private boolean somethingWrong = false; //to check if everything is correct. /** * Default constructor */ public REPSO(){ } /** * It reads the data from the input files (training, validation and test) and parse all the parameters * from the parameters array. * @param parameters parseParameters It contains the input files, output files and parameters */ public REPSO(parseParameters parameters) { train = new myDataset(); val = new myDataset(); test = new myDataset(); try { System.out.println("\nReading the training set: "+parameters.getTrainingInputFile()); train.readClassificationSet(parameters.getTrainingInputFile(), true); System.out.println("\nReading the validation set: "+parameters.getValidationInputFile()); val.readClassificationSet(parameters.getValidationInputFile(), false); System.out.println("\nReading the test set: "+parameters.getTestInputFile()); test.readClassificationSet(parameters.getTestInputFile(), false); } catch (IOException e) { System.err.println("There was a problem while reading the input data-sets: " + e); somethingWrong = true; } outputTr = parameters.getTrainingOutputFile(); outputTst = parameters.getTestOutputFile(); outputRules = parameters.getOutputFile(0); //Now we parse the parameters semilla = Long.parseLong(parameters.getParameter(0)); NumParticles=Integer.parseInt(parameters.getParameter(1)); WeightsUpperLimit = Double.parseDouble(parameters.getParameter(2)); maxUncoveredInstances = Double.parseDouble(parameters.getParameter(3)); constrictionCoefficient = Double.parseDouble(parameters.getParameter(4)); ConvergencePlatformWidth = Integer.parseInt(parameters.getParameter(5)); vmax = Double.parseDouble(parameters.getParameter(6)); vmin = Double.parseDouble(parameters.getParameter(7)); w1 = Double.parseDouble(parameters.getParameter(8)); w2 = Double.parseDouble(parameters.getParameter(9)); w3 = Double.parseDouble(parameters.getParameter(10)); Interesenting = Double.parseDouble(parameters.getParameter(11)); wmax = Double.parseDouble(parameters.getParameter(12)); wmin = Double.parseDouble(parameters.getParameter(13)); maxIterations = Integer.parseInt(parameters.getParameter(14)); //inicializar la semilla Randomize.setSeed(semilla); NumAttributes=train.getnInputs(); NumInstances=train.getnData(); ruleSet=new Vector<Particle>(25,10); Particle.InitializeParameters(constrictionCoefficient, WeightsUpperLimit, vmax, vmin, w1,w2,w3,Interesenting, NumAttributes); cronometro=new Crono(); } /** * It launches the algorithm */ public void execute() { if (somethingWrong) { //We do not execute the program System.err.println("An error was found, either the data-set have numerical values or missing values."); System.err.println("Aborting the program"); } else { cronometro.inicializa(); REPSO_Method(); cronometro.fin(); //Finally we should fill the training and test output files double accTrain=doOutput(val, outputTr); double accTest=doOutput(test, outputTst); PrintOutputRules(); double mediaAtts=0; for(int i=0 ; i<ruleSet.size() ; ++i) mediaAtts+=ruleSet.get(i).presentAttsBest(); mediaAtts/=ruleSet.size(); System.out.print("\n\n************************************************"); System.out.print("\nPorcertanje acierto train:\t"+accTrain); System.out.print("\nPorcertanje acierto test:\t"+accTest); System.out.print("\nNumero de reglas:\t\t"+ruleSet.size()); System.out.print("\nNumero atributos inicial:\t"+NumAttributes); System.out.print("\nMedia de atributos/regla:\t"+mediaAtts); System.out.print("\nTiempo:\t\t\t\t"+cronometro.tiempoTotal()); System.out.print("\n************************************************\n\n"); System.out.println("Algorithm Finished"); } } //********************************************************************* //***************** REPSO method ************************************** //********************************************************************* private void REPSO_Method(){ Particle bestRule; System.out.println("Total de instancias sin clasificar = "+train.noClasificadas()); for(int classChosen=train.ClasePredominante() ; train.QuedanMasInstancias(maxUncoveredInstances)&&train.NumClassesNotRemoved()>1 ; classChosen=train.ClasePredominante()){ bestRule=GetRule(classChosen); //get bestRule ruleSet.add(bestRule); //add bestRule to ruleSet EliminarInstanciasClasificadas(bestRule); //remove matched instances System.out.println("Total de instancias sin clasificar = "+train.noClasificadas()); } //add default rule Particle defaultRule=new Particle(train.ClasePredominante()); defaultRule.setAsDefaultRule(); ruleSet.add(defaultRule); //remove unnecesary rules EliminarReglasInnecesarias(); } //********************************************************************* //***************** PSO algorithm to get a rule *********************** //********************************************************************* private Particle GetRule(int classChosen){ double w; Particle[] P=new Particle[NumParticles]; Particle bestActual=new Particle(classChosen); Particle bestPrevious=new Particle(classChosen); boolean mejoraItActual; //inicializo las posiciones y velocidades aleatoriamente for(int i=0 ; i<NumParticles ; ++i){ P[i]=new Particle(classChosen); P[i].randomInitialization(); } int ItActOpt=0; int iter=0; do{ w=wmax-(((wmax-wmin)/maxIterations)*iter); mejoraItActual=false; bestActual.bestEvaluation=-1; //the first particle will be the best of the swarm at start //1) evaluar el fitness de cada particula for(int i=0 ; i<NumParticles ; ++i){ //1) evaluar P P[i].lastEvaluation=P[i].evaluation(); //2) actualizar Bp if(P[i].lastEvaluation>P[i].bestEvaluation) P[i].setB(P[i].X,P[i].lastEvaluation); //3) actualizar Bg if(P[i].isBetter(bestActual)) bestActual=P[i].cloneParticle(); } if(bestActual.isBetter(bestPrevious)) mejoraItActual=true; //2) mover cada particula a su siguiente posicion for(int i=0 ; i<NumParticles ; ++i){ P[i].updateV(bestActual,w); P[i].updateX(); } //ver si en esta iteracion se mejoro el global if(mejoraItActual) ItActOpt=0; else ItActOpt++; iter++; bestPrevious=bestActual.cloneParticle(); }while(ItActOpt<ConvergencePlatformWidth && iter<maxIterations); Particle bestParticle=bestActual.cloneParticle(); bestParticle.lastEvaluation=bestParticle.bestEvaluation; bestParticle.setX(bestParticle.B); return bestParticle; } //********************************************************************* //***************** Remove unnecesary rules *************************** //********************************************************************* private void EliminarReglasInnecesarias(){ Boolean continuar=true; //elimino si hay reglas despues de una regla por defecto continuar=false; for(int i=0 ; i<ruleSet.size() ; ++i){ if(continuar) ruleSet.remove(i--); if(!continuar && ruleSet.get(i).presentAttsBest()==0) continuar=true; } } //********************************************************************* //***************** Remove classified instances *********************** //********************************************************************* public void EliminarInstanciasClasificadas(Particle p){ for(int i=0 ; i<NumInstances ; ++i){ //si satisface la clase y el antecedente se remueve if(p.CoverInstance(train.getExample(i))&&train.getOutputAsInteger(i)==p.clase) train.setRemoved(i,true); } } //********************************************************************* //***************** To do outputs files ******************************* //********************************************************************* public void PrintOutputRules(){ String cad=""; //atributos presentes for(int i=0 ; i<ruleSet.size() ; ++i){ cad+="\n\n\nIF\t"; if(ruleSet.get(i).presentAttsBest()==0) cad+="TRUE\n\tTHEN CLASS = "+train.getOutputValue(ruleSet.get(i).clase); else{ for(int j=0 ; j<NumAttributes ; ++j){ if(ruleSet.get(i).GetAttributePresence(j)){ //obtener nombre del atributo String nombreAtt=Attributes.getInputAttribute(j).getName(); //obtener operador String operador=ruleSet.get(i).getOperator(j); //obtener valor String valor = ruleSet.get(i).getDomainValue(j); if(train.getTipo(j)==myDataset.NOMINAL) valor = Attributes.getInputAttribute(j).getNominalValue(Integer.parseInt(valor)); cad+="\t"+nombreAtt+operador+valor+"\n\tAND"; } } cad=cad.substring(0, cad.length()-4); cad+="\tTHEN CLASS = "+train.getOutputValue(ruleSet.get(i).clase); } } Fichero.escribeFichero(outputRules, cad); } /** * It generates the output file from a given dataset and stores it in a file * @param dataset myDataset input dataset * @param filename String the name of the file */ private double doOutput(myDataset dataset, String filename) { double aciertos=0; String output = new String(""); output = dataset.copyHeader(); //we insert the header in the output file //We write the output for each example for (int i = 0; i < dataset.getnData(); i++) { output += dataset.getOutputAsString(i) + " " + this.classificationOutput(dataset.getExample(i)) + "\n"; if(dataset.getOutputAsString(i).equals(this.classificationOutput(dataset.getExample(i)))) aciertos++; } Fichero.escribeFichero(filename, output); return aciertos/dataset.getnData(); } /** * It returns the algorithm classification output given an input example * @param example double[] The input example * @return String the output generated by the algorithm */ private String classificationOutput(double[] example){ String output = ""; for(int i=0 ; i<ruleSet.size() ; ++i){ //veo si coincide el antecedente if(ruleSet.get(i).CoverInstance(example)){//coincide el antecedente, devuelvo la primera clase que lo cumple output=train.getOutputValue(ruleSet.get(i).clase); return output; } } return output; } }