Implementasi K-Means Clustering

Posted on

Metode K-Means clustering merupakan salah satu metode yang dapat digunakan untuk mengetahui klasifikasi sekumpulan objek dengan melihat kategori / klasifikasi yang ada. Artikel tentang K-Means clustering dapat dilihat lengkap di https://fadlikadn.wordpress.com/2013/06/14/tahap-tahap-k-means-clustering/. Kali ini kita akan mencoba untuk mengimplementasikan metode K-Means Clustering menggunakan WPF (Windows Presentation Foundation) yang dibangun menggunakan bahasa pemrograman C#. Tool yang dibutuhkan adalah Visual Studio 2010 Professional atau Express.

Tahap pertama, buat form WPF dengan nama MainWindow.xaml. Pada saat membuat project WPF, VS akan secara otomatis membuat sebuah form bernama MainWindow.xaml.

Layout Form
Layout Form

<Window x:Class="KMeansWPF.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="K-Means Clustering" Height="465" Width="891" Loaded="Window_Loaded">
    <Grid Name="LayoutRoot">
        <TextBlock Height="23" HorizontalAlignment="Left" Margin="21,23,0,0" Name="textBlock1" Text="Jumlah Centroid" VerticalAlignment="Top" />
        <TextBlock Height="23" HorizontalAlignment="Left" Margin="21,52,0,0" Name="textBlock2" Text="Jumlah Variabel" VerticalAlignment="Top" Width="86" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="124,20,0,0" Name="txtNumCentroid" VerticalAlignment="Top" Width="173" ToolTip="Jumlah Centroid" Text="3" IsEnabled="False" />
        <TextBox Height="23" HorizontalAlignment="Left" Margin="124,49,0,0" Name="txtNumVariabel" VerticalAlignment="Top" Width="173" Text="3" ToolTip="Jumlah Variabel" IsEnabled="False" />
        <Button Content="Hitung Centroid" Height="26" HorizontalAlignment="Left" Margin="312,20,0,0" Name="btnHitung" VerticalAlignment="Top" Width="104" Click="btnHitung_Click" />
        <TextBox Height="33" HorizontalAlignment="Left" Margin="21,91,0,0" Name="txtBrowseFile" VerticalAlignment="Top" Width="276" />
        <Button Content="Browse" Height="34" HorizontalAlignment="Left" Margin="312,90,0,0" Name="btnBrowseFile" VerticalAlignment="Top" Width="104" Click="btnBrowseFile_Click" />
        <TextBox Margin="21,169,0,12" Name="txtIsiFile" ScrollViewer.VerticalScrollBarVisibility="Auto" HorizontalAlignment="Left" Width="394" HorizontalScrollBarVisibility="Auto" />
        <TextBlock Height="23" HorizontalAlignment="Left" Margin="21,140,0,0" Name="textBlock3" Text="Isi File" VerticalAlignment="Top" />
        <StackPanel Height="390" HorizontalAlignment="Left" Margin="437,24,0,0" Name="stackPanelCentroid" VerticalAlignment="Top" Width="275">
        </StackPanel>
        <Button Content="Clean" Height="26" HorizontalAlignment="Left" Margin="312,49,0,0" Name="btnClean" VerticalAlignment="Top" Width="104" Click="btnClean_Click" />
        <Button Content="Hitung K-Means" Height="26" HorizontalAlignment="Left" Margin="730,20,0,0" Name="btnToArray" VerticalAlignment="Top" Width="114" Click="btnToArray_Click" />
    </Grid>
</Window>

Berikutnya, buatlah sebuah class dengan nama City. Class city ini berguna untuk menyimpan informasi masing-masing kota, dengan data-data jumlah penduduk, jumlah ruang kelas, dan variabel lainnya.

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

namespace KMeansWPF
{
    //Class untuk menyimpan data kota
    public class City
    {
        public String NamaKota { get; set; }
        public Double TotalPenduduk { get; set; }
        public Double TotalKelas { get; set; }
        public Double TotalGuru { get; set; }
        public int Centroid { get; set; } //untuk menentukan Centroid 1,2, atau 3

        //constructor
        public City()
        {
        }

        public City(String namakota, Double totalpenduduk, Double totalkelas, Double totalguru)
        {
            NamaKota = namakota;
            TotalPenduduk = totalpenduduk;
            TotalKelas = totalkelas;
            TotalGuru = totalguru;
        }
    }
}

Berikutnya, tambahkan method berikut pada MainWindows.xaml.cs. File ini digunakan untuk menyimpan action dari objek-objek yang ada pada form MainWindow.xaml.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.IO;

namespace KMeansWPF
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        String[] dataBaseline;
        int numCentroid;
        int numVariabel;
        Double[] variabelList;
        List<City> cities = new List<City>();

        public MainWindow()
        {
            InitializeComponent();
        }

        private void btnBrowseFile_Click(object sender, RoutedEventArgs e)
        {
            //Create openFileDialog
            Microsoft.Win32.OpenFileDialog fileSearch = new Microsoft.Win32.OpenFileDialog();

            //Set Filter for file extension and default file extension
            fileSearch.DefaultExt = ".csv";
            fileSearch.Filter = "Comma Separated Value (.csv)|*.csv";

            //Display OpenFileDialog by calling ShowDialog method
            Nullable<bool> result = fileSearch.ShowDialog();

            //Get selected file and display content in textbox
            if (result == true)
            {
                //Open document
                String filename = fileSearch.FileName;
                String text = File.ReadAllText(filename);
                dataBaseline = File.ReadAllLines(filename);
                this.txtIsiFile.Text = text;
            }

            String message = "";

            for (int i = 0; i < dataBaseline.Length; i++)
            {
                message += dataBaseline[i] + '\n';
            }
            this.txtBrowseFile.Text = fileSearch.FileName;
            MessageBox.Show(message.ToString() + dataBaseline.Length);

            //isi dari file dimasukkan ke dalam array
            //mengetahui jumlah kolom
            String[] numCols = dataBaseline[0].Split(';');
            MessageBox.Show("Jumlah baris : " + dataBaseline.Length.ToString() + ", Jumlah Kolom : " + numCols.Length.ToString());

            //Sudah mengetahui jumlah baris dan kolom
            //menyiapkan array

            //Daftar kota disimpan pada list cities
            City kota = new City();
            for (int i = 1; i < dataBaseline.Length; i++ )
            {
                String[] detailKota = dataBaseline[i].Split(';');
                kota = new City(detailKota[2].ToString(), Double.Parse(detailKota[3].ToString()), Double.Parse(detailKota[4].ToString()), Double.Parse(detailKota[5].ToString()));
                cities.Add(kota);
            }
        }

        private void btnHitung_Click(object sender, RoutedEventArgs e)
        {
            for (int i = 1; i <= numCentroid; i++ )
            {
                Label centroid = new Label();
                centroid.Name = "lblCentroid" + i;
                centroid.Content = "Centroid " + i;
                stackPanelCentroid.Children.Add(centroid);
                for (int j = 1; j <= numVariabel; j++)
                {
                    TextBox txtVariabel = new TextBox();
                    txtVariabel.Name = "txtCentroid" + i + "Var" + j;
                    txtVariabel.ToolTip = "Variabel " + j + " Centroid " + i;
                    stackPanelCentroid.Children.Add(txtVariabel);
                }
            }
        }

        private void btnClean_Click(object sender, RoutedEventArgs e)
        {
            this.stackPanelCentroid.Children.Clear();
        }

        //function yang digunakan untuk menghitung algoritma K-Means Clustering
        public void KmeansClustering()
        {
            //Cek jumlah centroid --> numCentroid
            //Cek jumlah variabel --> numVariabel
            //array centroid
            Double[,] arrCentroid = new Double[3,3];
            Double[,] arrCentroidTemp = new Double[3, 3];
            int[] centroidKey = new int[3];
            String output = "";
            String outFull = "";
            Double[,] arrCountKMeans = new Double[cities.Count, numCentroid];
            String fileNameSave;
            //0-->Total Penduduk
            //1-->Total Ruang Kelas
            //2-->Total Guru
            //Centroid 1
            arrCentroid[0, 0] = 100000;
            arrCentroid[0, 1] = 3000;
            arrCentroid[0, 2] = 3000;
            //Centroid 2
            arrCentroid[1, 0] = 250000;
            arrCentroid[1, 1] = 7000;
            arrCentroid[1, 2] = 7000;
            //Centroid 3
            arrCentroid[2, 0] = 500000;
            arrCentroid[2, 1] = 12000;
            arrCentroid[2, 2] = 10500;

            bool finish = false;
            int numProcess = 0;

            while (finish != true)
            {
                numProcess += 1;

                for (int i = 0; i < cities.Count; i++)
                {
                    output = "";
                    for (int j = 0; j < numCentroid; j++)
                    {
                        arrCountKMeans[i, j] = Math.Sqrt(Math.Pow(cities[i].TotalPenduduk - arrCentroid[j, 0], 2) + Math.Pow(cities[i].TotalKelas - arrCentroid[j, 1], 2) + Math.Pow(cities[i].TotalGuru - arrCentroid[j, 2], 2));
                        output += arrCountKMeans[i, j].ToString() + " ";
                    }
                    outFull += cities[i].NamaKota + " " + output + "\n";
                }
                txtIsiFile.Text = outFull.ToString();

                //Check and compare Centroid1, Centroid2, Centroid3
                for (int i = 0; i < cities.Count; i++)
                {
                    if ((arrCountKMeans[i, 0] < arrCountKMeans[i, 1]) && (arrCountKMeans[i, 0] < arrCountKMeans[i, 2]))
                    {
                        cities[i].Centroid = 1;
                    }
                    else if ((arrCountKMeans[i, 1] < arrCountKMeans[i, 0]) && (arrCountKMeans[i, 1] < arrCountKMeans[i, 2]))
                    {
                        cities[i].Centroid = 2;
                    }
                    else if ((arrCountKMeans[i, 2] < arrCountKMeans[i, 0]) && (arrCountKMeans[i, 2] < arrCountKMeans[i, 1]))
                    {
                        cities[i].Centroid = 3;
                    }
                }

                centroidKey[0] = 0;
                centroidKey[1] = 0;
                centroidKey[2] = 0;

                //penentuan Centroid Baru
                //Centroid 1
                for (int i = 0; i < cities.Count; i++)
                {
                    if (cities[i].Centroid == 1)
                    {
                        arrCentroidTemp[0, 0] += cities[i].TotalPenduduk;
                        arrCentroidTemp[0, 1] += cities[i].TotalKelas;
                        arrCentroidTemp[0, 2] += cities[i].TotalGuru;
                        centroidKey[0] += 1;
                    }
                    else if (cities[i].Centroid == 2)
                    {
                        arrCentroidTemp[1, 0] += cities[i].TotalPenduduk;
                        arrCentroidTemp[1, 1] += cities[i].TotalKelas;
                        arrCentroidTemp[1, 2] += cities[i].TotalGuru;
                        centroidKey[1] += 1;
                    }
                    else if (cities[i].Centroid == 3)
                    {
                        arrCentroidTemp[2, 0] += cities[i].TotalPenduduk;
                        arrCentroidTemp[2, 1] += cities[i].TotalKelas;
                        arrCentroidTemp[2, 2] += cities[i].TotalGuru;
                        centroidKey[2] += 1;
                    }
                }

                //AVERAGE function di pencarian centroid baru
                //Centroid 1
                arrCentroidTemp[0, 0] = arrCentroidTemp[0, 0] / centroidKey[0];
                arrCentroidTemp[0, 1] = arrCentroidTemp[0, 1] / centroidKey[0];
                arrCentroidTemp[0, 2] = arrCentroidTemp[0, 2] / centroidKey[0];
                //Centroid 2
                arrCentroidTemp[1, 0] = arrCentroidTemp[1, 0] / centroidKey[1];
                arrCentroidTemp[1, 1] = arrCentroidTemp[1, 1] / centroidKey[1];
                arrCentroidTemp[1, 2] = arrCentroidTemp[1, 2] / centroidKey[1];
                //Centroid 3
                arrCentroidTemp[2, 0] = arrCentroidTemp[2, 0] / centroidKey[2];
                arrCentroidTemp[2, 1] = arrCentroidTemp[2, 1] / centroidKey[2];
                arrCentroidTemp[2, 2] = arrCentroidTemp[2, 2] / centroidKey[2];

                outFull = "Iterasi " + numProcess + "\n";
                outFull += "Centroid 1 \n";
                outFull += arrCentroidTemp[0, 0] + " ";
                outFull += arrCentroidTemp[0, 1] + " ";
                outFull += arrCentroidTemp[0, 2] + "\n";
                outFull += "Centroid 2 \n";
                outFull += arrCentroidTemp[1, 0] + " ";
                outFull += arrCentroidTemp[1, 1] + " ";
                outFull += arrCentroidTemp[1, 2] + "\n";
                outFull += "Centroid 3 \n";
                outFull += arrCentroidTemp[2, 0] + " ";
                outFull += arrCentroidTemp[2, 1] + " ";
                outFull += arrCentroidTemp[2, 2] + "\n";

                MessageBox.Show(outFull);

                if (arrCentroid[0, 0] == arrCentroidTemp[0, 0] && arrCentroid[0, 1] == arrCentroidTemp[0, 1] && arrCentroid[0, 2] == arrCentroidTemp[0, 2] &&
                    arrCentroid[1, 0] == arrCentroidTemp[1, 0] && arrCentroid[1, 1] == arrCentroidTemp[1, 1] && arrCentroid[1, 2] == arrCentroidTemp[1, 2] &&
                    arrCentroid[2, 0] == arrCentroidTemp[2, 0] && arrCentroid[2, 1] == arrCentroidTemp[2, 1] && arrCentroid[2, 2] == arrCentroidTemp[2, 2])
                {
                    finish = true;
                }

                if (finish != true)
                {
                    arrCentroid[0, 0] = arrCentroidTemp[0, 0];
                    arrCentroid[0, 1] = arrCentroidTemp[0, 1];
                    arrCentroid[0, 2] = arrCentroidTemp[0, 2];

                    arrCentroid[1, 0] = arrCentroidTemp[1, 0];
                    arrCentroid[1, 1] = arrCentroidTemp[1, 1];
                    arrCentroid[1, 2] = arrCentroidTemp[1, 2];

                    arrCentroid[2, 0] = arrCentroidTemp[2, 0];
                    arrCentroid[2, 1] = arrCentroidTemp[2, 1];
                    arrCentroid[2, 2] = arrCentroidTemp[2, 2];

                    //reset arrCentroidTemp
                    arrCentroidTemp[0, 0] = 0;
                    arrCentroidTemp[0, 1] = 0;
                    arrCentroidTemp[0, 2] = 0;

                    arrCentroidTemp[1, 0] = 0;
                    arrCentroidTemp[1, 1] = 0;
                    arrCentroidTemp[1, 2] = 0;

                    arrCentroidTemp[2, 0] = 0;
                    arrCentroidTemp[2, 1] = 0;
                    arrCentroidTemp[2, 2] = 0;
                }
            }

            outFull = "Hasil Klasifikasi Kota \n";
            String prioritas = "";

            //Menentukan kota menjadi klasifikasi prioritas pembangunan kota
            for (int i = 0; i < cities.Count; i++ )
            {
                outFull += cities[i].NamaKota + ";";
                outFull += cities[i].TotalPenduduk + ";";
                outFull += cities[i].TotalKelas + ";";
                outFull += cities[i].TotalGuru + ";";
                if (cities[i].Centroid == 1) prioritas = "1";
                else prioritas = "0";
                outFull += prioritas + " \n";
            }

            MessageBox.Show(outFull);

            //write to CSV file
            Microsoft.Win32.SaveFileDialog saveDialog = new Microsoft.Win32.SaveFileDialog();
            saveDialog.FileName = "New CSV"; //Default FileName
            saveDialog.DefaultExt = ".csv"; //Default File Extension
            saveDialog.Filter = "Comma Separated Value (.csv)|*.csv"; //Filter files by extension

            //Show save file dialog box
            Nullable<bool> result = saveDialog.ShowDialog();

            fileNameSave = "";
            //process save file dialog box results
            if (result == true)
            {
                fileNameSave = saveDialog.FileName;

                //Open file CSV
                StreamWriter objWriter;
                objWriter = new StreamWriter(fileNameSave);

                objWriter.Write(outFull);
                objWriter.Close();
            }

            txtIsiFile.Text = outFull;

        }

        private void btnToArray_Click(object sender, RoutedEventArgs e)
        {
            KmeansClustering();
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            numCentroid = Int32.Parse(this.txtNumCentroid.Text.ToString());
            numVariabel = Int32.Parse(this.txtNumVariabel.Text.ToString());
        }
    }
}

Sekarang waktunya mencoba aplikasi. Untuk itu, diperlukan dataset yang digunakan untuk processing K-Means. Dataset yang digunakan bertipe CSV (Comma Separating Value). Download di Datasetkmeans. Rename name file dataset menjadi berekstensi CSV terlebih dulu. Output dari aplikasi ini adalah file CSV yang berisi keputusan daftar kota yang direkomendasikan dilakukan pembangunan. Status 1 berarti diprioritaskan, sementara status 0 belum diprioritaskan.

Screenshot aplikasi saat dijalankan
Screenshot aplikasi saat dijalankan

Iklan

5 thoughts on “Implementasi K-Means Clustering

    Rosid Raeder said:
    4 Maret 2014 pukul 20:54

    bleh mnta aplikasi gan

    aji said:
    12 Agustus 2014 pukul 23:01

    boleh minta aplikasi mentahanya tentang data mining buat skripsi..

    razi said:
    20 November 2015 pukul 22:27
    erin said:
    19 Desember 2016 pukul 00:00

    bisa minta file datasetnya gan

    akhmad said:
    6 Juni 2017 pukul 21:23

    mas datasetkmeans nya kok corupted, bisa kirim lewat email mas??

Tinggalkan Balasan

Isikan data di bawah atau klik salah satu ikon untuk log in:

Logo WordPress.com

You are commenting using your WordPress.com account. Logout / Ubah )

Gambar Twitter

You are commenting using your Twitter account. Logout / Ubah )

Foto Facebook

You are commenting using your Facebook account. Logout / Ubah )

Foto Google+

You are commenting using your Google+ account. Logout / Ubah )

Connecting to %s