/***********************************************************************
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.Fuzzy_Rule_Learning.AdHoc.ClassifierFuzzyWangMendel;
import keel.Algorithms.Shared.Parsing.*;
import keel.Algorithms.Fuzzy_Rule_Learning.Shared.Fuzzy.*;
import org.core.*;
import java.io.*;
/**
* <p>
* ClassifierFuzzyWangMendel is intended to generate a Fuzzy Rule Based System
* (FRBS) classifier using the Wang and Mendel approach.
* Hence, the algorithm first partitions the input and the output spaces and thus
* generates a complete Rule Base (RB).
* Then, for each example in the training dataset the most compatible rule
* antecedent from the RB is found and assigned with the corresponding output
* class. Finally, this rule is chosen as a one of the FRBS rules.
* </p>
*
* <p>
* @author Written by Luciano Sanchez (University of Oviedo) 21/07/2008
* @author Modified by J.R. Villar (University of Oviedo) 19/12/2008
* @version 1.0
* @since JDK1.4
* </p>
*/
public class ClassifierFuzzyWangMendel {
//The Randomize object used in this class
static Randomize rand;
//The best suite rules
private static long [] reglas;
//The number of best suite rules
private static int numReglas;
/**
* <p>
* This private static method extract the dataset and the method's parameters
* from the KEEL environment, learns the FRBS classifier using the Wang and Mendel
* algorithm and print out the results with the validation dataset.
* </p>
* @param tty unused boolean parameter, kept for compatibility
* @param pc ProcessConfig object to obtain the train and test datasets
* and the method's parameters.
*/
private static void wangMendelFuzzyClassifier(boolean tty, ProcessConfig pc) {
try {
String linea=new String();
int default_neparticion=0;
int ncruces=0;
ProcessDataset pd=new ProcessDataset();
linea=(String)pc.parInputData.get(ProcessConfig.IndexTrain);
if (pc.parNewFormat) pd.processClassifierDataset(linea,true);
else pd.oldClusteringProcess(linea);
int ndatos=pd.getNdata(); // Number of examples
int nvariables=pd.getNvariables(); // Number of variables
int nentradas=pd.getNinputs(); // Number of inputs
pd.showDatasetStatistics();
System.out.println("Number of input data="+ndatos);
System.out.println("Number of output data="+nentradas);
double[][] X = pd.getX(); // Input data
int[] C = pd.getC(); // Output data
int nclases = pd.getNclasses(); // Number of classes
double[] emaximo = pd.getImaximum(); // Maximum and Minimum for input data
double[] eminimo = pd.getIminimum();
int[] neparticion=new int[nentradas];
pd.showDatasetStatistics();
// Partitions definition
FuzzyPartition[] particione=new FuzzyPartition[nentradas];
for (int i=0;i<nentradas;i++) {
System.out.print("Input Variable "+i+": ");
neparticion[i]=pc.parPartitionLabelNum;
particione[i]=new FuzzyPartition(eminimo[i],emaximo[i],neparticion[i]);
System.out.println(particione[i].aString());
}
System.out.print("Output Variable:");
FuzzyPartition particions=new FuzzyPartition(nclases);
System.out.println(particions.aString());
// Train results
int [] Ct=new int[C.length];
// Rule base
RuleBase sistema=
new RuleBase(particione,particions,
RuleBase.product,
RuleBase.sum);
// Wang-Mendel Algorithm
FuzzyRule [] reglas2 = new FuzzyRule[X.length];
reglas = new long[X.length];
numReglas = 0;
for (int i=0;i<X.length;i++) {
// For each example, More compatible antecedent is searched
double compatibilidad=0; long winr=0;
winr = sistema.codifyAntecents(X[i]);
double p = sistema.evaluateMembership(winr,X[i]);
// If rule was not found earlier, it's stored.
int numeroRegla = ruleSearching(winr);
if (numeroRegla == -1){
reglas[numReglas] = winr;
reglas2[numReglas] = new FuzzyRule(C[i],p);
numReglas++;
}
else if (p > reglas2[numeroRegla].weight) { //If it is better than the previous rule found
reglas2[numeroRegla].weight = p;
reglas2[numeroRegla].consequent = C[i];
}
}
// Weights are tranformed to binary code
for (int i = 0; i < numReglas; i++)
//sistema.getComponente(reglas[i]).peso = 1;
reglas2[i].weight = 1;
long [] nuevasReglas = new long[numReglas];
FuzzyRule [] nuevasReglas2 = new FuzzyRule[numReglas];
// Result is printed
for (int r = 0; r < numReglas; r++){
System.out.println(
"IF "+ sistema.variableNames(reglas[r]) + " THEN " +
//"S" + sistema.getComponente(reglas[r]).consecuente
"S" + reglas2[r].consequent
);
nuevasReglas[r] = reglas[r];
nuevasReglas2[r] = new FuzzyRule(reglas2[r].consequent,reglas2[r].weight);
}
sistema.addRules(nuevasReglas,nuevasReglas2);
// Test error
double error_clasificacion=0;
for (int i=0;i<ndatos;i++) {
double[] respuesta=sistema.myOutput(X[i]);
int ganadora=0;
for (int j=1;j<respuesta.length;j++)
if (respuesta[j]>respuesta[ganadora]) { ganadora=j; }
if (ganadora!=C[i]) error_clasificacion++;
Ct[i]=ganadora;
}
error_clasificacion/=ndatos;
System.out.println("Train error: "+ error_clasificacion);
pc.trainingResults(C,Ct);
ProcessDataset pdt = new ProcessDataset();
int nprueba,npentradas,npvariables;
linea=(String)pc.parInputData.get(ProcessConfig.IndexTest);
if (pc.parNewFormat) pdt.processClassifierDataset(linea,false);
else pdt.oldClusteringProcess(linea);
nprueba = pdt.getNdata();
npvariables = pdt.getNvariables();
npentradas = pdt.getNinputs();
pdt.showDatasetStatistics();
if (npentradas!=nentradas) throw new IOException("Test file error");
double[][] Xp=pdt.getX(); int [] Cp=pdt.getC(); int [] Co=new int[Cp.length];
// Test error
error_clasificacion=0;
for (int i=0;i<nprueba;i++) {
double[] respuesta=sistema.myOutput(Xp[i]);
int ganadora=0;
for (int j=1;j<respuesta.length;j++)
if (respuesta[j]>respuesta[ganadora]) { ganadora=j; }
if (ganadora!=Cp[i]) error_clasificacion++;
Co[i]=ganadora;
}
error_clasificacion/=nprueba;
System.out.println("Test set error: " + error_clasificacion);
pc.results(Cp,Co);
//We write in an output file the Data Base and Rule Base:
String rutaSalidaBD = (String)pc.outputData.get(0); //fichero BD
String rutaSalidaBR = (String)pc.outputData.get(1); //fichero BR
Fichero fichSalida = new Fichero();
String cad = new String("");
cad += "DATA BASE:\n";
for (int i=0;i<nentradas;i++) {
cad += "\nInput Variable "+i+": ";
cad += particione[i].aString();
}
cad += "\n\nOutput Variable:";
cad += particions.aString();
fichSalida.escribeFichero(rutaSalidaBD, cad);
cad = "RULE BASE:\n";
for (int r = 0; r < numReglas; r++){
cad += "\nRule_"+(r+1)+": IF "+ sistema.variableNames(reglas[r]) + " THEN " + "S" + reglas2[r].consequent;
}
fichSalida.escribeFichero(rutaSalidaBR, cad);
} catch(FileNotFoundException e) {
System.err.println(e+" Train not found");
} catch(IOException e) {
System.err.println(e+" Read Error");
}
}
/**
* <p>
* This private static method searchs for a certain rule in the set of best
* suite rule data base. The value -1 is returned if that rule is not in
* the rule data base.
* </p>
* @param winr the rule to be searched for.
* @return the position of the searched rule or -1 if it not found.
*/
private static int ruleSearching(long winr){
boolean salir = false;
int i;
for (i = 0; (i < numReglas)&&(!salir); i++){
salir = (winr == reglas[i]);
}
if (salir){
return (i-1);
}
return -1;
}
/**
* <p>
* This public static method runs the algorithm that this class concerns with.
* </p>
* @param args Array of strings to sent parameters to the main program. The
* path of the algorithm's parameters file must be given.
*/
public static void main(String args[]) {
boolean tty=false;
ProcessConfig pc=new ProcessConfig();
System.out.println("Reading configuration file: "+args[0]);
if (pc.fileProcess(args[0])<0) return;
int algo=pc.parAlgorithmType;
rand=new Randomize();
rand.setSeed(pc.parSeed);
ClassifierFuzzyWangMendel wm=new ClassifierFuzzyWangMendel();
wm.wangMendelFuzzyClassifier(tty,pc);
}
}