use of de.lmu.ifi.dbs.elki.logging.progress.MutableProgress in project elki by elki-project.
the class XMeans method run.
/**
* Run the algorithm on a database and relation.
*
* @param database Database to process
* @param relation Data relation
* @return Clustering result.
*/
@Override
public Clustering<M> run(Database database, Relation<V> relation) {
MutableProgress prog = LOG.isVerbose() ? new MutableProgress("X-means number of clusters", k_max, LOG) : null;
// Run initial k-means to find at least k_min clusters
innerKMeans.setK(k_min);
if (LOG.isStatistics()) {
LOG.statistics(new StringStatistic(KEY + ".initialization", initializer.toString()));
}
splitInitializer.setInitialMeans(initializer.chooseInitialMeans(database, relation, k_min, getDistanceFunction()));
Clustering<M> clustering = innerKMeans.run(database, relation);
if (prog != null) {
prog.setProcessed(k_min, LOG);
}
ArrayList<Cluster<M>> clusters = new ArrayList<>(clustering.getAllClusters());
while (clusters.size() <= k_max) {
// Improve-Structure:
ArrayList<Cluster<M>> nextClusters = new ArrayList<>();
for (Cluster<M> cluster : clusters) {
// Try to split this cluster:
List<Cluster<M>> childClusterList = splitCluster(cluster, database, relation);
nextClusters.addAll(childClusterList);
if (childClusterList.size() > 1) {
k += childClusterList.size() - 1;
if (prog != null) {
if (k >= k_max) {
prog.setTotal(k + 1);
}
prog.setProcessed(k, LOG);
}
}
}
if (clusters.size() == nextClusters.size()) {
break;
}
// Improve-Params:
splitInitializer.setInitialClusters(nextClusters);
innerKMeans.setK(nextClusters.size());
clustering = innerKMeans.run(database, relation);
clusters.clear();
clusters.addAll(clustering.getAllClusters());
}
// Ensure that the progress bar finished.
if (prog != null) {
prog.setTotal(k);
prog.setProcessed(k, LOG);
}
if (LOG.isDebugging()) {
LOG.debug("X-means returned k=" + k + " clusters.");
}
// add all current clusters to the result
Clustering<M> result = new Clustering<>("X-Means Result", "X-Means", clusters);
return result;
}
use of de.lmu.ifi.dbs.elki.logging.progress.MutableProgress in project elki by elki-project.
the class AffinityPropagationClusteringAlgorithm method run.
/**
* Perform affinity propagation clustering.
*
* @param db Database
* @param relation Relation
* @return Clustering result
*/
public Clustering<MedoidModel> run(Database db, Relation<O> relation) {
ArrayDBIDs ids = DBIDUtil.ensureArray(relation.getDBIDs());
final int size = ids.size();
int[] assignment = new int[size];
double[][] s = initialization.getSimilarityMatrix(db, relation, ids);
double[][] r = new double[size][size];
double[][] a = new double[size][size];
IndefiniteProgress prog = LOG.isVerbose() ? new IndefiniteProgress("Affinity Propagation Iteration", LOG) : null;
MutableProgress aprog = LOG.isVerbose() ? new MutableProgress("Stable assignments", size + 1, LOG) : null;
int inactive = 0;
for (int iteration = 0; iteration < maxiter && inactive < convergence; iteration++) {
// Update responsibility matrix:
for (int i = 0; i < size; i++) {
double[] ai = a[i], ri = r[i], si = s[i];
// Find the two largest values (as initially maxk == i)
double max1 = Double.NEGATIVE_INFINITY, max2 = Double.NEGATIVE_INFINITY;
int maxk = -1;
for (int k = 0; k < size; k++) {
double val = ai[k] + si[k];
if (val > max1) {
max2 = max1;
max1 = val;
maxk = k;
} else if (val > max2) {
max2 = val;
}
}
// With the maximum value known, update r:
for (int k = 0; k < size; k++) {
double val = si[k] - ((k != maxk) ? max1 : max2);
ri[k] = ri[k] * lambda + val * (1. - lambda);
}
}
// Update availability matrix
for (int k = 0; k < size; k++) {
// Compute sum of max(0, r_ik) for all i.
// For r_kk, don't apply the max.
double colposum = 0.;
for (int i = 0; i < size; i++) {
if (i == k || r[i][k] > 0.) {
colposum += r[i][k];
}
}
for (int i = 0; i < size; i++) {
double val = colposum;
// Adjust column sum by the one extra term.
if (i == k || r[i][k] > 0.) {
val -= r[i][k];
}
if (i != k && val > 0.) {
// min
val = 0.;
}
a[i][k] = a[i][k] * lambda + val * (1 - lambda);
}
}
int changed = 0;
for (int i = 0; i < size; i++) {
double[] ai = a[i], ri = r[i];
double max = Double.NEGATIVE_INFINITY;
int maxj = -1;
for (int j = 0; j < size; j++) {
double v = ai[j] + ri[j];
if (v > max || (i == j && v >= max)) {
max = v;
maxj = j;
}
}
if (assignment[i] != maxj) {
changed += 1;
assignment[i] = maxj;
}
}
inactive = (changed > 0) ? 0 : (inactive + 1);
LOG.incrementProcessed(prog);
if (aprog != null) {
aprog.setProcessed(size - changed, LOG);
}
}
if (aprog != null) {
aprog.setProcessed(aprog.getTotal(), LOG);
}
LOG.setCompleted(prog);
// Cluster map, by lead object
Int2ObjectOpenHashMap<ModifiableDBIDs> map = new Int2ObjectOpenHashMap<>();
DBIDArrayIter i1 = ids.iter();
for (int i = 0; i1.valid(); i1.advance(), i++) {
int c = assignment[i];
// Add to cluster members:
ModifiableDBIDs cids = map.get(c);
if (cids == null) {
cids = DBIDUtil.newArray();
map.put(c, cids);
}
cids.add(i1);
}
// If we stopped early, the cluster lead might be in a different cluster.
for (ObjectIterator<Int2ObjectOpenHashMap.Entry<ModifiableDBIDs>> iter = map.int2ObjectEntrySet().fastIterator(); iter.hasNext(); ) {
Int2ObjectOpenHashMap.Entry<ModifiableDBIDs> entry = iter.next();
final int key = entry.getIntKey();
int targetkey = key;
ModifiableDBIDs tids = null;
// Chase arrows:
while (ids == null && assignment[targetkey] != targetkey) {
targetkey = assignment[targetkey];
tids = map.get(targetkey);
}
if (tids != null && targetkey != key) {
tids.addDBIDs(entry.getValue());
iter.remove();
}
}
Clustering<MedoidModel> clustering = new Clustering<>("Affinity Propagation Clustering", "ap-clustering");
ModifiableDBIDs noise = DBIDUtil.newArray();
for (ObjectIterator<Int2ObjectOpenHashMap.Entry<ModifiableDBIDs>> iter = map.int2ObjectEntrySet().fastIterator(); iter.hasNext(); ) {
Int2ObjectOpenHashMap.Entry<ModifiableDBIDs> entry = iter.next();
i1.seek(entry.getIntKey());
if (entry.getValue().size() > 1) {
MedoidModel mod = new MedoidModel(DBIDUtil.deref(i1));
clustering.addToplevelCluster(new Cluster<>(entry.getValue(), mod));
} else {
noise.add(i1);
}
}
if (noise.size() > 0) {
MedoidModel mod = new MedoidModel(DBIDUtil.deref(noise.iter()));
clustering.addToplevelCluster(new Cluster<>(noise, true, mod));
}
return clustering;
}
use of de.lmu.ifi.dbs.elki.logging.progress.MutableProgress in project elki by elki-project.
the class LogPanel method getOrCreateProgressBar.
/**
* Get an existing or create a new progress bar.
*
* @param prog Progress
* @return Associated progress bar.
*/
private JProgressBar getOrCreateProgressBar(Progress prog) {
JProgressBar pbar = pbarmap.get(prog);
// Add a new progress bar.
if (pbar == null) {
synchronized (pbarmap) {
if (prog instanceof FiniteProgress) {
pbar = new JProgressBar(0, ((FiniteProgress) prog).getTotal());
pbar.setStringPainted(true);
} else if (prog instanceof IndefiniteProgress) {
pbar = new JProgressBar();
pbar.setIndeterminate(true);
pbar.setStringPainted(true);
} else if (prog instanceof MutableProgress) {
pbar = new JProgressBar(0, ((MutableProgress) prog).getTotal());
pbar.setStringPainted(true);
} else {
throw new RuntimeException("Unsupported progress record");
}
pbarmap.put(prog, pbar);
final JProgressBar pbar2 = pbar;
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
addProgressBar(pbar2);
}
});
}
}
return pbar;
}
use of de.lmu.ifi.dbs.elki.logging.progress.MutableProgress in project elki by elki-project.
the class P3C method mergeClusterCores.
/**
* Merge 1-signatures into p-signatures.
*
* @param binCount Number of bins in each dimension.
* @param signatures 1-signatures
* @return p-signatures
*/
private ArrayList<Signature> mergeClusterCores(final int binCount, ArrayList<Signature> signatures) {
MutableProgress mergeProgress = LOG.isVerbose() ? new MutableProgress("Merging signatures", signatures.size(), LOG) : null;
// Annotate dimensions to 1-signatures for quick stopping.
int[] firstdim = new int[signatures.size()];
for (int i = 0; i < signatures.size(); i++) {
firstdim[i] = signatures.get(i).getFirstDim();
}
LOG.debug("First dimensions: " + FormatUtil.format(firstdim));
// Merge to (p+1)-signatures (cluster cores).
ArrayList<Signature> clusterCores = new ArrayList<>(signatures);
// Try adding merge 1-signature with each cluster core.
for (int i = 0; i < clusterCores.size(); i++) {
final Signature parent = clusterCores.get(i);
final int end = parent.getFirstDim();
for (int j = 0; j < signatures.size() && firstdim[j] < end; j++) {
final Signature onesig = signatures.get(j);
final Signature merge = mergeSignatures(parent, onesig, binCount);
if (merge != null) {
// We add each potential core to the list to allow remaining
// 1-signatures to try merging with this p-signature as well.
clusterCores.add(merge);
// Flag both "parents" for removal.
parent.prune = true;
onesig.prune = true;
}
}
if (mergeProgress != null) {
mergeProgress.setTotal(clusterCores.size());
mergeProgress.incrementProcessed(LOG);
}
}
if (mergeProgress != null) {
mergeProgress.setProcessed(mergeProgress.getTotal(), LOG);
}
return clusterCores;
}
Aggregations