/***********************************************************************
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/
**********************************************************************/
/**
*
* File: LBR.java
*
* The LBR Algorithm.
* A Lazy Approach of the Naive Bayes Classifier. It tries to find
* the optimal subset of features and instances to use to build an
* ad-hoc NB Classifier for each testing instance.
*
* @author Written by Joaqu�n Derrac (University of Granada) 13/11/2008
* @version 1.0
* @since JDK1.5
*
*/
package keel.Algorithms.Lazy_Learning.LBR;
import keel.Algorithms.Lazy_Learning.LazyAlgorithm;
import keel.Algorithms.Lazy_Learning.Statistics;
public class LBR extends LazyAlgorithm{
int [] query;
private static final double SIGVALUE = 0.05;
/**
* The main method of the class
*
* @param script Name of the configuration script
*
*/
public LBR (String script) {
readDataFiles(script);
//Naming the algorithm
name="LBR";
//Inicialization of auxiliar structures
BayesianC.setNClasses(nClasses,inputAtt);
BayesianC.setNumValues();
for(int i=0;i<inputAtt;i++){
BayesianC.setNumValue(train.getAttributeDefinitions().getInputAttribute(i).getNumNominalValues(),i);
}
//Initialization stuff ends here. So, we can start time-counting
setInitialTime();
} //end-method
/**
* Reads configuration script, to extract the parameter's values.
*
* @param script Name of the configuration script
*
*/
protected void readParameters (String script) {
//No parameters to read in this algorithm
} //end-method
/**
* Evaluates a instance to predict its class.
*
* @param example Instance evaluated
* @return Class predicted
*
*/
protected int evaluate (double example[]) {
int output=-1;
boolean finished;
BayesianC classifier;
int tempError;
int bestError;
int bestAtt;
int oldError;
finished=false;
createQuery(example);
//create the initial classifier
classifier=new BayesianC(trainData,trainOutput);
classifier.calcProbabilities();
//get Loo error
classifier.doLeaveOneOut();
while(!finished){
bestError=Integer.MAX_VALUE;
bestAtt=-1;
//Find the attribute with lesser error.
for(int i=0;i<query.length;i++){
tempError=classifier.tempClassifier(i,query[i]);
if(bestError>=tempError){
bestError=tempError;
bestAtt=i;
}
}
if(bestAtt!=-1){
oldError=classifier.getOldError(bestAtt,query[bestAtt]);
//Test if the attribute selected reduces significatively the error
if( (classifier.looError()>(bestError+oldError))&&(statTest(bestError,bestError+oldError)<=SIGVALUE)){
//prune the train set
classifier.prune(bestAtt,query[bestAtt]);
classifier.doLeaveOneOut();
//prune the query
pruneQuery(bestAtt);
}
else{
//If differences are not significative, finish
finished=true;
}
}
else{
//If no attribute reduces the error
finished=true;
}
}
//Classify the initial query
output=classifier.classify(query);
return output;
} //end-method
/**
* Creates the query in integer representation
*
* @param example Instance evaluated
*
*/
private void createQuery(double [] example){
query=new int [example.length];
for(int i=0;i<example.length;i++){
query[i]=(int)(example[i]*(double)(BayesianC.getNumValue(i)-1));
}
} //end-method
/**
* Prunes the query, erasing the attribute selected
*
* @param attribute Attribute to be pruned
*
*/
private void pruneQuery(int bestAtt){
int [] newQuery;
newQuery=new int [query.length-1];
System.arraycopy(query, 0, newQuery, 0, bestAtt);
if(bestAtt!=query.length-1){
System.arraycopy(query, bestAtt+1, newQuery, bestAtt,query.length-(bestAtt+1));
}
query=new int [newQuery.length];
System.arraycopy(newQuery, 0, query, 0, newQuery.length);
} //end-method
/**
* Performs a statistical test to decide if new error rate
* is significatively lower than old error rate
*
* @param errorsNew New error rate
* @param errorsOld Old error rate
*
* @return P-Value obtained
*
*/
private double statTest(int errorsNew,int errorsOld){
binomP((double)errorsNew, (double)(errorsNew+ errorsOld), 0.5 );
return 0.0;
} //end-method
/**
* Performs a binomial test
*
* @param r R value
* @param n N Value
* @param p Probability
*
* @return P-Value obtained
*
*/
public double binomP(double r, double n, double p){
if (n == r) return 1.0;
return Statistics.incompleteBeta(n-r, r+1.0, 1.0-p);
} //end-method
} //end-class