/***********************************************************************
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.PSOLDA;
/**
* <p>Title: Algorithm PSOLDA</p>
*
* <p>Description: It contains the implementation of the algorithm PSOLDA</p>
*
*
* <p>Company: KEEL </p>
*
* @author Jose A. Saez Munoz
* @version 1.0
*/
import java.io.IOException;
import org.core.*;
import keel.Dataset.*;
public class PSOLDA{
myDataset train, val, test;
String outputTr, outputTst, outputFunctions;
//parameters
private long semilla;
private int maxIterations;
private int NumParticles;
private int NumAttributes;
private int NumInstances;
private int IterationsNonImproving;
private double vmax;
private int numClasses;
private double cognitiveWeight;
private double socialWeight;
private double inertiaFactor;
private Particle BestParticle;
private AD BestLDA;
private Crono cronometro;
private boolean somethingWrong = false; //to check if everything is correct.
/**
* Default constructor
*/
public PSOLDA() {
}
/**
* 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 PSOLDA(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();
outputFunctions = parameters.getOutputFile(0);
//Now we parse the parameters
semilla = Long.parseLong(parameters.getParameter(0));
maxIterations=Integer.parseInt(parameters.getParameter(1));
IterationsNonImproving = Integer.parseInt(parameters.getParameter(2));
NumParticles=Integer.parseInt(parameters.getParameter(3));
vmax = Double.parseDouble(parameters.getParameter(4));
cognitiveWeight = Double.parseDouble(parameters.getParameter(5));
socialWeight = Double.parseDouble(parameters.getParameter(6));
inertiaFactor = Double.parseDouble(parameters.getParameter(7));
//inicializar parametros
cronometro=new Crono();
Randomize.setSeed(semilla);
NumAttributes=train.getnInputs();
NumInstances=train.getnData();
numClasses=train.getnClasses();
Particle.InitializeParameters(cognitiveWeight, socialWeight, inertiaFactor, vmax);
}
/**
* 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 {
//We do here the algorithm's operations
train.normalize();
val.normalize();
test.normalize();
cronometro.inicializa();
PSOSLDA_Method();
cronometro.fin();
//Finally we should fill the training and test output files
double accTrain=doOutput(this.val, this.outputTr);
double accTest=doOutput(this.test, this.outputTst);
PrintOutputFunctions();
//get original results for LDA to compare
AD ldaAux=LDA_Method(train.getX());
double accTrainLDA=trainAccuracyRate(train.getX(), ldaAux);
double accTestLDA=testAccuracyRate(test.getX(), ldaAux);
System.out.print("\n\n************************************************");
System.out.print("\nLDA\t=> Porcertanje acierto train:\t"+accTrainLDA);
System.out.print("\nLDA\t=> Porcertanje acierto test:\t"+accTestLDA);
System.out.print("\nLDA\t=> Numero de atributos inicial:\t"+NumAttributes);
System.out.print("\nPSOLDA\t=> Porcertanje acierto train:\t"+accTrain);
System.out.print("\nPSOLDA\t=> Porcertanje acierto test:\t"+accTest);
System.out.print("\nPSOLDA\t=> Numero de atributos final:\t"+BestParticle.presentAttsBest());
System.out.print("\nPSOLDA\t=> Tiempo:\t\t\t"+cronometro.tiempoTotal());
System.out.print("\n************************************************\n\n");
System.out.println("Algorithm Finished");
}
}
//*********************************************************************
//***************** PSOLDA Method *************************************
//*********************************************************************
private void PSOSLDA_Method(){
AD lda;
Particle[] P=new Particle[NumParticles];
Particle bestActual=new Particle(NumAttributes);
Particle bestPrevious=new Particle(NumAttributes);
double[][] ctoTrain, ctoTest;
boolean mejoraItActual;
//inicializo las posiciones y velocidades aleatoriamente
for(int i=0 ; i<NumParticles ; ++i){
P[i]=new Particle(NumAttributes);
P[i].randomInitialization();
}
int iter=0;
int ItActOpt=0;
do{
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){
//si tiene algun atributo...
if(P[i].presentAttsActual()>0){
// a) obtener discrimanantes con train y Pi
ctoTrain=train.removeAttributes(P[i].X, P[i].presentAttsActual());
lda=LDA_Method(ctoTrain);
// b) calcular sobre test el fitness que se asigna a la particula
ctoTest=test.removeAttributes(P[i].X, P[i].presentAttsActual());
P[i].lastEvaluation=testAccuracyRate(ctoTest,lda);
}
//si no tiene atributos...
else
P[i].lastEvaluation=-1;
//2) actualizar Bp
if(P[i].lastEvaluation>P[i].bestEvaluation)
P[i].setB(P[i].X,P[i].lastEvaluation, P[i].presentAttsActual());
else if(P[i].lastEvaluation==P[i].bestEvaluation && P[i].presentAttsActual()<P[i].presentAttsBest())
P[i].setB(P[i].X,P[i].lastEvaluation, P[i].presentAttsActual());
//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);
P[i].updateX();
}
//ver si en esta iteracion se mejoro el global
if(mejoraItActual)
ItActOpt=0;
else
ItActOpt++;
bestPrevious=bestActual.cloneParticle();
}while(++iter<maxIterations&&ItActOpt<IterationsNonImproving);
//en bestActual tengo la mejor particula, ahora aplico LDA con bestP
ctoTrain=train.removeAttributes(bestActual.B, bestActual.presentAttsBest());
lda=LDA_Method(ctoTrain);
BestParticle=bestActual.cloneParticle();
BestLDA=lda;
}
//*********************************************************************
//***************** LDA Method ****************************************
//*********************************************************************
private AD LDA_Method(double[][] ctoTrain){
double[][] X = ctoTrain; // Input data
// marco con 1 la clase de cada instancia
double Cbin[][] = new double[NumInstances][numClasses];
for (int i=0;i<NumInstances;i++)
Cbin[i][train.getOutputAsInteger(i)]=1;
//creo las funciones discrimantes
AD adlin = new AD(X,Cbin);
try {
adlin.CalculaParametros(); //esto calcula los discriminates
}catch (Exception e){}
return adlin;
}
//*********************************************************************
//***************** Computes test accuracy ****************************
//*********************************************************************
private double testAccuracyRate(double[][]ctoTest, AD lda){
double[][] X = ctoTest; // Input data
double aciertos=0;
try{
for(int i=0 ; i<test.getnData() ; i++){
double[] resp=lda.distancias(X[i]); //esto devuelve el resultado de cada discrimante para la instancia dada
int clase=lda.argmax(resp); //esto devuelve la posicion del maximo discriminante
if (clase==test.getOutputAsInteger(i))
aciertos++;
}
}catch(Exception e){}
return aciertos/test.getnData();
}
//*********************************************************************
//***************** Computes train accuracy ***************************
//*********************************************************************
private double trainAccuracyRate(double[][]ctoTrain, AD lda){
double[][] X = ctoTrain; // Input data
double aciertos=0;
try {
for(int i=0 ; i<train.getnData() ; i++){
double[] resp=lda.distancias(X[i]); //esto devuelve el resultado de cada discrimante para la instancia dada
int clase=lda.argmax(resp); //esto devuelve la posicion del maximo discriminante
if (clase==train.getOutputAsInteger(i))
aciertos++;
}
}catch (Exception e){}
return aciertos/train.getnData();
}
//*********************************************************************
//***************** To do the output files ****************************
//*********************************************************************
public void PrintOutputFunctions(){
String cad="Warning: Examples should be standardized in the interval [0,1] to use these functions\n\n";
cad+="Selected attributes = {";
//atributos presentes
for(int i=0 ; i<NumAttributes; ++i)
if(BestParticle.B[i]>0.5)
cad+=Attributes.getInputAttribute(i).getName()+", ";
cad=cad.substring(0, cad.length()-2);
cad+="}\n\n";
String coef[]=new String[numClasses];
try{
coef=BestLDA.Coeficientes();
}catch(Exception e){}
for(int i=0 ; i<numClasses ; ++i){
cad+="-----------------------------------------------------\n";
cad+="Discriminant function for class "+ train.getOutputValue(i) + "\n"+coef[i];
}
Fichero.escribeFichero(outputFunctions, 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++) {
//for classification:
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 = "";
double[] resp=null;
//quitar atributos de example
double[] exampleAux=new double[BestParticle.presentAttsBest()];
int pos=0;
for(int i=0 ; i<NumAttributes ; ++i)
if(BestParticle.B[i]>0.5){
exampleAux[pos]=example[i];
pos++;
}
try {
resp=BestLDA.distancias(exampleAux); //esto devuelve el resultado de cada discrimante para la instancia dada
}catch (Exception e){}
int clase=BestLDA.argmax(resp); //esto devuelve la posicion del maximo discriminante
output=train.getOutputValue(clase);
return output;
}
}