/***********************************************************************
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 Jaume Bacardit (La Salle, Ram�n Llull University - Barcelona) 28/03/2004
* @author Modified by Xavi Sol� (La Salle, Ram�n Llull University - Barcelona) 23/12/2008
* @version 1.1
* @since JDK1.2
* </p>
*/
package keel.Algorithms.Genetic_Rule_Learning.GAssist;
import keel.Algorithms.Genetic_Rule_Learning.Globals.*;
public class PerformanceAgent {
/**
* <p>
* This class computes several performance measures taken from a fitness
* computation of an individual
* </p>
*/
public static int[] utilRules;
public static int[] okClass;
public static int[] totalClass;
public static int[][] confusionMatrix;
static int numAliveRules;
static double totalInstances;
static double okInstances;
/**
* This function computes the rules of an individual that will be
* deleted by the rule deletion operator, based on their activity
* during the previous fitness computation cycle
*/
public static int[] controlBloatRuleDeletion() {
int nRules = utilRules.length;
int minRules = Parameters.ruleDeletionMinRules;
int[] rulesToDelete = new int[nRules];
int countDeleted = 0;
if (nRules > minRules) {
for (int i = 0; i < nRules; i++) {
if (utilRules[i] == 0) {
rulesToDelete[countDeleted++] = i;
}
}
if (nRules - countDeleted < minRules) {
int rulesToKeep = minRules - (nRules - countDeleted);
for (int i = 0; i < rulesToKeep; i++) {
int pos = Rand.getInteger(0, countDeleted - 1);
for (int j = pos + 1; j < countDeleted; j++) {
rulesToDelete[j - 1] = rulesToDelete[j];
}
countDeleted--;
}
}
}
int[] arrayRules = new int[countDeleted];
for (int i = 0; i < countDeleted; i++) {
arrayRules[i] = rulesToDelete[i];
}
return arrayRules;
}
public static void resetPerformance(int _numRules) {
utilRules = new int[_numRules];
for (int i = 0; i < _numRules; i++) {
utilRules[i] = 0;
}
numAliveRules = 0;
totalInstances = 0;
okInstances = 0;
}
/**
* The test stage computes more statistics. The data structures that
* hold these statistics are initialized here
*/
public static void resetPerformanceTest(int _numRules) {
utilRules = new int[_numRules];
okClass = new int[Parameters.numClasses];
totalClass = new int[Parameters.numClasses];
confusionMatrix = new int[Parameters.numClasses][];
for (int i = 0; i < _numRules; i++) {
utilRules[i] = 0;
}
for (int i = 0; i < Parameters.numClasses; i++) {
okClass[i] = totalClass[i] = 0;
confusionMatrix[i] = new int[Parameters.numClasses];
for (int j = 0; j < Parameters.numClasses; j++) {
confusionMatrix[i][j] = 0;
}
}
numAliveRules = 0;
totalInstances = 0;
okInstances = 0;
}
/**
* Function used to inform PerformanceAgent of each example
* classified during the training stage
*/
public static void addPrediction(int predicted, int real, int activatedRule) {
totalInstances++;
if (predicted != -1) {
if (utilRules[activatedRule] == 0
&& activatedRule < utilRules.length) {
numAliveRules++;
}
utilRules[activatedRule]++;
}
if (predicted == real) {
okInstances++;
}
}
/**
* Function used to inform PerformanceAgent of each example
* classified during the test stage
*/
public static void addPredictionTest(int predicted, int real,
int activatedRule) {
totalInstances++;
totalClass[real]++;
if (predicted != -1) {
if (utilRules[activatedRule] == 0
&& activatedRule < utilRules.length) {
numAliveRules++;
}
utilRules[activatedRule]++;
confusionMatrix[real][predicted]++;
}
if (predicted == real) {
okInstances++;
okClass[real]++;
}
}
public static double getAccuracy() {
return okInstances / totalInstances;
}
public static int getNumAliveRules() {
return numAliveRules;
}
public static int getActivationsOfRule(int rule) {
return utilRules[rule];
}
/**
* This function returns the fitness formula used
*/
public static double getFitness(Classifier ind) {
double fitness;
double penalty = 1;
if (numAliveRules < Parameters.sizePenaltyMinRules) {
penalty = (1 - 0.025 * (Parameters.sizePenaltyMinRules - numAliveRules));
if (penalty <= 0) {
penalty = 0.01;
}
penalty *= penalty;
}
if (Parameters.useMDL) {
fitness = Globals_MDL.mdlFitness(ind) / penalty;
}
else {
fitness = getAccuracy();
fitness *= fitness;
fitness *= penalty;
}
return fitness;
}
/**
* This function dumps the test statistics
*/
public static void dumpStats(String typeOfTest) {
LogManager.println(typeOfTest + " accuracy " + okInstances + "/" +
totalInstances + "=" + getAccuracy());
for (int i = 0; i < Parameters.numClasses; i++) {
LogManager.println(typeOfTest + " acc. in class " + i + " : " + okClass[i] +
"/" + totalClass[i] + "=" +
( (double) okClass[i] / (double) totalClass[i]));
}
LogManager.println(typeOfTest +
" confusion matrix. Rows=real, columns=predicted");
for (int i = 0; i < Parameters.numClasses; i++) {
for (int j = 0; j < Parameters.numClasses; j++) {
LogManager.print(confusionMatrix[i][j] + "\t");
}
LogManager.println("");
}
LogManager.println(typeOfTest + " activations of classifiers");
for (int i = 0; i < utilRules.length; i++) {
LogManager.println("Classifier " + i + " : " + utilRules[i]);
}
}
}