Общая структура программы
Общая структура демонстрационной программы с рис. 1 с небольшими правками показана на рис. 3. С помощью Visual Studio 2010 я создал новое консольное приложение на C# под названием «ClusteringKMeans»; для работы с этим проектом подойдет любая недавняя версия Visual Studio. В окне Solution Explorer я переименовал файл Program.cs в ClusteringKMeansProgram.cs, что автоматически повлекло переименование класса, генерируемого шаблоном. Я удалил ненужные выражения using в начале файла.
Рис. 3. Общая структура программы
1. using System;
2. namespace ClusteringKMeans
3. {
4. class ClusteringKMeansProgram
5. {
6. static void Main(string[] args)
7. {
Try
9. {
10. Console.WriteLine("\nBegin outlier data detection demo\n");
11. Console.WriteLine("Loading all (height-weight) data into memory");
12. string[] attributes = new string[] { "Height", "Weight" };
13. double[][] rawData = new double[20][];
14. rawData[0] = new double[] { 65.0, 220.0 };
15. rawData[1] = new double[] { 73.0, 160.0 };
16. rawData[2] = new double[] { 59.0, 110.0 };
17. rawData[3] = new double[] { 61.0, 120.0 };
18. rawData[4] = new double[] { 75.0, 150.0 };
19. rawData[5] = new double[] { 67.0, 240.0 };
20. rawData[6] = new double[] { 68.0, 230.0 };
21. rawData[7] = new double[] { 70.0, 220.0 };
22. rawData[8] = new double[] { 62.0, 130.0 };
23. rawData[9] = new double[] { 66.0, 210.0 };
24. rawData[10] = new double[] { 77.0, 190.0 };
25. rawData[11] = new double[] { 75.0, 180.0 };
26. rawData[12] = new double[] { 74.0, 170.0 };
27. rawData[13] = new double[] { 70.0, 210.0 };
28. rawData[14] = new double[] { 61.0, 110.0 };
29. rawData[15] = new double[] { 58.0, 100.0 };
30. rawData[16] = new double[] { 66.0, 230.0 };
31. rawData[17] = new double[] { 59.0, 120.0 };
32. rawData[18] = new double[] { 68.0, 210.0 };
33. rawData[19] = new double[] { 61.0, 130.0 };
34. Console.WriteLine("\nRaw data:\n");
35. ShowMatrix(rawData, rawData.Length, true);
36. int numAttributes = attributes.Length;
37. int numClusters = 3;
38. int maxCount = 30;
39. Console.WriteLine("\nk = " + numClusters + " and maxCount = " + maxCount);
40. int[] clustering = Cluster(rawData, numClusters, numAttributes, maxCount);
41. Console.WriteLine("\nClustering complete");
42. Console.WriteLine("\nClustering in internal format: \n");
43. ShowVector(clustering, true);
44. Console.WriteLine("\nClustered data:");
45. ShowClustering(rawData, numClusters, clustering, true);
46. double[] outlier = Outlier(rawData, clustering, numClusters, 0);
47. Console.WriteLine("Outlier for cluster 0 is:");
48. ShowVector(outlier, true);
49. Console.WriteLine("\nEnd demo\n");
50. }
51. catch (Exception ex)
52. {
53. Console.WriteLine(ex.Message);
54. }
55. } // Main
56. // Здесь находятся 14 определений статических методов
57. }
58. }
Для простоты я использовал подход со статическими методами и убрал всю проверку на ошибки. Первая часть демонстрационного кода подготавливает данные по росту и весу к кластеризации. Поскольку последовательностей всего 20, я «зашил» эти данные в код и помещаю их в памяти в виде массива rawData. Обычно данные хранятся в текстовом файле или SQL-таблице. В таких случаях вы должны написать вспомогательную функцию для загрузки данных в память. Если ваш источник данных слишком велик, вам придется модифицировать код так, чтобы он перебирал источник внешних данных, а не массив.
По крайней мере в принципе, алгоритм k-средних довольно прост. Но, как вы еще увидите, некоторые детали реализации весьма изощренные.
После подготовки исходных данных демонстрационная программа вызывает вспомогательную функцию ShowMatrix для отображения данных. Затем переменным numAttributes, numClusters и maxCount присваиваются значения 2 (height и weight), 3 и 30 соответственно. Вспомните, что maxCount ограничивает число итераций основного цикла обработки алгоритма. Алгоритм k-средних имеет тенденцию к быстрому схождению, но вам может понадобиться немного поэкспериментировать со значением maxCount.
Вся работа по кластеризации выполняется методом Cluster. Этот метод возвращает массив типа int, который определяет, как каждая последовательность назначается одному кластеру. По окончании демонстрационная программа сообщает о кластеризации и отображает исходные данные, сгруппированные по кластерам.
Демонстрационная программа заканчивает анализом кластеризованных данных на выпадающие, возможно, аномальные последовательности, используя метод Outliers. Этот метод принимает идентификатор кластера и возвращает значения из последовательности данных, которые находятся дальше всего (по евклидовой метрике) от центра масс кластера (наиболее репрезентативной последовательности). В данном случае для кластера 0 выпадающей последовательностью является (67.0, 240.0).