View Javadoc

1   /*
2   	AUTOMATICALLY GENERATED BY jTemp FROM
3   	/Users/jsh2/Work/openimaj/target/checkout/machine-learning/clustering/src/main/jtemp/org/openimaj/ml/clustering/assignment/soft/#T#KNNAssigner.jtemp
4   */
5   /**
6    * Copyright (c) 2011, The University of Southampton and the individual contributors.
7    * All rights reserved.
8    *
9    * Redistribution and use in source and binary forms, with or without modification,
10   * are permitted provided that the following conditions are met:
11   *
12   *   * 	Redistributions of source code must retain the above copyright notice,
13   * 	this list of conditions and the following disclaimer.
14   *
15   *   *	Redistributions in binary form must reproduce the above copyright notice,
16   * 	this list of conditions and the following disclaimer in the documentation
17   * 	and/or other materials provided with the distribution.
18   *
19   *   *	Neither the name of the University of Southampton nor the names of its
20   * 	contributors may be used to endorse or promote products derived from this
21   * 	software without specific prior written permission.
22   *
23   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
24   * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
25   * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
26   * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
27   * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
28   * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
29   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
30   * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
31   * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
32   * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
33   */
34  package org.openimaj.ml.clustering.assignment.soft;
35  
36  import org.openimaj.feature.FloatFVComparison;
37  import org.openimaj.knn.FloatNearestNeighbours;
38  import org.openimaj.knn.FloatNearestNeighboursExact;
39  import org.openimaj.knn.FloatNearestNeighboursProvider;
40  import org.openimaj.knn.approximate.FloatNearestNeighboursKDTree;
41  import org.openimaj.ml.clustering.assignment.SoftAssigner;
42  import org.openimaj.ml.clustering.CentroidsProvider;
43  import org.openimaj.util.pair.IndependentPair;
44  
45  /**
46   * A {@link SoftAssigner} that picks a fixed number of nearest neighbours.
47   * Weights returned are actually the distances to the centroids.
48   * 
49   * @author Jonathon Hare (jsh2@ecs.soton.ac.uk)
50   *
51   */
52  public class FloatKNNAssigner implements SoftAssigner<float[], float[]> {
53  	protected FloatNearestNeighbours nn;
54  	protected int numNeighbours;
55  
56  	/**
57  	 * Construct the assigner using the given cluster data. The assigner
58  	 * is backed by either a {@link FloatNearestNeighboursExact} or 
59  	 * {@link FloatNearestNeighboursKDTree}, depending on whether the exact
60  	 * parameter is true or false. If the parameter is true, then the 
61  	 * resultant {@link FloatNearestNeighboursExact} will use Euclidean
62  	 * distance.
63  	 * 
64  	 * @param provider the cluster data provider
65  	 * @param exact if true, then use exact mode; false implies approximate mode.
66  	 * @param numNeighbours the number of nearest neighbours to select.
67  	 */
68  	public FloatKNNAssigner(CentroidsProvider<float[]> provider, boolean exact, int numNeighbours) {
69  		this.numNeighbours = numNeighbours;
70  		
71  		if (exact) {
72  			nn = new FloatNearestNeighboursExact(provider.getCentroids());
73  		} else {
74  			if (provider instanceof FloatNearestNeighboursProvider) {
75  				FloatNearestNeighbours internal = ((FloatNearestNeighboursProvider)provider).getNearestNeighbours();
76  
77  				if (internal != null && internal instanceof FloatNearestNeighboursKDTree) {
78  					nn = (FloatNearestNeighboursKDTree) internal;
79  					return;
80  				}
81  			}
82  
83  			nn = new FloatNearestNeighboursKDTree(provider.getCentroids(), FloatNearestNeighboursKDTree.DEFAULT_NTREES, FloatNearestNeighboursKDTree.DEFAULT_NCHECKS);
84  		}
85  	}
86  	
87  	/**
88  	 * Construct the assigner using the given cluster data. The assigner
89  	 * is backed by either a {@link FloatNearestNeighboursExact} or 
90  	 * {@link FloatNearestNeighboursKDTree}, depending on whether the exact
91  	 * parameter is true or false. If the parameter is true, then the 
92  	 * resultant {@link FloatNearestNeighboursExact} will use Euclidean
93  	 * distance.
94  	 * 
95  	 * @param data the cluster data
96  	 * @param exact if true, then use exact mode; false implies approximate mode.
97  	 * @param numNeighbours the number of nearest neighbours to select.
98  	 */
99  	public FloatKNNAssigner(float[][] data, boolean exact, int numNeighbours) {
100 		this.numNeighbours = numNeighbours;
101 		
102 		if (exact) {
103 			nn = new FloatNearestNeighboursExact(data);
104 		} else {
105 			nn = new FloatNearestNeighboursKDTree(data, FloatNearestNeighboursKDTree.DEFAULT_NTREES, FloatNearestNeighboursKDTree.DEFAULT_NCHECKS);
106 		}
107 	}
108 	
109 	/**
110 	 * Construct the assigner using the given cluster data and 
111 	 * distance function. The assigner will operate in exact mode,
112 	 * using a {@link FloatNearestNeighboursExact}.
113 	 * 
114 	 * @param provider the cluster data provider
115 	 * @param comparison the distance function
116 	 * @param numNeighbours the number of nearest neighbours to select.
117 	 */
118 	public FloatKNNAssigner(CentroidsProvider<float[]> provider, FloatFVComparison comparison, int numNeighbours) {
119 		this.numNeighbours = numNeighbours;
120 		
121 		nn = new FloatNearestNeighboursExact(provider.getCentroids(), comparison);
122 	}
123 	
124 	/**
125 	 * Construct the assigner using the given cluster data and 
126 	 * distance function. The assigner will operate in exact mode,
127 	 * using a {@link FloatNearestNeighboursExact}.
128 	 * 
129 	 * @param data the cluster data
130 	 * @param comparison the distance function
131 	 * @param numNeighbours the number of nearest neighbours to select.
132 	 */
133 	public FloatKNNAssigner(float[][] data, FloatFVComparison comparison, int numNeighbours) {
134 		this.numNeighbours = numNeighbours;
135 		
136 		nn = new FloatNearestNeighboursExact(data, comparison);
137 	}
138 
139 	@Override
140 	public int[][] assign(float[][] data) {
141 		int [][] indices = new int [data.length][numNeighbours];
142 		float [][] distances = new float [data.length][numNeighbours];
143 		
144 		nn.searchKNN(data, numNeighbours, indices, distances);
145 		
146 		return indices;
147 	}
148 
149 	@Override
150 	public int[] assign(float[] data) {
151 		return assign(new float[][] { data })[0];
152 	}
153 
154 	@Override
155 	public void assignWeighted(float[][] data, int[][] assignments, float[][] weights) {
156 		nn.searchKNN(data, numNeighbours, assignments, weights);
157 	}
158 
159 	@Override
160 	public IndependentPair<int[], float[]> assignWeighted(float[] data) {
161 		int [][] indices = new int [data.length][numNeighbours];
162 		float [][] distances = new float [data.length][numNeighbours];
163 		
164 		nn.searchKNN(new float[][] { data }, numNeighbours, indices, distances);
165 		
166 		return new IndependentPair<int[], float[]>(indices[0], distances[0]);
167 	}
168 	
169 	@Override
170 	public int numDimensions() {
171 	    return nn.numDimensions();
172 	}
173 	
174 	@Override
175 	public int size() {
176 	    return nn.size();
177 	}
178 }