Commit e1663488 authored by lafabregue's avatar lafabregue

fix merge with new constrained samarah

parents b230db4b ee095199
......@@ -33,9 +33,11 @@ import multiCube.tools.util.exceptions.MethodNotImplementedException;
* hybride (methode Samarah).
* </p>
*
* Implementation progressable avec liste de sous-processus progressables à suivre par Jean-Noël Balanche
*
* @author WEMMERT Cedric
*
* Implementation progressable avec liste de sous-processus progressable à suivre par Jean-Noël Balanche
*
*/
public abstract class Classification extends Observable implements
......@@ -146,21 +148,6 @@ public abstract class Classification extends Observable implements
this.clusteringResult = _result;
}
/**
* <p>
* Methode de calcul de la distance entre deux classes.
* </p>
*
* @param k1
* le numero de la premiere classe
* @param k2
* le numero de la seconde classe
* @return la distance entre la classe k1 et k2
*/
public double centroidsDistance(final int k1, final int k2) {
return this.getClusteringResult().centroidsDistance(k1, k2);
}
/**
* <p>
* Methode creant le resultat de classification :
......@@ -175,25 +162,6 @@ public abstract class Classification extends Observable implements
@Override
abstract public Object clone();
/**
* <p>
* Methode de calcul de la distance entre un objet et une classe.
* </p>
*
* @param object
* l'objet
* @param k
* le numero de la classe
* @return la distance entre l'objet object et la classe k
*/
public double distance(final int object, final int k) {
final Data data = this.getData();
final ClusteringResult result = this.getClusteringResult();
final Cluster clusterK = result.getCluster(k);
return clusterK.distance(data.getDataObject(object));
}
/**
* <p>
* Methode d'acces aux methodes de classification.
......@@ -217,120 +185,6 @@ public abstract class Classification extends Observable implements
return this.clusteringResult;
}
/**
* <p>
* Methode renvoyant un texte descriptif de la comparaison entre un resultat
* donne en parametre et le resultat courant.
* </p>
*
* @param matrix
* la matrice diagonalisee de comparaison
* @param som
* la matrice de confusion entre les deux resultats
* @param res
* le resultat a comparer
* @return un texte en HTML decrivant la qualite et la comparaison des
* resultats
*/
public String getComparisonInfos(final double[][] matrix,
final int[][] som, final ClusteringResult res) {
String texte = "<html>";
final int nbClassesReal = res.getNbClusters();
// meilleure somme de pixel classe pour chaque classe
final int[] best = new int[nbClassesReal];
// classes qui correspondent le mieux aux classes reels -1 si aucune
final int[] clas = new int[nbClassesReal];
Arrays.fill(clas, -1);
/** @todo revoir le calcul et les statistiques qu'on veut afficher... */
for (int i = 1; i < matrix.length - 1; i++) {
int ind = 0;
double max = 0;
boolean great = true;
// on cherche le max de la ligne
for (int j = 1; j < matrix[0].length - 1; j++) {
if (matrix[i][j] > max) {
max = matrix[i][j];
ind = j;
}
}
// on regarde si s'est le max de la colonne
for (int j = 1; j < matrix.length - 1; j++) {
if (matrix[j][ind] > max) {
great = false;
}
}
if (great) {
best[ind - 1] = som[i - 1][ind - 1];
clas[ind - 1] = i - 1;
}
}
int max = 0;
for (final int element : best) {
max += element;
}
final NumberFormat nf2 = NumberFormat.getInstance();
nf2.setMaximumFractionDigits(2);
texte += "<h3>Information</h3>";
texte += "<hr>";
texte += "<p>Nb attributes : "
+ this.getData().getOneDataObject().getNbAttributes() + "</p>";
texte += "<p>Nb objects" + " : " + this.getData().getNbObjects()
+ "</p>";
texte += "<p>" + "Nb match" + " : " + "</p>";
texte += "<ul>";
for (int i = 0; i < nbClassesReal; i++) {
if (clas[i] != -1) {
texte += "<li>"
+ res.getLegend(i)
+ " : "
+ best[i]
+ "/"
+ res.getCard(i)
+ " "
+ (int) (((double) best[i] / (double) res.getCard(i)) * 100)
+ "% (" + this.getClusteringResult().getLegend(clas[i])
+ ") </li>";
} else {
texte += "<li>" + res.getLegend(i) + " : " + best[i] + "/"
+ res.getCard(i) + " (None)" + "</li>";
}
}
texte += "</ul>";
texte += "<hr>";
final int percent = (int) (((double) max / (double) this.getData()
.getNbObjects()) * 100.0);
texte += "<p>" + "Nb well classified" + " : " + max + " (" + percent
+ "%)</p>";
final ClusteringQuality evaluation = this.getClusteringResult()
.evaluate();
texte += "<table>";
for (int i = 0; i < evaluation.getNbAccuracyIndices(); i++) {
final QualityIndex qualityIndex = evaluation.getAccuracyIndex(i);
texte += "<tr><td>" + qualityIndex.getName()
+ "</td><td>:</td><td>"
+ nf2.format(qualityIndex.getValue()) + "</td></tr>";
}
texte += "</table>";
texte += "</html>";
return texte;
}
/**
* <p>
* Accesseur aux donnees de la classification.
......
......@@ -5,6 +5,8 @@ import java.io.Serializable;
import jcl.data.Data;
import jcl.data.DataObject;
import jcl.data.distance.DistanceModel;
import jcl.data.distance.DistanceParameter;
import jcl.weights.Weights;
import multiCube.tools.util.exceptions.MethodNotImplementedException;
......@@ -84,43 +86,21 @@ abstract public class Cluster implements Serializable {
/**
* <p>
* Euclidean distance from the center of the class and an object.
* Distance from the center of the class and an object.
* </p>
*
* @param o
* the object
* the object
* @param model
* the model used to compute the distance
* @param parameters
* the list of parameters used by the distance model
* @return the distance between the center and o
*/
public double distance(final DataObject o) {
return this.clusterCenter.distance2(o, this.weights);
public double distance(final DataObject o, DistanceModel model, DistanceParameter[] parameters) {
return this.clusterCenter.distance(o, model, parameters);
}
/**
* <p>
* Weighted distance from the center of the class and an object.
* </p>
*
* @param o
* the object
* @param weights
* a weight vector
* @return the distance between the center and oo
*/
public double distance(final DataObject o, final Weights weights) {
return this.clusterCenter.distance(o, weights);
}
/**
* <p>
* Distance entre le centre de la classe et un objet de la classe.
* </p>
*
* @param o
* index de l'objet de la classe
* @return la distance entre le centre le o-ieme objet de la classe
*/
abstract public double distance(final int o);
/**
* <p>
* Cardinal de la classe.
......
......@@ -11,6 +11,8 @@ import javax.swing.tree.DefaultMutableTreeNode;
import jcl.data.Data;
import jcl.data.DataObject;
import jcl.data.distance.DistanceModel;
import jcl.data.distance.DistanceParameter;
import jcl.evaluation.clustering.ClusteringQuality;
import jcl.learning.LearningResult;
import jcl.learning.methods.ClassifierUtils;
......@@ -167,14 +169,25 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
return res;
}
private DefaultMutableTreeNode construireArbreAHC(final Agglomerate agglo) {
/**
* (méthode récursive) Le but de cette méthode est de convertir une
* structure d'arbre contenue dans les objets de type Agglomerate vers
* une structure d'arbre standard de type DefaultMutableTreeNode.
*
* pour cela, on balaye le premier arbre en profondeur
*
* @param agglo
*
* @param model
* the model used to compute the distance
* @param parameters
* the list of parameters used by the distance model
* @return the result sub-tree node
*/
private DefaultMutableTreeNode construireArbreAHC(final Agglomerate agglo,
DistanceModel model, DistanceParameter[] parameters) {
/*
* (méthode récursive) Le but de cette méthode est de convertir une
* structure d'arbre contenue dans les objets de type Agglomerate vers
* une structure d'arbre standard de type DefaultMutableTreeNode.
*
* pour cela, on balaye le premier arbre en profondeur
*/
DefaultMutableTreeNode res;
Cluster tmpCluster;
......@@ -189,8 +202,8 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
res = new DefaultMutableTreeNode(tmpCluster);
res.add(this.construireArbreAHC(agglo.getSubAgglomerate1()));
res.add(this.construireArbreAHC(agglo.getSubAgglomerate2()));
res.add(this.construireArbreAHC(agglo.getSubAgglomerate1(), model, parameters));
res.add(this.construireArbreAHC(agglo.getSubAgglomerate2(), model, parameters));
tmpCluster.setColor(new Color(r.nextInt(255), r.nextInt(255), r
.nextInt(255)));
......@@ -201,7 +214,7 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
Cluster associatedCluster = null;
for (int i = 0; i < this.clusters.length; i++) {
if (this.clusters[i].distance(agglo.getCenter(), null) == 0) {
if (this.clusters[i].distance(agglo.getCenter(), model, parameters) == 0) {
associatedCluster = this.clusters[i];
break;
}
......@@ -219,24 +232,6 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
return res;
}
/**
* <p>
* Distance objet-centre.
* </p>
*
* @param k1
* l'index d'un centre
* @param k2
* l'index de l'autre centre
* @return renvoie la distance entre le k1-ieme centre et le k2-ieme
*/
public double centroidsDistance(final int k1, final int k2) {
return this.clusters[k1].getClusterCenter().distance(
this.clusters[k2].getClusterCenter(),
new Weights(this.clusters[k1].getData(true).getOneDataObject()
.getNbAttributes()));
}
/**
* <p>
* Methode de clonage du resultat.
......@@ -298,11 +293,15 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
* Evaluation de la qualite du resultat.
* </p>
*
* @param model
* the model used to compute the distance
* @param parameters
* the list of parameters used by the distance model
* @return la qualite de ce resultat
*/
public ClusteringQuality evaluate() {
public ClusteringQuality evaluate(DistanceModel model, DistanceParameter[] parameters) {
if (this.clusteringQuality == null) {
this.clusteringQuality = new ClusteringQuality(this);
this.clusteringQuality = new ClusteringQuality(this, model, parameters);
}
return this.clusteringQuality;
}
......@@ -655,10 +654,15 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
* Methode renvoyant une representation sous forme d'arbre du resultat.
* </p>
*
* @param model
* the model used to compute the distance
* @param parameters
* the list of parameters used by the distance model
*
* @return la racine de l'arbre
*/
public DefaultMutableTreeNode getRoot() {
this.initClusterTree();
public DefaultMutableTreeNode getRoot(DistanceModel model, DistanceParameter[] parameters) {
this.initClusterTree(model, parameters);
return this.clusterTree;
}
......@@ -767,7 +771,14 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
return result;
}
private void initClusterTree() {
/**
*
* @param model
* the model used to compute the distance
* @param parameters
* the list of parameters used by the distance model
*/
private void initClusterTree(DistanceModel model, DistanceParameter[] parameters) {
// TODO: corriger la façon d'accéder aux données de cluster (nouveau
// cluster)
DefaultMutableTreeNode node;
......@@ -791,7 +802,7 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
if (this.hierarchy != null) {
// une hiérarchie a été obtenue grâce à AHC.
this.clusterTree.add(this.construireArbreAHC(this.hierarchy));
this.clusterTree.add(this.construireArbreAHC(this.hierarchy, model, parameters));
} else {
// pas de hiérarchie.
for (final Cluster element : this.clusters) {
......@@ -994,7 +1005,7 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
* a set of colors associated to the clusters, null if auto generated
*
*/
static public ClusteringResult gerenerateDefaultClusteringResult(final LearningResult learning,
static public ClusteringResult generateDefaultClusteringResult(final LearningResult learning,
final int clusterMap[], final double membershipDegree[][],
ClassificationWeights weights, final int nbClusters,
double proba[], final Data data, final int qualityCriteria[], List<Color> colors) {
......@@ -1030,7 +1041,7 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
final int clusterMap[], final double membershipDegree[][],
final ClassificationWeights weights, final int nbClusters,
final Data data, final int qualityCriteria[], List<Color> colors) {
return gerenerateDefaultClusteringResult(learning, clusterMap, membershipDegree, weights, nbClusters, null,
return generateDefaultClusteringResult(learning, clusterMap, membershipDegree, weights, nbClusters, null,
data, qualityCriteria, colors);
}
......@@ -1060,7 +1071,7 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
static public ClusteringResult gerenerateDefaultClusteringResult(final LearningResult learning,
final int clusterMap[], final ClassificationWeights weights,
final int nbClusters, final Data data, final int qualityCriteria[], List<Color> colors) {
return gerenerateDefaultClusteringResult(learning, clusterMap, null, weights, nbClusters, null, data,
return generateDefaultClusteringResult(learning, clusterMap, null, weights, nbClusters, null, data,
qualityCriteria, colors);
}
......@@ -1092,7 +1103,7 @@ public abstract class ClusteringResult implements Serializable, MemoryFlush {
final int clusterMap[], final ClassificationWeights weights,
final int nbClusters, final Data data, final int associed[],
final int qualityCriteria[], List<Color> colors) {
ClusteringResult result = gerenerateDefaultClusteringResult(learning, clusterMap, null, weights, nbClusters, null, data,
ClusteringResult result = generateDefaultClusteringResult(learning, clusterMap, null, weights, nbClusters, null, data,
qualityCriteria, colors);
result.associatedTo = new int[associed.length];
for (int i = 0; i < associed.length; i++) {
......
......@@ -110,12 +110,6 @@ public class LightCluster extends Cluster {
return new LightCluster(this);
}
@Override
public double distance(int o) {
return clusterCenter.distance(result.getData().getWholeDataDataObject(o),
weights);
}
@Override
public int getCard() {
return cardinal;
......
......@@ -40,9 +40,6 @@ public class SimpleCluster extends Cluster {
super(cluster);
this.data = (Data) cluster.data.clone();
if (cluster.clusterCenter == null) {
this.clusterCenter = this.computeCenter();
}
this.membershipDegree = new double[cluster.membershipDegree.length];
for (int i = 0; i < this.membershipDegree.length; i++) {
try {
......@@ -54,82 +51,6 @@ public class SimpleCluster extends Cluster {
this.membershipProbabilityEM = cluster.membershipProbabilityEM;
}
/**
* <p>
* Constructeur. (principal)
* </p>
*
* @param data
* l'ensemble de donnees d'o� est extraite la classe
* @param clusterMap
* la carte de classification
* @param k
* l'index de la classe
* @param weights
* le vecteur de poid associe a la classe
* @param membershipDegree
* le degre d'appartenance de tous les objets a la classe
* @param proba
* probabilite qu'un objet appartienne a cette classe
* @param result
* the parent result of the cluster
*/
public SimpleCluster(final Data data, final int clusterMap[], final int k,
final Weights weights, final double membershipDegree[],
final double proba, ClusteringResult result) {
super(result);
int c = 0;
this.weights = weights;
this.membershipDegree = new double[clusterMap.length];
if (membershipDegree != null) {
for (int i = 0; i < clusterMap.length; i++) {
if (clusterMap[i] == k) {
c++;
}
this.membershipDegree[i] = membershipDegree[i];
}
} else {
for (int i = 0; i < clusterMap.length; i++) {
if (clusterMap[i] == k) {
c++;
this.membershipDegree[i] = 1.;
} else {
this.membershipDegree[i] = 0.;
}
}
}
// TODO this.data = new Data(c, data.getStructure());
this.data = new SimpleData(c);
this.data.setComments(data.getComments());
this.data.setDataName(data.getDataName());
this.data.setAttributesNames(data.getAttributesNames());
c = 0;
Iterator<DataObject> iter = data.iterator();
int i = 0;
while(iter.hasNext()) {
DataObject current = iter.next();
if (clusterMap[i] == k) {
this.data.setDataObject(c, current);
c++;
}
i++;
}
if (this.data.getNbObjects() != 0) {
this.clusterCenter = this.computeCenter();
} else {
this.setVisible(false);
// System.out.println("attention, creation d'un cluster vide.");
}
this.membershipProbabilityEM = proba;
this.locked = false;
this.name = "Cluster " + (k + 1);
this.id = k;
}
/**
* <p>
......@@ -180,8 +101,7 @@ public class SimpleCluster extends Cluster {
}
// TODO this.data = new Data(c, data.getStructure());
this.data = new SimpleData(c);
this.data = new SimpleData(c, data.getDistanceModel(), data.getDistanceParameters());
this.data.setComments(data.getComments());
this.data.setDataName(data.getDataName());
this.data.setAttributesNames(data.getAttributesNames());
......@@ -228,46 +148,12 @@ public class SimpleCluster extends Cluster {
this.name = name;
}
public SimpleCluster(Cluster cluster, boolean fromSample) {
super(cluster);
if (cluster.getData(fromSample) != null) {
this.data = (Data) cluster.getData(fromSample).clone();
}
try {
if(cluster instanceof SimpleCluster) {
this.membershipDegree = new double[((SimpleCluster)cluster).membershipDegree.length];
for (int i = 0; i < this.membershipDegree.length; i++) {
this.membershipDegree[i] = cluster.getMembership(i);
}
this.membershipProbabilityEM = ((SimpleCluster)cluster).membershipProbabilityEM;
} else {
this.membershipDegree = new double[cluster.getCard()];
for (int i = 0; i < this.membershipDegree.length; i++) {
this.membershipDegree[i] = cluster.getMembership(i);
}
}
} catch (MethodNotImplementedException e) {
e.printStackTrace();
}
if (this.clusterCenter == null)
this.clusterCenter = this.computeCenter();
}
@Override
public Object clone() {
return new SimpleCluster(this);
}
@Override
public double distance(final int o) {
return this.clusterCenter.distance(this.data.getDataObject(o),
this.weights);
}
@Override
public int getCard() {
if (this.data == null) {
......@@ -372,14 +258,7 @@ public class SimpleCluster extends Cluster {
@Override
public DataObject getCenter() {
if(this.clusterCenter == null) {
this.clusterCenter = computeCenter();
}
return this.clusterCenter;
}
private DataObject computeCenter() {
return data.mean();
}
}
package jcl.clustering;
import java.util.Iterator;
import jcl.data.Data;
import jcl.data.DataObject;
import jcl.data.SimpleData;
import jcl.weights.Weights;
import multiCube.tools.util.exceptions.MethodNotImplementedException;
/**
* <p>
* Implementation simple de Cluster qui reprend les developpements avant abstraction
* </p>
*
* @author Baptiste Lafabregue
*/
public class SimpleCluster extends Cluster {
/** */
private static final long serialVersionUID = 1L;
/** Les donnees appartenant aéé& ce cluster */
private Data data = null;
/** Le degre d'appartenance de chaque objet a ce cluster */
private double membershipDegree[] = null;
/** Probabilite de la classe (pour EM) */
private double membershipProbabilityEM = 0;
/**
* <p>
* Constructeur de copie
* </p>
*
* @param cluster
* une classe
*/
public SimpleCluster(final SimpleCluster cluster) {
super(cluster);
this.data = (Data) cluster.data.clone();
this.membershipDegree = new double[cluster.membershipDegree.length];
for (int i = 0; i < this.membershipDegree.length; i++) {
try {
this.membershipDegree[i] = cluster.getMembership(i);
} catch (MethodNotImplementedException e) {
e.printStackTrace();
}
}
this.membershipProbabilityEM = cluster.membershipProbabilityEM;
}
<<<<<<< HEAD
=======
/**
* <p>
* Constructeur. (principal)
* </p>
*