View Javadoc

1   /**
2    * Copyright (c) 2011, The University of Southampton and the individual contributors.
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without modification,
6    * are permitted provided that the following conditions are met:
7    *
8    *   * 	Redistributions of source code must retain the above copyright notice,
9    * 	this list of conditions and the following disclaimer.
10   *
11   *   *	Redistributions in binary form must reproduce the above copyright notice,
12   * 	this list of conditions and the following disclaimer in the documentation
13   * 	and/or other materials provided with the distribution.
14   *
15   *   *	Neither the name of the University of Southampton nor the names of its
16   * 	contributors may be used to endorse or promote products derived from this
17   * 	software without specific prior written permission.
18   *
19   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
20   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
21   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
23   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
24   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
26   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29   */
30  package org.openimaj.experiment.evaluation.cluster;
31  
32  import java.util.ArrayList;
33  import java.util.HashMap;
34  import java.util.List;
35  import java.util.Map;
36  import java.util.Map.Entry;
37  
38  import org.openimaj.experiment.evaluation.AnalysisResult;
39  import org.openimaj.experiment.evaluation.Evaluator;
40  import org.openimaj.experiment.evaluation.cluster.analyser.ClusterAnalyser;
41  import org.openimaj.ml.clustering.dbscan.SparseMatrixDBSCAN;
42  import org.openimaj.util.function.Function;
43  import org.openimaj.util.iterator.UniformDoubleRangeIterable;
44  
45  import ch.akuhn.matrix.SparseMatrix;
46  
47  /**
48   * @author Sina Samangooei (ss@ecs.soton.ac.uk)
49   * 
50   * @param <D>
51   *            The type of data which the internal clusterer can cluster lists of
52   * @param <T>
53   *            The type of results the
54   */
55  public class RangedDBSCANClusterEvaluator<D, T extends AnalysisResult>
56  		implements
57  			Evaluator<Map<Double, int[][]>, RangedAnalysisResult<Double, T>>
58  {
59  
60  	private int[][] correct;
61  	private ClusterAnalyser<T> analyser;
62  	private SparseMatrixDBSCAN gen;
63  	private SparseMatrix data;
64  	UniformDoubleRangeIterable r;
65  
66  	/**
67  	 * @param r
68  	 *            the range of values for the {@link SparseMatrixDBSCAN} eps
69  	 *            value
70  	 * @param gen
71  	 * @param data
72  	 * @param clusters
73  	 * @param analyser
74  	 */
75  	public RangedDBSCANClusterEvaluator(UniformDoubleRangeIterable r, SparseMatrixDBSCAN gen, SparseMatrix data,
76  			int[][] clusters, ClusterAnalyser<T> analyser)
77  	{
78  		this.gen = gen;
79  		this.correct = clusters;
80  		this.analyser = analyser;
81  		this.data = data;
82  	}
83  
84  	/**
85  	 * @param r
86  	 *            the range of values for the {@link SparseMatrixDBSCAN} eps
87  	 *            value
88  	 * @param gen
89  	 * @param data
90  	 * @param dataset
91  	 *            extract the elements of this map "in order" and build a ground
92  	 *            truth. very dangerous.
93  	 * @param analyser
94  	 */
95  	public <A, B> RangedDBSCANClusterEvaluator(UniformDoubleRangeIterable r, SparseMatrixDBSCAN gen, SparseMatrix data,
96  			Map<A, ? extends List<B>> dataset, ClusterAnalyser<T> analyser)
97  	{
98  		this.r = r;
99  		this.gen = gen;
100 		this.correct = new int[dataset.size()][];
101 		int j = 0;
102 		int k = 0;
103 		for (final Entry<A, ? extends List<B>> es : dataset.entrySet()) {
104 			this.correct[j] = new int[es.getValue().size()];
105 			int i = 0;
106 			final List<B> value = es.getValue();
107 			for (int l = 0; l < value.size(); l++) {
108 				this.correct[j][i++] = k;
109 				k++;
110 			}
111 			j++;
112 		}
113 		this.analyser = analyser;
114 		this.data = data;
115 	}
116 
117 	/**
118 	 * @param r
119 	 *            the range of values for the {@link SparseMatrixDBSCAN} eps
120 	 *            value
121 	 * @param gen
122 	 * @param data
123 	 * @param indexFunc
124 	 *            given a data instance, return its index
125 	 * @param dataset
126 	 * @param analyser
127 	 */
128 	public <A, B> RangedDBSCANClusterEvaluator(
129 			UniformDoubleRangeIterable r,
130 			SparseMatrixDBSCAN gen,
131 			SparseMatrix data,
132 			Function<B, Integer> indexFunc,
133 			Map<A, ? extends List<B>> dataset,
134 			ClusterAnalyser<T> analyser)
135 	{
136 		this.r = r;
137 		this.gen = gen;
138 		this.correct = new int[dataset.size()][];
139 		int j = 0;
140 		for (final Entry<A, ? extends List<B>> es : dataset.entrySet()) {
141 			this.correct[j] = new int[es.getValue().size()];
142 			int i = 0;
143 			final List<B> value = es.getValue();
144 			for (final B b : value) {
145 				this.correct[j][i++] = indexFunc.apply(b);
146 			}
147 			j++;
148 		}
149 		this.analyser = analyser;
150 		this.data = data;
151 	}
152 
153 	/**
154 	 * @param r
155 	 *            the range of values for the {@link SparseMatrixDBSCAN} eps
156 	 *            value
157 	 * @param gen
158 	 * @param dataset
159 	 * @param transform
160 	 *            turn a list of dataset items into the required type for
161 	 *            clustering
162 	 * @param analyser
163 	 */
164 	public <A, B> RangedDBSCANClusterEvaluator(
165 			UniformDoubleRangeIterable r,
166 			SparseMatrixDBSCAN gen,
167 			Map<A, ? extends List<B>> dataset,
168 			Function<List<B>, SparseMatrix> transform,
169 			ClusterAnalyser<T> analyser)
170 	{
171 		this.r = r;
172 		this.gen = gen;
173 		this.analyser = analyser;
174 		this.correct = new int[dataset.size()][];
175 		int j = 0;
176 		final List<B> flattened = new ArrayList<B>();
177 		for (final Entry<A, ? extends List<B>> es : dataset.entrySet()) {
178 			this.correct[j] = new int[es.getValue().size()];
179 			int i = 0;
180 			for (final B b : es.getValue()) {
181 				this.correct[j][i++] = flattened.size();
182 				flattened.add(b);
183 			}
184 			j++;
185 		}
186 		this.data = transform.apply(flattened);
187 	}
188 
189 	@Override
190 	public Map<Double, int[][]> evaluate() {
191 		final Map<Double, int[][]> ret = new HashMap<Double, int[][]>();
192 		for (final Double eps : this.r) {
193 			this.gen.setEps(eps);
194 			ret.put(eps, new ClusterEvaluator<SparseMatrix, T>(gen, data, correct, analyser).evaluate());
195 		}
196 		return ret;
197 	}
198 
199 	@Override
200 	public RangedAnalysisResult<Double, T> analyse(Map<Double, int[][]> estimated) {
201 		final RangedAnalysisResult<Double, T> ret = new RangedAnalysisResult<Double, T>();
202 		for (final Entry<Double, int[][]> ent : estimated.entrySet()) {
203 			ret.put(ent.getKey(), this.analyser.analyse(correct, ent.getValue()));
204 		}
205 		return ret;
206 	}
207 
208 }