[29] | 1 | /* |
---|
| 2 | * This program is free software; you can redistribute it and/or modify |
---|
| 3 | * it under the terms of the GNU General Public License as published by |
---|
| 4 | * the Free Software Foundation; either version 2 of the License, or |
---|
| 5 | * (at your option) any later version. |
---|
| 6 | * |
---|
| 7 | * This program is distributed in the hope that it will be useful, |
---|
| 8 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
---|
| 9 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
---|
| 10 | * GNU General Public License for more details. |
---|
| 11 | * |
---|
| 12 | * You should have received a copy of the GNU General Public License |
---|
| 13 | * along with this program; if not, write to the Free Software |
---|
| 14 | * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. |
---|
| 15 | */ |
---|
| 16 | |
---|
| 17 | /* |
---|
| 18 | * AbstractDensityBasedClusterer.java |
---|
| 19 | * Copyright (C) 1999 University of Waikato, Hamilton, New Zealand |
---|
| 20 | * |
---|
| 21 | */ |
---|
| 22 | |
---|
| 23 | package weka.clusterers; |
---|
| 24 | |
---|
| 25 | import weka.core.Instance; |
---|
| 26 | import weka.core.SerializedObject; |
---|
| 27 | import weka.core.Utils; |
---|
| 28 | |
---|
| 29 | /** |
---|
| 30 | * Abstract clustering model that produces (for each test instance) |
---|
| 31 | * an estimate of the membership in each cluster |
---|
| 32 | * (ie. a probability distribution). |
---|
| 33 | * |
---|
| 34 | * @author Mark Hall (mhall@cs.waikato.ac.nz) |
---|
| 35 | * @author Eibe Frank (eibe@cs.waikato.ac.nz) |
---|
| 36 | * @version $Revision: 1.1 $ |
---|
| 37 | */ |
---|
| 38 | public abstract class AbstractDensityBasedClusterer |
---|
| 39 | extends AbstractClusterer implements DensityBasedClusterer { |
---|
| 40 | |
---|
| 41 | /** for serialization. */ |
---|
| 42 | private static final long serialVersionUID = -5950728041704213845L; |
---|
| 43 | |
---|
| 44 | // =============== |
---|
| 45 | // Public methods. |
---|
| 46 | // =============== |
---|
| 47 | |
---|
| 48 | /** |
---|
| 49 | * Returns the prior probability of each cluster. |
---|
| 50 | * |
---|
| 51 | * @return the prior probability for each cluster |
---|
| 52 | * @exception Exception if priors could not be |
---|
| 53 | * returned successfully |
---|
| 54 | */ |
---|
| 55 | public abstract double[] clusterPriors() |
---|
| 56 | throws Exception; |
---|
| 57 | |
---|
| 58 | /** |
---|
| 59 | * Computes the log of the conditional density (per cluster) for a given instance. |
---|
| 60 | * |
---|
| 61 | * @param instance the instance to compute the density for |
---|
| 62 | * @return an array containing the estimated densities |
---|
| 63 | * @exception Exception if the density could not be computed |
---|
| 64 | * successfully |
---|
| 65 | */ |
---|
| 66 | public abstract double[] logDensityPerClusterForInstance(Instance instance) |
---|
| 67 | throws Exception; |
---|
| 68 | |
---|
| 69 | /** |
---|
| 70 | * Computes the density for a given instance. |
---|
| 71 | * |
---|
| 72 | * @param instance the instance to compute the density for |
---|
| 73 | * @return the density. |
---|
| 74 | * @exception Exception if the density could not be computed successfully |
---|
| 75 | */ |
---|
| 76 | public double logDensityForInstance(Instance instance) throws Exception { |
---|
| 77 | |
---|
| 78 | double[] a = logJointDensitiesForInstance(instance); |
---|
| 79 | double max = a[Utils.maxIndex(a)]; |
---|
| 80 | double sum = 0.0; |
---|
| 81 | |
---|
| 82 | for(int i = 0; i < a.length; i++) { |
---|
| 83 | sum += Math.exp(a[i] - max); |
---|
| 84 | } |
---|
| 85 | |
---|
| 86 | return max + Math.log(sum); |
---|
| 87 | } |
---|
| 88 | |
---|
| 89 | /** |
---|
| 90 | * Returns the cluster probability distribution for an instance. |
---|
| 91 | * |
---|
| 92 | * @param instance the instance to be clustered |
---|
| 93 | * @return the probability distribution |
---|
| 94 | * @throws Exception if computation fails |
---|
| 95 | */ |
---|
| 96 | public double[] distributionForInstance(Instance instance) throws Exception { |
---|
| 97 | |
---|
| 98 | return Utils.logs2probs(logJointDensitiesForInstance(instance)); |
---|
| 99 | } |
---|
| 100 | |
---|
| 101 | /** |
---|
| 102 | * Returns the logs of the joint densities for a given instance. |
---|
| 103 | * |
---|
| 104 | * @param inst the instance |
---|
| 105 | * @return the array of values |
---|
| 106 | * @exception Exception if values could not be computed |
---|
| 107 | */ |
---|
| 108 | public double[] logJointDensitiesForInstance(Instance inst) |
---|
| 109 | throws Exception { |
---|
| 110 | |
---|
| 111 | double[] weights = logDensityPerClusterForInstance(inst); |
---|
| 112 | double[] priors = clusterPriors(); |
---|
| 113 | |
---|
| 114 | for (int i = 0; i < weights.length; i++) { |
---|
| 115 | if (priors[i] > 0) { |
---|
| 116 | weights[i] += Math.log(priors[i]); |
---|
| 117 | } else { |
---|
| 118 | throw new IllegalArgumentException("Cluster empty!"); |
---|
| 119 | } |
---|
| 120 | } |
---|
| 121 | return weights; |
---|
| 122 | } |
---|
| 123 | |
---|
| 124 | /** |
---|
| 125 | * Creates copies of the current clusterer. Note that this method |
---|
| 126 | * now uses Serialization to perform a deep copy, so the Clusterer |
---|
| 127 | * object must be fully Serializable. Any currently built model will |
---|
| 128 | * now be copied as well. |
---|
| 129 | * |
---|
| 130 | * @param model an example clusterer to copy |
---|
| 131 | * @param num the number of clusterer copies to create. |
---|
| 132 | * @return an array of clusterers. |
---|
| 133 | * @exception Exception if an error occurs |
---|
| 134 | */ |
---|
| 135 | public static DensityBasedClusterer [] makeCopies(DensityBasedClusterer model, |
---|
| 136 | int num) throws Exception { |
---|
| 137 | if (model == null) { |
---|
| 138 | throw new Exception("No model clusterer set"); |
---|
| 139 | } |
---|
| 140 | DensityBasedClusterer [] clusterers = new DensityBasedClusterer [num]; |
---|
| 141 | SerializedObject so = new SerializedObject(model); |
---|
| 142 | for(int i = 0; i < clusterers.length; i++) { |
---|
| 143 | clusterers[i] = (DensityBasedClusterer) so.getObject(); |
---|
| 144 | } |
---|
| 145 | return clusterers; |
---|
| 146 | } |
---|
| 147 | } |
---|