/*********************************************************************** 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.Decision_Trees.DT_oblicuo; /** * * * @author Anonymous - 2011 * @version 1.0 * @since JDK1.6 */ public class Nodo { String clase; boolean isLeaf; double[] pesos; //para la combinaci�n lineal double valor, impureza; myDataset train; int ejemplos[], ejemplosI[], ejemplosD[]; int n_ejemplos, n_ejemplos_i, n_ejemplos_d, nGenerations; public Nodo() { } public Nodo(myDataset train, int n_ejemplos, int[] ejemplos, int nGenerations) { this.train = train; this.n_ejemplos = n_ejemplos; this.ejemplos = new int[ejemplos.length]; this.ejemplos = ejemplos.clone(); this.nGenerations = nGenerations; //Si todos los ejemplos son de la misma clase --> Hoja isLeaf = true; int clase = train.getOutputAsInteger(ejemplos[0]); int i; for (i = 1; (i < n_ejemplos) && (isLeaf); i++) { isLeaf = (train.getOutputAsInteger(ejemplos[i]) == clase); } pesos = new double[train.getnInputs()]; if (isLeaf) { this.clase = train.getOutputAsString(ejemplos[0]); } /*else if ( ( (n_ejemplos < 10) && (totalNodos > 25)) || (totalNodos > 50)) { //ya tengo que ir cortando no? isLeaf = true; //Clase == clase mayoritaria int clases[] = new int[train.getnClasses()]; for (i = 0; i < clases.length; i++) { clases[i] = 0; } for (i = 0; i < n_ejemplos; i++) { clases[train.getOutputAsInteger(ejemplos[i])]++; } int max = 0; for (i = 1; i < clases.length; i++) { if (clases[i] > clases[max]) { max = i; } this.clase = train.getOutputValue(max); } }*/ else { //Hay que crear un nodo con el procedimiento chungo crearNodo(); } if (this.impureza == Double.MIN_VALUE) { //No he encontrado ningun corte isLeaf = true; //Clase == clase mayoritaria int clases[] = new int[train.getnClasses()]; for (i = 0; i < clases.length; i++) { clases[i] = 0; } for (i = 0; i < n_ejemplos; i++) { clases[train.getOutputAsInteger(ejemplos[i])]++; } int max = 0; for (i = 1; i < clases.length; i++) { if (clases[i] > clases[max]) { max = i; } this.clase = train.getOutputValue(max); } } } private void crearNodo() { //Primer paso: Calcular el mejor "axis-paralel" test calculaAxisParalel(); //Segundo paso //Solo si el atributo no es nominal (si no no me vale para nada tanta parafernalia!!) int i; for (i = 0; pesos[i] != 0; i++) { ; } if (!train.esNominal(i)) { if (n_ejemplos > 2 * train.getnInputs()) { //condicion algoritmo crearHyperplane(); } } } private void calculaAxisParalel() { //Pruebo todos los posibles tests hasta encontrar el de minima impureza (greedy) //double impureza = Double.MAX_VALUE; double impureza = Double.MIN_VALUE; int atributo = 0; double mi_valor = 0; for (int i = 0; i < train.getnInputs(); i++) { for (int j = 0; j < train.totalValores(i); j++) { valor = train.valor(i, j); for (int k = 0; k < train.getnInputs(); k++) { pesos[k] = 0; } pesos[i] = -1; double imp = calculaImpureza(); if (imp > impureza) { impureza = imp; mi_valor = valor; atributo = i; //System.out.println("Escogido atributo["+atributo+"] y valor["+valor+"]: "+impureza+" ("+n_ejemplos_i+"/"+n_ejemplos_d+")"); } } } for (int k = 0; k < train.getnInputs(); k++) { pesos[k] = 0; } pesos[atributo] = -1; valor = mi_valor; calculaImpureza(); //esto solo me vale para recalcular n_ejemplos /* System.out.println("Escogido atributo[" + atributo + "] y valor[" + valor + "]: " + impureza + " (" + n_ejemplos_i + "/" + n_ejemplos_d + ")"); */ //System.out.println("FIN -> "+impureza+" ("+n_ejemplos_i+"/"+n_ejemplos_d+")"); //System.exit(0); } public boolean cubre(double[] ejemplo) { double aux = 0; for (int j = 0; j < ejemplo.length; j++) { aux += ejemplo[j] * pesos[j]; } aux += valor; return (aux >= 0); } private double calculaImpureza() { //double imp = Double.MAX_VALUE; double imp = Double.MIN_VALUE; int ejemplos_ii[], ejemplos_di[]; n_ejemplos_i = n_ejemplos_d = 0; ejemplosD = new int[n_ejemplos]; ejemplosI = new int[n_ejemplos]; ejemplos_ii = new int[train.getnClasses()]; ejemplos_di = new int[train.getnClasses()]; //calculo lo necesario for (int i = 0; i < n_ejemplos; i++) { double[] ejemplo = train.getExample(ejemplos[i]); int clase = train.getOutputAsInteger(ejemplos[i]); if (this.cubre(ejemplo)) { ejemplosI[n_ejemplos_i] = ejemplos[i]; n_ejemplos_i++; ejemplos_ii[clase]++; } else { ejemplosD[n_ejemplos_d] = ejemplos[i]; n_ejemplos_d++; ejemplos_di[clase]++; } } if ( (n_ejemplos_i > 0) && (n_ejemplos_d > 0)) { imp = 0; for (int i = 0; i < train.getnClasses(); i++) { imp += Math.abs( ( (1.0 * ejemplos_ii[i] / n_ejemplos_i) - (1.0 * ejemplos_di[i] / n_ejemplos_d))); //System.err.println("imp["+i+"]: "+imp+" ("+( (1.0 * ejemplos_ii[i] / n_ejemplos_i) - (1.0 * ejemplos_di[i] / n_ejemplos_d))+") n_i:"+ejemplos_ii[i]+", n_d:" +ejemplos_di[i]); } imp *= imp; imp *= (n_ejemplos_i * n_ejemplos_d); imp /= (1.0 * n_ejemplos * n_ejemplos); /*if (valor == 0.1){ System.err.println("impT: "+imp+" n_i:"+n_ejemplos_i+", n_d:" +n_ejemplos_d); }*/ } impureza = imp; return imp; } private void crearHyperplane() { Poblacion p = new Poblacion(train, n_ejemplos, ejemplos, this.nGenerations, pesos, valor); p.genetico(); if (p.mejor_fitness > impureza) { double[] aux = p.mejorSolucion(); for (int i = 0; i < pesos.length; i++) { pesos[i] = aux[i]; } valor = aux[aux.length - 1]; calculaImpureza(); //actualiza los valores de ejemplosD y ejemplosI } } public String printString() { String cadena = new String(""); if (isLeaf) { cadena += train.nombreVar(train.getnInputs()) + " = " + clase + " (" + n_ejemplos + ")"; } else { for (int i = 0; i < train.getnInputs(); i++) { if (pesos[i] != 0) { cadena += pesos[i] + "*" + train.nombreVar(i) + " + "; } } cadena += valor + " >= 0 "; } return cadena; } public Nodo copia() { Nodo n = new Nodo(); n.clase = this.clase; n.isLeaf = this.isLeaf; n.pesos = this.pesos.clone(); n.valor = this.valor; n.ejemplos = this.ejemplos.clone(); n.ejemplosD = this.ejemplosD.clone(); n.ejemplosI = this.ejemplosI.clone(); n.n_ejemplos = this.n_ejemplos; n.n_ejemplos_d = this.n_ejemplos_d; n.n_ejemplos_i = this.n_ejemplos_i; n.nGenerations = this.nGenerations; return n; } }