An euclidian distance.
Inheritance: IDistance
Esempio n. 1
0
        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;
        }
Esempio n. 2
0
        /// <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;
        }