/*********************************************************************** 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 Written by Rosa Venzala (University of Granada) 02/06/2008 * @author Modified by Xavi Sol� (La Salle, Ram�n Llull University - Barcelona) 16/12/2008 * @version 1.1 * @since JDK1.2 * </p> */ package keel.Algorithms.Rule_Learning.Prism; import java.io.IOException; import java.util.Arrays; import java.util.ArrayList; import java.util.Collections; import keel.Dataset.*; import java.util.*; import org.core.*; public class Prism { /** * <p> * Contents the principal methods of the Prismsd algorithm * </p> */ private Dataset train ; private Dataset test; private String ficheroSalida; private String ficheroSalidaTr; private String ficheroSalidaTst; private String [][]valores=null;private String []clases=null;private int []clasitas=null; private boolean reglaPerfecta,cubierta; private InstanceSet instancias; private String []nombre_atributos=null; private double accuracy=-1.;private double accuracy_ant=-1.; private int clase,seleccionado=0,p=0,atributo,num_cubiertas,num_correctas; private ConjReglas conjunto_reglas; private Selector s; private Complejo almacen,regla; private boolean hayContinuos = false; private ConjDatos datosTrain,datosTest; private EvaluaCalidadReglas evReg; // Para evaluar la calidad de las reglas private int muestPorClaseEval[]; private int muestPorClaseTest[]; private Instance instancia; private long seed; /** * <p> * Checks if there're sets or not. * </p> * @return OK(there're sets) or not OK */ public boolean todoBien(){ return (!hayContinuos); } public Prism(){ } /** * <p> * Constructor with all the attributes to initialize * </p> * @param ficheroTrain Train file * @param ficheroTest Test file * @param fSalidaTr Out-put train file * @param fSalidaTst Out-put test file * @param fsalida Out-put file * @param semilla seed */ public Prism(String ficheroTrain,String ficheroTest, String fSalidaTr, String fSalidaTst, String fsalida,long semilla){ ficheroSalida = fsalida;ficheroSalidaTr = fSalidaTr; ficheroSalidaTst = fSalidaTst; seed=semilla; datosTrain = new ConjDatos();//datosEval = new ConjDatos(); datosTest = new ConjDatos(); train=new Dataset();test=new Dataset(); s=new Selector(0,0,0.); conjunto_reglas=new ConjReglas(); try { Randomize.setSeed(seed); System.out.println("la semilla es "+seed); train.leeConjunto(ficheroTrain, true); test.leeConjunto(ficheroTest,false);// if (train.hayAtributosContinuos()/*|| train.hayAtributosDiscretos()*/){ System.err.println("\nPrism may not work properly with real or integer attributes.\n"); //System.exit(-1); hayContinuos = true; } if(!hayContinuos){ train.calculaMasComunes();//eval.calculaMasComunes(); test.calculaMasComunes(); datosTrain = creaConjunto(train); //Leemos los datos de entrenamiento (todos seguidos como un String)//datosEval = creaConjunto(eval); datosTest = creaConjunto(test); valores=train.getX2();//obtengo los valores nominales clases=train.getC2(); clasitas=train.getC(); /*System.out.println(train.getndatos()); System.out.println(train.getnentradas()); for(int i=0;i<train.getndatos();i++){ for(int j=0;j<train.getnentradas();j++) System.out.print(valores[i][j]); System.out.print(clases[i]);System.out.println(clasitas[i]);}*/ //COMENZAMOS EL ALGORITMO PRISM //FOR EACH CLASS C clases=train.dameClases(); int unavez=0,candidato; for(int i=0;i<train.getnclases();i++){ System.out.println("CLASE :"+clases[i]+"\n"); //initialize E to the instance set /*Cuando haya que inicializar de nuevo el conjunto de instancias no es necesario insertar aquellas que se eliminaron, sino que nos va a bastar con inicializar otra vez el conjunto mediante el fichero de entrenamiento. Por eso hay un metodo para insertar una instancia*/ train.leeConjunto(ficheroTrain,false); nombre_atributos=train.dameNombres(); instancias=train.getInstanceSet(); //While E contains instances in class C while(train.hayInstanciasDeClaseC(i)){ //Create a rule R with an empty left-hand side that predicts class C regla=new Complejo(train.getnclases()); regla.setClase(i); regla.adjuntaNombreAtributos(nombre_atributos); //esto lo hacemos solo aqui pq luego vamos quitando selectores del almacen almacen=hazSelectores(train); almacen.adjuntaNombreAtributos(nombre_atributos); do{ //FOR EACH ATTRIBUTE A NOT MENTIONED IN R, AND EACH VALUE V accuracy_ant=-1.;p=0; int seleccionados[]=new int[almacen.size()]; for(int jj=0;jj<almacen.size();jj++) seleccionados[jj]=0; System.out.println(); for(int j=0;j<almacen.size();j++){ //tenemos que quitar el selector anterior if(j>0)regla.removeSelector(s); s=almacen.getSelector(j); //if(i==0) s.print(); //CONSIDER ADDING THE CONDITION A=V TO THE LHS OF R regla.addSelector(s); accuracy=getAccuracy(i); //if(i==0) { System.out.println("correctas "+num_correctas+" cubiertas "+num_cubiertas); System.out.println("Acurracy "+accuracy); //} if( (accuracy>accuracy_ant)||((accuracy==accuracy_ant) &&(num_correctas>p)) ){ //if((accuracy==accuracy_ant) &&(num_correctas>p)){ //System.out.println("atn "+accuracy_ant); //System.out.println("ahora "+accuracy); accuracy_ant=accuracy; seleccionado=j; p=num_correctas; //si se encuentra un superior hay que quitar //todo lo q se hay ido almacenando en esta iteracion for(int jj=0;jj<almacen.size();jj++) seleccionados[jj]=0; //} } else{ if((accuracy==accuracy_ant) &&(num_correctas==p)){ seleccionados[seleccionado]=1; seleccionados[j]=1; } } } //seleccionamos uno de los seleccionados en el caso de empate int contador=0; for(int jj=0;jj<almacen.size();jj++){ if(seleccionados[jj]==1){ contador++; System.out.println("OPCION "+jj); } } if(contador>0){ candidato=Randomize.RandintClosed(1, contador); contador=0; for(int jj=0;jj<almacen.size();jj++){ if(seleccionados[jj]==1){ contador++; if(contador==candidato)seleccionado=jj; } } } System.out.println("ELEGIDO "+seleccionado); //antes hay que quitar el q metimos regla.removeSelector(s); s=almacen.getSelector(seleccionado); s.print(); //ADD A=V TO R regla.addSelector(s); /*AHORA HAY QUE QUITAR DEL ALMACEN SE SELECTORES AQUELLOS QUE HACEN REFERENCIA AL ATRIBUTO SELECCIONADO*/ //obtener el atributo del selector ganador atributo=s.getAtributo(); //se borran todos los q tengan ese atributo //System.out.println("ALMACEN");almacen.print(); almacen.removeSelectorAtributo(atributo); reglaPerfecta=perfectRule(regla,train); }while(!reglaPerfecta && (regla.size() < train.getnentradas())); System.out.println("\n"); System.out.println("\nREGLA............................................"); regla.print(); System.out.println("\n"); /*necesitamos evaluar la regla para obtener la salida del metodo para compararla con la salida esperada*/ evaluarComplejo(regla,datosTrain); //INCLUIMOS ESTA REGLA YA PARA EL CONJUNTO FINAL DE REGLAS conjunto_reglas.addRegla(regla); //REMOVE THE INSTANCES COVERED BY R FROM E //Instance instancia; /*for(int k=0;k<instancias.getNumInstances();k++){ instancia=instancias.getInstance(k); System.out.print(k+" "); instancia.print(); System.out.println(); }*/ removeInstancesCovered(i); for(int k=0;k<instancias.getNumInstances();k++){ instancia=instancias.getInstance(k); clase=instancia.getOutputNominalValuesInt(0); if(clase==i){ System.out.print(k+" "); instancia.print(); System.out.println(); } } //instancias.print(); System.out.println("\n"); }//del while }//del for de las clases //EVALUAMOS LA CALIDAD DE LAS REGLAS int [] clasesEval; clasesEval = train.getC(); muestPorClaseEval = new int[train.getnclases()]; for (int j = 0; j < train.getnclases(); j++) { muestPorClaseEval[j] = 0; for (int i = 0; i < datosTrain.size(); i++) { if (/*valorClases[j]*/j == clasesEval[i]) { muestPorClaseEval[j]++; } } } conjunto_reglas.eliminaRepetidos(1); evReg = new EvaluaCalidadReglas(conjunto_reglas, datosTrain, datosTest, muestPorClaseEval, muestPorClaseEval,clases); //GENERAMOS LA SALIDA generaSalida(); System.out.println("la semilla es "+seed); }//del if }catch (IOException e) { System.err.println("There was a problem while trying to read the dataset files:"); System.err.println("-> " + e); //System.exit(0); } } /** * <p> * Evaluation of the complex over the example's set for see witch match all the class * </p> * @param c Complex to evaluate * @param e Set of data */ private void evaluarComplejo(Complejo c, ConjDatos e) { c.borraDistrib(); for (int i = 0; i < e.size(); i++) { int cl = e.getDato(i).getClase(); if (c.cubre(e.getDato(i))) { c.incrementaDistrib(cl); } } c.calculaLaplaciano(); } /** * <p> * Returns the fraction of correct instances of the instance's set for the rule 'regla' * </p> * @param i Number of the rule * @return Fraction of correct instances of the instance's set for the rule 'regla' */ private double getAccuracy(int i){ Instance instancia; double Accuracy; num_cubiertas=0; num_correctas=0; for(int k=0;k<instancias.getNumInstances();k++){ instancia=instancias.getInstance(k); cubierta=regla.reglaCubreInstancia(instancia); if(cubierta){ num_cubiertas++; clase=instancia.getOutputNominalValuesInt(0); if(clase==i)num_correctas++; } } Accuracy=(double)num_correctas/(double)num_cubiertas; if(num_cubiertas==0)Accuracy=0; return Accuracy; } /** * <p> * Removes from the instance's set those instances that matches with the rule * </p> * @param i Numebr of the rule */ private void removeInstancesCovered(int i){ for(int k=0;k<instancias.getNumInstances();k++){ instancia=instancias.getInstance(k); /*System.out.print(k+" "); instancia.print(); System.out.println();*/ cubierta=regla.reglaCubreInstancia(instancia); if(cubierta){ // System.out.println("CUBIERTA"); clase=instancia.getOutputNominalValuesInt(0); // if(clase==i){ instancias.removeInstance(k); instancia.print(); System.out.println(); k=k-1; //} } } } /** * <p> * Calculates the necessary statistical data and creates KEEL out-put files * </p> */ private void generaSalida() { Fichero f = new Fichero(); String cad = ""; String miSalida = new String(""); miSalida = train.copiaCabeceraTest(); //System.out.println("\n Estas son las reglas encontradas:"); //conjReglasFinal.print(); conjunto_reglas.adjuntaNombreClases(clases); conjunto_reglas.adjuntaNombreClase(nombre_atributos[train.getnentradas()]); cad = conjunto_reglas.printString(); /*cad += "\n\n" + evReg.printString() + "\n\n Time (seconds); " + (tiempo / 1000);*/ f.escribeFichero(ficheroSalida, cad); f.escribeFichero(ficheroSalidaTr, miSalida + evReg.salida(datosTrain)); f.escribeFichero(ficheroSalidaTst, miSalida + evReg.salida(datosTest)); } /** * <p> * Creates a set of data(attribute/class) * </p> * @param mis_datos Must be a set of data readen from the file (see doc Dataset.java) * @return The set of data created, a list of examples (see ConjDatos.java and Muestra.java) */ private ConjDatos creaConjunto(Dataset mis_datos) { ConjDatos datos = new ConjDatos(); //Creo un nuevo conjunto de datos int tam = mis_datos.getnentradas(); //Pillo el nmero de atributos de entrada (suponemos una sola salida [clase]) double[] vars = new double[tam]; //Creamos el vector que guardar�los valores de los atributos (aun siendo enteros o enum) double[][] X; int[] C; int clase = 0; //Variable que contendr�el valor para la clase X = mis_datos.getX(); C = mis_datos.getC(); for (int i = 0; i < mis_datos.getndatos(); i++) { //System.out.print("\n"+i+":"); for (int j = 0; (j < tam); j++) { //System.out.print(" "+X[i][j]); if (mis_datos.isMissing(i, j)) { vars[j] = mis_datos.masComun(j); } else { //CAMBIAR POR OTROS METODOS DE MANEJO DE VALORES PERDIDOS (15-NN). vars[j] = X[i][j]; //Double.parseDouble(mis_datos.getDatosIndex(i, j)); //pillo el valor del atributo j para el ejemplo i } } //if (!salir) { clase = C[i]; //Integer.parseInt(mis_datos.getDatosIndex(i, tam)); Muestra m = new Muestra(vars, clase, tam); //Creo un nuevo dato del conjunto con sus variables, su clase y el num variables m.setPosFile(i); datos.addDato(m); //} } return datos; } /** * <p> * Returns True if the rule is perfect for the data set. * </p> */ public boolean perfectRule(Complejo regla,Dataset train){ ConjDatos datosTrain; datosTrain=new ConjDatos(); datosTrain=creaConjunto(train); boolean perfecta=false; /*Muestra m = datosTrain.getDato(3);//la primera instancia basicamente System.out.println(m.getClase());*/ Muestra m; ConjDatos cubiertas; cubiertas=new ConjDatos(); /*todas las instancias que cubra la regla las metemos en un conjunto*/ for(int i=0;i<train.getndatos();i++){ m=datosTrain.getDato(i); if(regla.cubre(m)){ cubiertas.addDato(m); } } /*perfecta sera true si todos los ejemplos del conjunto 'cubiertas' tienen la misma clase que predice la regla*/ for(int i=0;i<cubiertas.size();i++){ if(cubiertas.getDato(i).getClase()!=regla.getClase()){perfecta=false;return perfecta;} else perfecta=true; } return perfecta; } /** * <p> * Creates the total selector's set for get all the possible rules * </p> */ private Complejo hazSelectores(Dataset train) { Complejo almacenSelectores; int nClases=train.getnclases(); almacenSelectores = new Complejo(nClases); //Aqui voy a almacenar los selectores (numVariable,operador,valor) Attribute []atributos=null; int num_atributos,type; Vector nominalValues; atributos=Attributes.getAttributes(); num_atributos=Attributes.getNumAttributes(); Selector s; for(int i=0;i<train.getnentradas();i++){ type=atributos[i].getType(); switch (type){ case 0://NOMINAL nominalValues=atributos[i].getNominalValuesList(); //System.out.print("{"); for (int j=0; j<nominalValues.size(); j++){ //System.out.print ((String)nominalValues.elementAt(j)+" "); s = new Selector(i, 0,(String)nominalValues.elementAt(j),true); //[atr,op,valor] //incluimos tb los valores en double para facilitar algunas funciones s.setValor((double)j); almacenSelectores.addSelector(s); //s.print(); } //System.out.println("}"); break; } //System.out.println(num_atributos); } return almacenSelectores; } }