/* * 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/>. */ /* * AbstractDensityBasedClusterer.java * Copyright (C) 1999-2012 University of Waikato, Hamilton, New Zealand * */ package weka.clusterers; import weka.core.Instance; import weka.core.SerializedObject; import weka.core.Utils; /** * Abstract clustering model that produces (for each test instance) * an estimate of the membership in each cluster * (ie. a probability distribution). * * @author Mark Hall (mhall@cs.waikato.ac.nz) * @author Eibe Frank (eibe@cs.waikato.ac.nz) * @version $Revision: 8034 $ */ public abstract class AbstractDensityBasedClusterer extends AbstractClusterer implements DensityBasedClusterer { /** for serialization. */ private static final long serialVersionUID = -5950728041704213845L; // =============== // Public methods. // =============== /** * Returns the prior probability of each cluster. * * @return the prior probability for each cluster * @exception Exception if priors could not be * returned successfully */ public abstract double[] clusterPriors() throws Exception; /** * Computes the log of the conditional density (per cluster) for a given instance. * * @param instance the instance to compute the density for * @return an array containing the estimated densities * @exception Exception if the density could not be computed * successfully */ public abstract double[] logDensityPerClusterForInstance(Instance instance) throws Exception; /** * Computes the density for a given instance. * * @param instance the instance to compute the density for * @return the density. * @exception Exception if the density could not be computed successfully */ public double logDensityForInstance(Instance instance) throws Exception { double[] a = logJointDensitiesForInstance(instance); double max = a[Utils.maxIndex(a)]; double sum = 0.0; for(int i = 0; i < a.length; i++) { sum += Math.exp(a[i] - max); } return max + Math.log(sum); } /** * Returns the cluster probability distribution for an instance. * * @param instance the instance to be clustered * @return the probability distribution * @throws Exception if computation fails */ public double[] distributionForInstance(Instance instance) throws Exception { return Utils.logs2probs(logJointDensitiesForInstance(instance)); } /** * Returns the logs of the joint densities for a given instance. * * @param inst the instance * @return the array of values * @exception Exception if values could not be computed */ public double[] logJointDensitiesForInstance(Instance inst) throws Exception { double[] weights = logDensityPerClusterForInstance(inst); double[] priors = clusterPriors(); for (int i = 0; i < weights.length; i++) { if (priors[i] > 0) { weights[i] += Math.log(priors[i]); } else { throw new IllegalArgumentException("Cluster empty!"); } } return weights; } /** * Creates copies of the current clusterer. Note that this method * now uses Serialization to perform a deep copy, so the Clusterer * object must be fully Serializable. Any currently built model will * now be copied as well. * * @param model an example clusterer to copy * @param num the number of clusterer copies to create. * @return an array of clusterers. * @exception Exception if an error occurs */ public static DensityBasedClusterer [] makeCopies(DensityBasedClusterer model, int num) throws Exception { if (model == null) { throw new Exception("No model clusterer set"); } DensityBasedClusterer [] clusterers = new DensityBasedClusterer [num]; SerializedObject so = new SerializedObject(model); for(int i = 0; i < clusterers.length; i++) { clusterers[i] = (DensityBasedClusterer) so.getObject(); } return clusterers; } }