2017年5月28日 星期日

K-means


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace SimpleKmean
{
    class Program
    {
        static int LoopCount = 1;
        static bool RecursiveFlag = false;
        static void Main(string[] args)
        {
            int[,] Nodes;
            int[,] Classes;
            System.Console.Write("how many nodes do you want? :");
          //  int NodeNumber = Convert.ToInt32(System.Console.ReadLine());
            int NodeNumber = 15;
            System.Console.Write("how many classes do you want? :");
         //   int ClassNumber = Convert.ToInt32(System.Console.ReadLine());
            int ClassNumber = 3;
            Nodes = new int[NodeNumber, 3]; // index -> x = 0 , y = 1 , classFlag = 3
            Classes = new int[NodeNumber, 2]; // classnumber coordinate , clustering coordinates
            Console.WriteLine();
           
            // get random coordinates
            //隨機產生15個點
            for (int i = 0; i < NodeNumber; i++)
            {               
                Random Random = new Random((int)DateTime.Now.Millisecond);
                Thread.Sleep(20);  //亂數的產生
                // get x
                Nodes[i, 0] = Random.Next(0, 10);              
                // get y
                Nodes[i, 1] = Random.Next(0, 10);
                System.Console.WriteLine("({0},{1})", Nodes[i, 0], Nodes[i, 1]);               
            }
            System.Console.WriteLine("-----------------");
           
            // get random class
            // 隨機產生class位置
            for (int i = 0; i < ClassNumber; i++)
            {
                Random random = new Random((int)DateTime.Now.Millisecond);
                Thread.Sleep(20);  //亂數的產生
                // get x
                Classes[i, 0] = random.Next(0, 10);               
                // get y
                Classes[i, 1] = random.Next(0, 10);
                System.Console.WriteLine("class[{0}]--({1},{2})", i, Classes[i, 0], Classes[i, 1]);
            }
            System.Console.WriteLine("---------------------------------------------------");
            Console.WriteLine("\n");

            Kmean(NodeNumber, ClassNumber, Nodes, Classes);           
            System.Console.WriteLine("=================================");
            System.Console.WriteLine("finish! recusive times : {0}", LoopCount);
           // ShowResult(Nodes, NodeNumber, Classes, ClassNumber);
            System.Console.WriteLine("Press any key to continue...");
            System.Console.ReadKey();
        }

        // use the euclidean distane to calculate two coordinates.
        // 勾股定理計算距離
        static double Distance(int x1, int y1, int x2, int y2)
        {
            return Math.Sqrt(Math.Pow((x1 - x2), 2) + Math.Pow((y1 - y2), 2));
        }

        // procedure that show the group
        //顯示每組產生的過程
        static void ShowResult(int[,] Nodes, int NodeNumber, int[,] Classes, int ClassNumber)
        {
            for (int i = 0; i < ClassNumber; i++)
            {
                System.Console.WriteLine("class[{0}]--({1},{2})", i, Classes[i, 0], Classes[i, 1]);
            }
            System.Console.WriteLine("-------------------");
            for (int i = 0; i < NodeNumber; i++)
            {
                System.Console.WriteLine("({0},{1}) --> class[{2}]", Nodes[i, 0], Nodes[i, 1], Nodes[i, 2]);
            }
        }

        // K-means Algorithm
        //Kmeans計算
        static void Kmean(int NodeNumber, int ClassNumber, int[,] Nodes, int[,] Classes)
        {
            // calculate the distance between the class and the coordinate .
            for (int i = 0; i < NodeNumber; i++)
            {
                double min = 100000;
                for (int j = 0; j < ClassNumber; j++)
                {
                    double mindDistance = Distance(Nodes[i, 0], Nodes[i, 1], Classes[j, 0], Classes[j, 1]);
                    if (mindDistance < min)
                    {
                        min = mindDistance;
                        Nodes[i, 2] = j; // flag to set the group that the coordinate belong to.
                    }
                }
            }

           // ShowResult(Nodes, NodeNumber, Classes, ClassNumber);

            // calculate the new center class
            //

            int[,] TempClasses = new int[ClassNumber, 3];
            for (int j = 0; j < ClassNumber; j++)
            {
                int[] TempCoordinate = new int[2];
                for (int i = 0; i < NodeNumber; i++)
                {
                    if (Nodes[i, 2] == j)
                    {
                        // new class
                        TempCoordinate[0] += Nodes[i, 0];
                        TempCoordinate[1] += Nodes[i, 1];
                        TempClasses[j, 2]++;
                    }
                }
                if (TempClasses[j, 2] == 0)TempClasses[j, 2] = 1; //除法分母不為0
                TempClasses[j, 0] = TempCoordinate[0] / TempClasses[j, 2];
                TempClasses[j, 1] = TempCoordinate[1] / TempClasses[j, 2];
                System.Console.WriteLine("count = {3},class[{0}] :new cor ({1},{2})", j, TempClasses[j, 0], TempClasses[j, 1], TempClasses[j, 2]);
            }
            Console.WriteLine();
            int k = 0;
            for (k = 0; k < ClassNumber; k++)
            {
                if ((TempClasses[k, 0] != Classes[k, 0]) || (TempClasses[k, 1] != Classes[k, 1]))
                {
                    RecursiveFlag = true;
                    break;
                }
            }
            if (k == ClassNumber) RecursiveFlag = false;
            if (RecursiveFlag == true)   //New classes center point
            {
                for (int j = 0; j < ClassNumber; j++)
                {
                    Classes[j, 0] = TempClasses[j, 0];
                    Classes[j, 1] = TempClasses[j, 1];
                }
            //    System.Console.ReadKey();
                // recursive
                Kmean(NodeNumber, ClassNumber, Nodes, Classes);
                LoopCount++;
            }
            if (RecursiveFlag == false)
            {
      //          ShowResult(Nodes, NodeNumber, Classes, ClassNumber);
            }
        }
    }


    // procedure for check the same coordinates

}

沒有留言:

張貼留言

WinFormTb02

https://drive.google.com/drive/u/0/folders/1UwS9FZ3ELCOK6SAwirHrkxq3z_RSbxJt https://www.youtube.com/watch?v=k7IkIeww_U0&list=PLumjEWemD...