Un mio amico, o meglio conoscente, mi ha dato un suo vecchio progetto universitario che sto svolgendo per esercitarmi ma mi sono bloccato.
Viene fornito un training set, in modo particolare questo ( http://i57.tinypic.com/6zrp5v.jpg ), e lo scopo del programma è quello di restituire per il momento la stampa delle regola e altre informazioni.
Un esempio di output del programma è questo ( http://i61.tinypic.com/32zjddc.jpg ).
Veniamo ora al mio problema.
Secondo me il problema ce l'ho nel metodo che deve stabilire se un nodo è foglia oppure no. Il metodo in questione è questo:
codice:
private boolean isLeaf(Data trainingSet,int begin, int end,int numberOfExamplesPerLeaf){
boolean result = false;
if(end-begin+1 < numberOfExamplesPerLeaf) {
result = true;
}
else {
for(int i=begin; i<=end; i++) {
result = true;
if (trainingSet.getClassValue(begin) != trainingSet.getClassValue(i)) {
result = false;
break;
}
}
}
return result;
}
La traccia dava alcune dritte e cioè che un nodo è foglia se il numero di esempi addestramento che ricadono nella partizione corrente è minore di numberOfExamplesPerLeaf, oppure se tutti gli esempi addestramento che ricadono nella partizione corrente appartengono alla stessa classe.
Analizzando l'esempio di output ho potuto capire che ad esempio "Overcast" è foglia perchè il corrispondente valore di classe (l'ultima colonna del training set) contiene sempre lo stesso valore.
Il problema è che non capisco come far per analizzare tutti i valori di un determinato tipo (es. tutti gli "Overcast") per determinare se è foglia o meno.
Dico questo perchè il metodo che analizza tutto il training set l'ho pensato così:
codice:
void setSplitInfo(Data trainingSet, int beginExampleIndex, int endExampleIndex, Attribute attribute) {
SplitNode.SplitInfo object = null;
this.mapSplit = new SplitInfo[endExampleIndex+1-beginExampleIndex];
for(int i=0; i<trainingSet.getNumberOfExplanatoryAttributes(); i++) {
Attribute test = trainingSet.getExplanatoryAttribute(i);
if(test == attribute) {
for(int j=beginExampleIndex; j<=endExampleIndex; j++) {
object = new SplitNode.SplitInfo(trainingSet.getExplanatoryValue(j, i), j, j, 1);
mapSplit[j] = object;
}
}
}
cioè che ogni esempio rappresenta un elemento singolo dell'array mapSplit (array che contiene il valore del nodo, l'indice di inizio e fine nel training set e il numero di figli).
Ovviamente non sarebbe difficile accorpare gli esempi con lo stesso valore in un singolo elemento dell'array mapSplit (anche perchè prima di eseguire il metodo setSplitInfo il training set viene ordinato in base all'attributo) però successivamente non sarebbe possibile più analizzare attraverso mapSplit tutti i singoli valori del training set perchè sarebbero raggruppati...non so se ho reso l'idea.
Voi come risolvereste il problema? Diciamo che è più un problema logico piuttosto che di programmazione.
Per completezza vi ho caricato qui ( http://www.filedropper.com/decisiontree ) i sorgenti completi del progetto in modo tale che, se avete tempo, potreste provarlo per vedere come funziona anche perchè non credo di essere stato sufficientemente chiaro nella spiegazione.
Sia ben chiaro, NON voglio la soluzione da voi ma solo qualche dritta perchè DEVO arrivarci io.