internal static List <IMathPoint> InitCenters(IMathSet mathSet, ClusteringOptions options)
        {
            IMathPoint minPoint = DataMiningMath.GetLimitPoint(mathSet, (Double c, Double p) => c > p);
            IMathPoint maxPoint = DataMiningMath.GetLimitPoint(mathSet, (Double c, Double p) => c < p);

            if (options.Initialization == InitializationType.RANDOM)
            {
                return(GetRandomClusterCenters(minPoint, maxPoint, options));
            }
            else
            {
                throw new ArgumentException("поддерживаемый метод инициализации центров кластеризации: random");
            }
        }
示例#2
0
 private void Btn_load_Click(object sender, EventArgs e)
 {
     this.m_workInfo.AddInfornation("выбор подходящего набора данных");
     using (OpenFileDialog fd = new OpenFileDialog()
     {
         InitialDirectory = @"c:\",
         Filter = "json files (*.json)|*.json|xml files (*.xml)|*.xml",
         FilterIndex = 1,
         RestoreDirectory = true
     })
     {
         if (fd.ShowDialog() == DialogResult.OK)
         {
             try
             {
                 FileInfo fi = new FileInfo(fd.FileName);
                 if (fi.Extension.Equals(".xml"))
                 {
                     var set = DataSetSerializer.LoadFromXmlFile(fd.FileName);
                     this.m_mathSet = DataSetSerializer.SetToIMathSet(set);
                 }
                 else
                 {
                     using (StreamReader sr = new StreamReader(fd.FileName, Encoding.Default))
                     {
                         String jsonString = sr.ReadToEnd();
                         this.m_mathSet = DataSetSerializer.JsonToMathSet(jsonString);
                     }
                 }
                 this.m_workInfo.AddInfornation("набор данных \'" + fi.Name + "\' загружен");
                 this.m_renderHandler.AddMathSet(this.m_mathSet);
                 this.RenderClasses();
             }
             catch (Exception ex)
             {
                 this.m_workInfo.AddError(ex.Message);
             }
         }
         else
         {
             this.m_workInfo.AddInfornation("операция отменена");
         }
     }
 }
示例#3
0
 internal static IMathPoint GetLimitPoint(IMathSet mathSet, Func <Double, Double, Boolean> comparisonFunc)
 {
     if (1 < mathSet.RowsCount)
     {
         IMathPoint limitPoint = mathSet[0].Clone() as IMathPoint;
         for (Int32 r = 0; r < mathSet.RowsCount; r++)
         {
             for (Int32 c = 0; c < mathSet[r].CoordinatesCount; c++)
             {
                 if (comparisonFunc(limitPoint[c], mathSet[r][c]))
                 {
                     limitPoint[c] = mathSet[r][c];
                 }
             }
         }
         return(limitPoint);
     }
     throw new ArgumentException("входной набор IMathSet должен содержать минимум 2 точки с данными");
 }
        public void Run(IMathSet mathSet, ClusteringOptions options)
        {
            this.m_sw.Restart();
            switch (this.Algorithm)
            {
            case AlgorithmType.KMEANS:
                this.Result = ClusteringFacade.Kmeans(mathSet, options);
                break;

            case AlgorithmType.KMEDOIDS:
                this.Result = ClusteringFacade.Kmedoids(mathSet, options);
                break;

            default:
                throw new ArgumentException("выбран не используемый (не реализованный) алгоритм");
            }
            this.m_sw.Stop();
            this.CalculationTime = this.m_sw.ElapsedMilliseconds;
        }
示例#5
0
        public static ClusteringResult Kmedoids(IMathSet mathSet, ClusteringOptions options)
        {
            if (mathSet != null)
            {
                if (options.ClusterCount <= mathSet.RowsCount)
                {
                    switch (options.Mode)
                    {
                    case ModeType.SINGLETHREADED:
                        return(K_medoids.Singlethreaded(mathSet, options));

                    case ModeType.MULTITHREADED:
                        return(K_medoids.Multithreaded(mathSet, options));

                    default:
                        throw new ArgumentException("был выбран неприемлемый параметр из enum AlgoritmType");
                    }
                }
                throw new ArgumentException("количество точек с данными в input Set должно быть больше или равно количества кластеров в options");
            }
            throw new ArgumentNullException("входной набор данных inputSet равен null");
        }
示例#6
0
        internal static ClusteringResult Multithreaded(IMathSet mathSet, ClusteringOptions options)
        {
            // выбор метрики для расчета:
            Func <IMathPoint, IMathPoint, Double> func = DataMiningMath.UsedMetrics(options.Distance);

            // построение всех medoids для входного набора данных:
            Double[][] allMedoids = new Double[mathSet.RowsCount][];
            Parallel.For(0, mathSet.RowsCount, (Int32 row) => {
                allMedoids[row] = new Double[mathSet.RowsCount];
                for (int col = 0; col < mathSet.RowsCount; col++)
                {
                    if (row != col)
                    {
                        allMedoids[row][col] = func(mathSet[row], mathSet[col]);
                    }
                }
            });

            // выбор центров кластеризации (случайная инициализация):
            Random random = new Random();
            Dictionary <String, Int32>         cIndexes       = new Dictionary <String, Int32>(options.ClusterCount);
            Dictionary <String, List <Int32> > cDistributions = new Dictionary <String, List <Int32> >();

            for (Int32 i = 0; i < options.ClusterCount; i++)
            {
                String name = "Cluster " + (i + 1);
                cIndexes.Add(name, random.Next(mathSet.RowsCount));
                cDistributions.Add(name, new List <Int32>());
            }

            // первый этап: предварительное связывание точек с центрами:
            Double newCost = 0;

            Parallel.For(0, mathSet.RowsCount, (Int32 row) => {
                String name        = "";
                Double minDistance = Double.MaxValue;

                // обход центров кластеризации:
                foreach (KeyValuePair <String, Int32> cluster in cIndexes)
                {
                    if (minDistance > allMedoids[row][cluster.Value])
                    {
                        name        = cluster.Key;
                        minDistance = allMedoids[row][cluster.Value];
                    }
                }

                lock (cDistributions)
                {
                    newCost += minDistance;        // подсчет текущей стоймости
                    cDistributions[name].Add(row); // добавить точку в распределение
                }
            });

            // основной цикл обработки:
            Int32  iteration = 0;
            Double prevCost;

            while (iteration++ <= options.MaxIterations)
            {
                // выбрать новые центры из ранее полученного распределения:
                prevCost = newCost;
                newCost  = 0;
                Dictionary <String, Int32>         newIndexes      = new Dictionary <string, int>(options.ClusterCount);
                Dictionary <String, List <Int32> > newDistribution = new Dictionary <String, List <Int32> >();
                foreach (KeyValuePair <string, int> cIndex in cIndexes)
                {
                    newIndexes.Add(cIndex.Key, cDistributions[cIndex.Key][random.Next(cDistributions[cIndex.Key].Count)]);
                    newDistribution.Add(cIndex.Key, new List <Int32>());
                }

                // повторное связывание:
                Parallel.For(0, mathSet.RowsCount, (Int32 row) => {
                    String name        = "";
                    Double minDistance = Double.MaxValue;

                    // обход центров кластеризации:
                    foreach (KeyValuePair <String, Int32> cluster in newIndexes)
                    {
                        if (minDistance > allMedoids[row][cluster.Value])
                        {
                            name        = cluster.Key;
                            minDistance = allMedoids[row][cluster.Value];
                        }
                    }

                    lock (newDistribution)
                    {
                        newCost += minDistance;         // подсчет текущей стоймости
                        newDistribution[name].Add(row); // добавить точку в распределение
                    }
                });

                // проверка на выход из цикла:
                Double dCost = newCost - prevCost;
                if (dCost > 0)
                {
                    break;
                }
                cDistributions = newDistribution;
                cIndexes       = newIndexes;
            }

            // маркировка данных по кластера:
            Parallel.ForEach(cDistributions, (KeyValuePair <string, List <int> > distribution) => {
                foreach (Int32 index in distribution.Value)
                {
                    mathSet[index].Cluster = distribution.Key;
                }
            });

            // получение центро клстеризации:
            List <IMathPoint> centers = new List <IMathPoint>();

            foreach (KeyValuePair <string, int> index in cIndexes)
            {
                centers.Add(mathSet[index.Value]);
            }

            return(new ClusteringResult(centers, mathSet, iteration));
        }
示例#7
0
 internal void AddMathSet(IMathSet set)
 {
     this.m_mathSet = set;
     this.m_cResult = null;
 }
示例#8
0
 public ClusteringResult(List <IMathPoint> centers, IMathSet mathSet, Int32 iteration)
 {
     this.Centers          = centers;
     this.MathSet          = mathSet;
     this.IterationCounter = iteration;
 }
        internal static ClusteringResult Multithreaded(IMathSet mathSet, ClusteringOptions options)
        {
            // выбор метрики для расчета:
            Func <IMathPoint, IMathPoint, Double> func = DataMiningMath.UsedMetrics(options.Distance);

            // инициализация центров кластеров для текущего шага расчета:
            List <IMathPoint> currentCenters = InitCenters(mathSet, options);

            // инициализация центров кластеров для предыдущего шага расчета:
            List <IMathPoint> prevCenters = new List <IMathPoint>(options.ClusterCount);

            // основной цикл обработки:
            Int32 iteration = 0;

            while (iteration++ <= options.MaxIterations)
            {
                // вычисление самого удачного центра для кластеров на рассматриваемой иттерации:
                Parallel.For(0, mathSet.RowsCount, (Int32 r) =>
                {
                    // поиск ближайшего кластера к точке:
                    Int32 closestIdx   = -1;
                    Double minDistance = Double.MaxValue;
                    for (Int32 i = 0; i < currentCenters.Count; i++)
                    {
                        Double distance = func(mathSet[r], currentCenters[i]);
                        if (minDistance > distance)
                        {
                            closestIdx  = i;
                            minDistance = distance;
                        }
                    }

                    // обновляем центр выбраного кластера:
                    lock (currentCenters)
                    {
                        currentCenters[closestIdx] = DataMiningMath.MeanPoint(mathSet[r], currentCenters[closestIdx]);
                    }
                });

                // кластеризация данных в соответствии с новыми центрами:
                Parallel.For(0, mathSet.RowsCount, (Int32 r) =>
                {
                    // поиск ближайшего кластера к точке:
                    IMathPoint closestCluster = null;
                    Double minDistance        = Double.MaxValue;
                    for (Int32 i = 0; i < currentCenters.Count; i++)
                    {
                        Double distance = func(mathSet[r], currentCenters[i]);
                        if (minDistance > distance)
                        {
                            closestCluster = currentCenters[i];
                            minDistance    = distance;
                        }
                    }

                    // обновить кластер у точки:
                    mathSet[r].Cluster = closestCluster.Cluster;
                });

                // проверка на выход из цикла:
                if (prevCenters.Count != 0)
                {
                    Boolean flag = true; // флаг прерывания расчета
                    // обход центров кластеризации:
                    for (Int32 i = 0; i < currentCenters.Count; i++)
                    {
                        // обход координат:
                        for (Int32 c = 0; c < currentCenters[i].CoordinatesCount; c++)
                        {
                            if (currentCenters[i][c] != prevCenters[i][c])
                            {
                                flag = false;
                                break;
                            }
                        }
                    }

                    if (flag)
                    {
                        break;
                    }
                }
                prevCenters = new List <IMathPoint>(currentCenters);
            }
            return(new ClusteringResult(currentCenters, mathSet, iteration));
        }
 public void AddMathSet(IMathSet set)
 {
     this.m_mathSet = set;
     this.m_cResult = null;
 }
示例#11
0
 public static String MathSetToJson(IMathSet mathSet)
 {
     return(DataSetSerializer.SetToJson(mathSet.SerializableSet));
 }