private int[] compute(double[][] points) { // first, select initial points double[][] seeds = createSeeds(points, 2 * Bandwidth); var maxcandidates = new ConcurrentStack <double[]>(); // construct map of the data tree = KDTree.FromData <int>(points, distance); // now, for each initial point if (UseParallelProcessing) { Parallel.For(0, seeds.Length, (index) => iterate(seeds, maxcandidates, index)); } else { for (int index = 0; index < seeds.Length; index++) { iterate(seeds, maxcandidates, index); } } // suppress non-maximum points double[][] maximum = cut ? maxcandidates.ToArray() : supress(seeds); // create a decision map using seeds int[] seedLabels = classifySeeds(seeds, maximum); tree = KDTree.FromData(seeds, seedLabels, distance); // create the cluster structure clusters = new MeanShiftClusterCollection(tree, maximum); // label each point return(clusters.Nearest(points)); }
/// <summary> /// Divides the input data into clusters. /// </summary> /// /// <param name="points">The data where to compute the algorithm.</param> /// <param name="threshold">The relative convergence threshold /// for the algorithm. Default is 1e-3.</param> /// <param name="maxIterations">The maximum number of iterations. Default is 100.</param> /// public int[] Compute(double[][] points, double threshold, int maxIterations = 100) { // first, select initial points double[][] seeds = createSeeds(points, 2 * Bandwidth); var maxcandidates = new ConcurrentStack <double[]>(); // construct map of the data tree = KDTree.FromData <int>(points, distance); // now, for each initial point global::Accord.Threading.Tasks.Parallel.For(0, seeds.Length, #if DEBUG new ParallelOptions() { MaxDegreeOfParallelism = 1 }, #endif (index) => { double[] point = seeds[index]; double[] mean = new double[point.Length]; double[] delta = new double[point.Length]; // we will keep moving it in the // direction of the density modes int iterations = 0; // until convergence or max iterations reached while (iterations < maxIterations) { iterations++; // compute the shifted mean computeMeanShift(point, mean); // extract the mean shift vector for (int j = 0; j < mean.Length; j++) { delta[j] = point[j] - mean[j]; } // update the point towards a mode for (int j = 0; j < mean.Length; j++) { point[j] = mean[j]; } // Check if we are already near any maximum point if (cut && nearest(point, maxcandidates) != null) { break; } // check for convergence: magnitude of the mean shift // vector converges to zero (Comaniciu 2002, page 606) if (Norm.Euclidean(delta) < threshold * Bandwidth) { break; } } if (cut) { double[] match = nearest(point, maxcandidates); if (match != null) { seeds[index] = match; } else { maxcandidates.Push(point); } } }); // suppress non-maximum points double[][] maximum = cut ? maxcandidates.ToArray() : supress(seeds); // create a decision map using seeds int[] seedLabels = classifySeeds(seeds, maximum); tree = KDTree.FromData(seeds, seedLabels, distance); // create the cluster structure clusters = new MeanShiftClusterCollection(tree, maximum); // label each point return(clusters.Nearest(points)); }