示例#1
0
        // Класстеризация объектов методом k-средних
        private List <int>[] kMeansClustering(int clustersCount, Dictionary <int, ObjectParameters> objParametrs)
        {
            if (objParametrs.Count < 1)
            {
                MessageBox.Show("Ошибка: не найдено ни одного объекта.");
                return(null);
            }

            List <ObjectParameters> objects = new List <ObjectParameters>(objParametrs.Values);

            // Выбор стартового набора центь центроидов кластеров методом k-средних++
            List <ObjectParameters> centroids = kMeansPPSelectionStartingCentroids(clustersCount, objParametrs);

            // Список кластеров, содержащий набор объектов, принадлежищих каждому из них
            List <int>[]
            clusters = new List <int> [centroids.Count],
            oldClusters = new List <int> [centroids.Count];

            for (int i = 0; i < clusters.Length; ++i)
            {
                clusters[i] = new List <int>();
            }

            while (true)
            {
                for (int i = 0; i < clusters.Length; ++i)
                {
                    oldClusters[i] = new List <int>(clusters[i]);
                    clusters[i].Clear();
                }

                // Формирование кластеров
                foreach (KeyValuePair <int, ObjectParameters> obj in objParametrs)
                {
                    int    selectedCentroid = 0;
                    double minDistance      = double.MaxValue;

                    // Объект выбирает центроид кластера, которому он принадлежит
                    double distance;
                    for (int i = 0; i < centroids.Count; ++i)
                    {
                        distance = сalculateDistance(obj.Value, centroids[i]);
                        if (distance < minDistance)
                        {
                            minDistance      = distance;
                            selectedCentroid = i;
                        }
                    }

                    // После того, как кластер выбран, метка объекта добавляется в его список
                    clusters[selectedCentroid].Add(obj.Key);
                }

                for (int i = 0; i < clusters.Length; ++i)
                {
                    if (!clusters[i].SequenceEqual(oldClusters[i]))
                    {
                        break;
                    }
                    // Если все объекты идентичны
                    else if (i == (clusters.Length - 1))
                    {
                        // Выход из бесконечного цикла кластеризации
                        return(clusters);
                    }
                }

                // Для каждого полученного класстера перерассчитываются центроиды
                for (int i = 0; i < clusters.Length; ++i)
                {
                    centroids[i] = new ObjectParameters();

                    foreach (int objMark in clusters[i])
                    {
                        centroids[i].Perimeter   += objParametrs[objMark].Perimeter;
                        centroids[i].Square      += objParametrs[objMark].Square;
                        centroids[i].Compactness += objParametrs[objMark].Compactness;
                        centroids[i].Elongation  += objParametrs[objMark].Elongation;
                    }

                    if (clusters[i].Count != 0)
                    {
                        centroids[i].Perimeter   /= clusters[i].Count;
                        centroids[i].Square      /= clusters[i].Count;
                        centroids[i].Compactness /= clusters[i].Count;
                        centroids[i].Elongation  /= clusters[i].Count;
                    }
                }
            }

            // Циклический перерассчёт до тех пор, пока результаты не усреднятся
        }