Commit b2729a30 authored by Bruno López Trigo's avatar Bruno López Trigo

Xa se pode cambiar a configuración do experto en atributos numéricos

parent 82807fc9
......@@ -354,6 +354,7 @@ public class ClassifierManagerImpl implements ClassifierManager {
}
try {
configFileEn = this.fmanager.getConfig(token, dataset, "en");
if (logJ48 != null && treeFileJ48 != null) {
this.treeBuilder = new TreeBuilder(logJ48, configFileEn, treeFileJ48);
this.treeBuilder.buildTree(true);
......@@ -427,6 +428,7 @@ public class ClassifierManagerImpl implements ClassifierManager {
this.mapper.writeJSON(configGl, configFileGl);
try {
configFileEn = this.fmanager.getConfig(token, dataset, "en");
if (logJ48 != null && treeFileJ48 != null) {
this.treeBuilder = new TreeBuilder(logJ48, configFileEn, treeFileJ48);
this.treeBuilder.buildTree(true);
......@@ -536,6 +538,7 @@ public class ClassifierManagerImpl implements ClassifierManager {
this.mapper.writeJSON(configGl, configFileGl);
try {
configFileEn = this.fmanager.getConfig(token, dataset, "en");
if (logJ48 != null && treeFileJ48 != null) {
this.treeBuilder = new TreeBuilder(logJ48, configFileEn, treeFileJ48);
this.treeBuilder.buildTree(true);
......
......@@ -4,6 +4,7 @@ import brunolopez.expliclas.models.Antecedent;
import brunolopez.expliclas.models.Attribute;
import brunolopez.expliclas.models.CategoricNode;
import brunolopez.expliclas.models.Classification;
import brunolopez.expliclas.models.Consequent;
import brunolopez.expliclas.models.ConsequentNode;
import brunolopez.expliclas.models.DatasetConfig;
import brunolopez.expliclas.models.Instance;
......@@ -135,6 +136,7 @@ public class TreeInterpreter {
Classification classification = new Classification();
HashMap<String, Boolean> modified = new HashMap();
ArrayList<HashMap<String, Boolean>> modifiedList = new ArrayList();
ArrayList<String> solutions = new ArrayList();
for (Map.Entry<String, Object> entry : instance.getValues().entrySet()) {
modified.put(entry.getKey(), false);
......@@ -247,8 +249,9 @@ public class TreeInterpreter {
path.add(((CategoricNode) path.get(path.size() - 1)).getChild(alternatives.get(0).getCategoricValue(att.getId())));
classification.addAntecedent(new Antecedent(att.getId() + " is " + alternatives.get(0).getCategoricValue(att.getId())));
}
if (path.get(path.size() - 1) instanceof ConsequentNode) {
if (path.get(path.size() - 1) instanceof ConsequentNode && !solutions.contains(((ConsequentNode) path.get(path.size()-1)).getConsequent().getId())) {
classification.setConsequent(((ConsequentNode) path.get(path.size() - 1)).getConsequent());
solutions.add(((ConsequentNode) path.get(path.size() - 1)).getConsequent().getId());
VisualNode treePath = this.treebuilder.buildVisualNode(new VisualNode(), this.tree, config, path);
classification.setTree(treePath);
classification.setInstance(alternatives.get(0));
......@@ -256,6 +259,10 @@ public class TreeInterpreter {
classification = new Classification();
alternatives.remove(0);
modifiedList.remove(0);
} else if(path.get(path.size() -1) instanceof ConsequentNode) {
classification = new Classification();
alternatives.remove(0);
modifiedList.remove(0);
}
}
path.clear();
......
......@@ -97,7 +97,7 @@ public class ConfusionAnalyzer {
}
public Double getConfusionBetween(int consequentA, int consequentB){
return this.matrix.getConfusion(consequentA, consequentB);
return this.matrix.getConfusion(consequentA, consequentB) * 100;
}
}
......@@ -2,6 +2,7 @@ package brunolopez.expliclas.explainer;
import brunolopez.expliclas.models.Antecedent;
import brunolopez.expliclas.models.Attribute;
import brunolopez.expliclas.models.CategoricProperty;
import brunolopez.expliclas.models.Classification;
import brunolopez.expliclas.models.Consequent;
import brunolopez.expliclas.models.DatasetConfig;
......@@ -18,13 +19,13 @@ public class InfoExtractor {
private ConfusionAnalyzer analyzer;
private GlobalConfig global;
private ArrayList<Classification> classifications;
public InfoExtractor(DatasetConfig config, File input, GlobalConfig global) throws FileNotFoundException {
this.config = config;
this.analyzer = new ConfusionAnalyzer(input);
this.global = global;
}
public InfoExtractor(DatasetConfig config, File input, GlobalConfig global, ArrayList<Classification> classifications) throws FileNotFoundException {
this.config = config;
this.analyzer = new ConfusionAnalyzer(input);
......@@ -81,19 +82,19 @@ public class InfoExtractor {
confused.add(this.config.getConsequentByPosition(i).getName());
}
return true;
} else if (cycle.size() <= this.global.getEnumLimit() && getConfusedConseqPercentage() < this.global.getConfusionParam("some")) {
} else if (cycle.size() <= this.global.getEnumLimit() && getConfusedConseqPercentage() < this.global.getConfusionParam("some")) {
for (Integer i : cycle) {
confused.add(this.config.getConsequentByPosition(i).getName());
}
return false;
} else if (cycle.size() > this.global.getEnumLimit() && getConfusedConseqPercentage() < this.global.getConfusionParam("some")) {
} else if (cycle.size() > this.global.getEnumLimit() && getConfusedConseqPercentage() < this.global.getConfusionParam("some")) {
mostConfused = this.analyzer.mostConfusedPairs(cycle);
for (Integer i : mostConfused) {
confused.add(this.config.getConsequentByPosition(i).getName());
}
return true;
} else if (getConfusedConseqPercentage() < this.global.getConfusionParam("most")) {
if ((this.config.getConsequents().size() - cycle.size()) <= this.global.getEnumLimit() ) {
if ((this.config.getConsequents().size() - cycle.size()) <= this.global.getEnumLimit()) {
for (Consequent c : this.config.getConsequents()) {
if (!cycle.contains(c.getMatrixPosition())) {
confused.add(c.getName());
......@@ -116,68 +117,80 @@ public class InfoExtractor {
}
}
public Double getConfusionBetween(ArrayList<Consequent> consequents) {
return this.analyzer.getConfusionBetween(consequents.get(0).getMatrixPosition()-1, consequents.get(1).getMatrixPosition() - 1);
return this.analyzer.getConfusionBetween(consequents.get(0).getMatrixPosition() - 1, consequents.get(1).getMatrixPosition() - 1);
}
public int getNumAlternatives() {
return this.classifications.size();
}
public HashMap<String, ArrayList<String>> getAttributeLabels(int alternative){
public HashMap<String, ArrayList<String>> getAttributeLabels(int alternative) {
HashMap<String, ArrayList<String>> list = new HashMap();
ArrayList<String> attributes;
Antecedent antecedent;
String categoricId;
for(Attribute a: this.config.getAttributes()){
for (Attribute a : this.config.getAttributes()) {
antecedent = this.classifications.get(alternative).getAntecedenById(a.getId());
if(antecedent != null){
if(antecedent.isCategoric() )
attributes = list.get(antecedent.getDecision().split(" is ")[1]);
else
attributes = list.get(this.config.getAttributeById(a.getId()).getPropertyById(antecedent.getProperty()).getName());
if(attributes == null){
attributes = new ArrayList();
attributes.add(a.getName());
if (antecedent != null) {
if (antecedent.isCategoric()) {
categoricId = antecedent.getDecision().split(" is ")[1];
attributes = list.get(((CategoricProperty)this.config.getAttributeById(a.getId()).getPropertyByName(categoricId)).getValue());
if (attributes == null) {
attributes = new ArrayList();
attributes.add(a.getName());
} else {
attributes.add(a.getName());
}
list.put(((CategoricProperty)this.config.getAttributeById(a.getId()).getPropertyByName(categoricId)).getValue(), attributes);
} else {
attributes.add(a.getName());
attributes = list.get(this.config.getAttributeById(a.getId()).getPropertyById(antecedent.getProperty()).getName());
if (attributes == null) {
attributes = new ArrayList();
attributes.add(a.getName());
} else {
attributes.add(a.getName());
}
list.put(this.config.getAttributeById(a.getId()).getPropertyById(antecedent.getProperty()).getName(), attributes);
}
list.put(this.config.getAttributeById(a.getId()).getPropertyById(antecedent.getProperty()).getName(), attributes);
}
}
return list;
}
public String getConsequent(int alternative){
public String getConsequent(int alternative) {
return this.config.getConsequentById(this.classifications.get(alternative).getConsequent().getId()).getName();
}
public String branchProbabilityHigh(int alternative){
public String branchProbabilityHigh(int alternative) {
double percentage = this.classifications.get(alternative).getConsequent().getPercentageNode();
if(percentage >= this.global.getBranchProbabilityCut())
if (percentage >= this.global.getBranchProbabilityCut()) {
return this.global.getLabelBranchFor(percentage);
}
return null;
}
public String branchProbabilityLow(int alternative){
public String branchProbabilityLow(int alternative) {
double percentage = this.classifications.get(alternative).getConsequent().getPercentageNode();
if(percentage < this.global.getBranchProbabilityCut())
if (percentage < this.global.getBranchProbabilityCut()) {
return this.global.getLabelBranchFor(percentage);
}
return null;
}
}
......@@ -40,6 +40,9 @@ public class Matrix {
for(Integer i: this.data.get(a))
sum+=i;
if(sum == 0)
return 0d;
return this.data.get(a).get(b) / sum;
}
......
=== Run information ===
Scheme: trees.J48 -C 0.25 -M 2
Relation: iris
Instances: 150
Attributes: 5
sepallength
sepalwidth
petallength
petalwidth
class
Test mode: 10-fold cross-validation
=== Classifier model (full training set) ===
J48 pruned tree
------------------
petalwidth <= 0.6: Iris-setosa (50.0)
petalwidth > 0.6
| petalwidth <= 1.7
| | petallength <= 4.9: Iris-versicolor (48.0/1.0)
| | petallength > 4.9
| | | petalwidth <= 1.5: Iris-virginica (3.0)
| | | petalwidth > 1.5: Iris-versicolor (3.0/1.0)
| petalwidth > 1.7: Iris-virginica (46.0/1.0)
Number of Leaves : 5
Size of the tree : 9
=== Summary ===
Correctly Classified Instances 144 96 %
Incorrectly Classified Instances 6 4 %
Kappa statistic 0.94
K&B Relative Info Score 14004.9837 %
K&B Information Score 221.9737 bits 1.4798 bits/instance
Class complexity | order 0 237.7444 bits 1.585 bits/instance
Class complexity | scheme 3238.3794 bits 21.5892 bits/instance
Complexity improvement (Sf) -3000.6351 bits -20.0042 bits/instance
Mean absolute error 0.035
Root mean squared error 0.1586
Relative absolute error 7.8705 %
Root relative squared error 33.6353 %
Total Number of Instances 150
=== Confusion Matrix ===
a b c <-- classified as
49 1 0 | a = Iris-setosa
0 47 3 | b = Iris-versicolor
0 2 48 | c = Iris-virginica
{
"type" : "numericNode",
"attribute" : {
"type" : "numericAtt",
"id" : "petalwidth",
"name" : "petalwidth",
"properties" : [ {
"type" : "numericProp",
"name" : "Low",
"id" : 0,
"interval" : {
"left" : 0.1,
"right" : 0.8999999999999999
}
}, {
"type" : "numericProp",
"name" : "Medium",
"id" : 1,
"interval" : {
"left" : 0.8999999999999999,
"right" : 1.7
}
}, {
"type" : "numericProp",
"name" : "High",
"id" : 2,
"interval" : {
"left" : 1.7,
"right" : 2.5
}
} ],
"interval" : {
"left" : 0.1,
"right" : 2.5
},
"value" : 0.0
},
"splitValue" : 0.6,
"comparisonSymbol" : "<=",
"leftChild" : {
"type" : "consequentNode",
"consequent" : {
"matrixPosition" : 1,
"id" : "Iris-setosa",
"name" : "Iris-setosa",
"percentageNode" : 100.0
}
},
"rightChild" : {
"type" : "numericNode",
"attribute" : {
"type" : "numericAtt",
"id" : "petalwidth",
"name" : "petalwidth",
"properties" : [ {
"type" : "numericProp",
"name" : "Low",
"id" : 0,
"interval" : {
"left" : 0.1,
"right" : 0.8999999999999999
}
}, {
"type" : "numericProp",
"name" : "Medium",
"id" : 1,
"interval" : {
"left" : 0.8999999999999999,
"right" : 1.7
}
}, {
"type" : "numericProp",
"name" : "High",
"id" : 2,
"interval" : {
"left" : 1.7,
"right" : 2.5
}
} ],
"interval" : {
"left" : 0.1,
"right" : 2.5
},
"value" : 0.0
},
"splitValue" : 1.7,
"comparisonSymbol" : "<=",
"leftChild" : {
"type" : "numericNode",
"attribute" : {
"type" : "numericAtt",
"id" : "petallength",
"name" : "petallength",
"properties" : [ {
"type" : "numericProp",
"name" : "Low",
"id" : 0,
"interval" : {
"left" : 1.0,
"right" : 2.966666666666667
}
}, {
"type" : "numericProp",
"name" : "Medium",
"id" : 1,
"interval" : {
"left" : 2.966666666666667,
"right" : 4.933333333333334
}
}, {
"type" : "numericProp",
"name" : "High",
"id" : 2,
"interval" : {
"left" : 4.933333333333334,
"right" : 6.9
}
} ],
"interval" : {
"left" : 1.0,
"right" : 6.9
},
"value" : 0.0
},
"splitValue" : 4.9,
"comparisonSymbol" : "<=",
"leftChild" : {
"type" : "consequentNode",
"consequent" : {
"matrixPosition" : 2,
"id" : "Iris-versicolor",
"name" : "Iris-versicolor",
"percentageNode" : 97.91666666666666
}
},
"rightChild" : {
"type" : "numericNode",
"attribute" : {
"type" : "numericAtt",
"id" : "petalwidth",
"name" : "petalwidth",
"properties" : [ {
"type" : "numericProp",
"name" : "Low",
"id" : 0,
"interval" : {
"left" : 0.1,
"right" : 0.8999999999999999
}
}, {
"type" : "numericProp",
"name" : "Medium",
"id" : 1,
"interval" : {
"left" : 0.8999999999999999,
"right" : 1.7
}
}, {
"type" : "numericProp",
"name" : "High",
"id" : 2,
"interval" : {
"left" : 1.7,
"right" : 2.5
}
} ],
"interval" : {
"left" : 0.1,
"right" : 2.5
},
"value" : 0.0
},
"splitValue" : 1.5,
"comparisonSymbol" : "<=",
"leftChild" : {
"type" : "consequentNode",
"consequent" : {
"matrixPosition" : 3,
"id" : "Iris-virginica",
"name" : "Iris-virginica",
"percentageNode" : 100.0
}
},
"rightChild" : {
"type" : "consequentNode",
"consequent" : {
"matrixPosition" : 2,
"id" : "Iris-versicolor",
"name" : "Iris-versicolor",
"percentageNode" : 66.66666666666666
}
}
}
},
"rightChild" : {
"type" : "consequentNode",
"consequent" : {
"matrixPosition" : 3,
"id" : "Iris-virginica",
"name" : "Iris-virginica",
"percentageNode" : 97.82608695652173
}
}
}
}
\ No newline at end of file
{
"dataset" : "example",
"attributes" : [ {
"type" : "numericAtt",
"id" : "sepallength",
"name" : "sepallength",
"properties" : [ {
"type" : "numericProp",
"name" : "Low",
"id" : 0,
"interval" : {
"left" : 4.3,
"right" : 5.5
}