public int[] Generate(Matrix x, int k, IDistance metric) { if (metric == null) metric = new EuclidianDistance(); X = x; var means = InitializeRandom(X, k); int[] assignments = new int[X.Rows]; for (int i = 0; i < 100; i++) { // Assignment step Parallel.For(0, X.Rows, j => { var min_index = -1; var min = double.MaxValue; for (int m = 0; m < means.Rows; m++) { var d = metric.Compute(X[j], means[m]); if (d < min) { min = d; min_index = m; } } assignments[j] = min_index; }); // Update Step Matrix new_means = Matrix.Zeros(k, X.Cols); Vector sum = Vector.Zeros(k); // Part 1: Sum up assignments for (int j = 0; j < X.Rows; j++) { int a = assignments[j]; new_means[a] += X[j, VectorType.Row]; sum[a]++; } // Part 2: Divide by counts for (int j = 0; j < new_means.Rows; j++) new_means[j] /= sum[j]; // Part 3: Check for convergence // find norm of the difference if ((means - new_means).Norm() < .00001) break; means = new_means; } Centers = means; return assignments; }
/// <summary>Generates.</summary> /// <param name="x">The Matrix to process.</param> /// <param name="k">The int to process.</param> /// <param name="metric">the metric.</param> /// <returns>An int[].</returns> public int[] Generate(Matrix x, int k, IDistance metric) { if (metric == null) { metric = new EuclidianDistance(); } this.X = x; var means = this.InitializeRandom(this.X, k); var assignments = new int[this.X.Rows]; for (var i = 0; i < 100; i++) { // Assignment step Parallel.For( 0, this.X.Rows, j => { var min_index = -1; var min = double.MaxValue; for (var m = 0; m < means.Rows; m++) { var d = metric.Compute(this.X[j], means[m]); if (d < min) { min = d; min_index = m; } } // bounds? if (min_index == -1) { min_index = 0; } assignments[j] = min_index; }); // Update Step var new_means = Matrix.Zeros(k, this.X.Cols); var sum = Vector.Zeros(k); // Part 1: Sum up assignments for (var j = 0; j < this.X.Rows; j++) { var a = assignments[j]; new_means[a] += this.X[j, VectorType.Row]; sum[a]++; } // Part 2: Divide by counts for (var j = 0; j < new_means.Rows; j++) { new_means[j] /= sum[j]; } // Part 3: Check for convergence // find norm of the difference if ((means - new_means).Norm() < .00001) { break; } means = new_means; } this.Centers = means; return assignments; }