示例#1
0
        public double SquaredError(CentroidItem centroid, IEnumerable <Client> PointsInCluster)
        {
            double amount = .0;

            foreach (var point in PointsInCluster)
            {
                amount += Math.Pow(point.Distance(centroid.Data), 2);
            }
            return(amount);
        }
示例#2
0
        public Tuple <Client[], double> Run(Client[] clients, int MaxAmountOfClusters, int MaxAmountOfIterations)
        {
            var centroidChooserList = clients.ToList();

            if (clients.Length < MaxAmountOfClusters)
            {
                return(null);
            }
            var changed   = true;
            var centroids = new List <CentroidItem>();

            Random rnd = new Random();

            for (int i = 0; i < MaxAmountOfClusters; i++)
            {
                int randomIndex = rnd.Next(centroidChooserList.Count);
                var data        = centroidChooserList[randomIndex].Data;
                centroidChooserList = centroidChooserList.Where(x => !x.Data.Equals(data)).ToList();
                centroids.Add(new CentroidItem(data, i));
            }

            while (changed && MaxAmountOfIterations != 0)
            {
                foreach (var client in clients)
                {
                    double lowestDistance = double.PositiveInfinity;

                    for (int i = 0; i < MaxAmountOfClusters; i++)
                    {
                        double distanceBetweenPoints = client.Distance(centroids[i].Data);
                        if (distanceBetweenPoints < lowestDistance)
                        {
                            lowestDistance       = distanceBetweenPoints;
                            client.ClusterNumber = centroids[i].Number;
                        }
                    }
                }

                var centroidWithPoints = clients
                                         .GroupBy(c => c.ClusterNumber)
                                         .ToDictionary(c => c.Key, c => c.ToList());


                var centroidNotChangedCount = 0;
                foreach (var c in centroidWithPoints)
                {
                    var oldCentroid = centroids.First(x => x.Number == c.Key);

                    var list = new List <Vector>();
                    foreach (var client in c.Value)
                    {
                        list.Add(client.Data);
                    }

                    var newCentroid = new CentroidItem(Mean(list, oldCentroid.Data.Points.Length), c.Key);

                    if (!oldCentroid.Equals(newCentroid))
                    {
                        centroids[newCentroid.Number] = newCentroid;
                    }
                    else
                    {
                        centroidNotChangedCount++;
                    }
                }

                if (centroidNotChangedCount == MaxAmountOfClusters)
                {
                    changed = false;
                }

                MaxAmountOfIterations--;
            }

            var sse = .0;

            for (int i = 0; i < MaxAmountOfClusters; i++)
            {
                var clientByClusterId = clients.Where(x => x.ClusterNumber == i);
                sse += SquaredError(centroids[i], clientByClusterId);
            }

            return(Tuple.Create(clients, sse));
        }