转自:http://blog.csdn.net/cyxlzzs/article/details/7416491

算法——K均值聚类算法(Java实现)

分类:javaalgorithm

(19921)  (2)

1、用途:聚类算法通常用于数据挖掘,将相似的数组进行聚簇

2、原理:网上比较多,可以百度或者google一下

3、实现:Java代码如下

[java] view plain copy
  1. package org.algorithm;
  2. import java.util.ArrayList;
  3. import java.util.Random;
  4. /**
  5. * K均值聚类算法
  6. */
  7. public class Kmeans {
  8. private int k;// 分成多少簇
  9. private int m;// 迭代次数
  10. private int dataSetLength;// 数据集元素个数,即数据集的长度
  11. private ArrayList<float[]> dataSet;// 数据集链表
  12. private ArrayList<float[]> center;// 中心链表
  13. private ArrayList<ArrayList<float[]>> cluster; // 簇
  14. private ArrayList<Float> jc;// 误差平方和,k越接近dataSetLength,误差越小
  15. private Random random;
  16. /**
  17. * 设置需分组的原始数据集
  18. *
  19. * @param dataSet
  20. */
  21. public void setDataSet(ArrayList<float[]> dataSet) {
  22. this.dataSet = dataSet;
  23. }
  24. /**
  25. * 获取结果分组
  26. *
  27. * @return 结果集
  28. */
  29. public ArrayList<ArrayList<float[]>> getCluster() {
  30. return cluster;
  31. }
  32. /**
  33. * 构造函数,传入需要分成的簇数量
  34. *
  35. * @param k
  36. *            簇数量,若k<=0时,设置为1,若k大于数据源的长度时,置为数据源的长度
  37. */
  38. public Kmeans(int k) {
  39. if (k <= 0) {
  40. k = 1;
  41. }
  42. this.k = k;
  43. }
  44. /**
  45. * 初始化
  46. */
  47. private void init() {
  48. m = 0;
  49. random = new Random();
  50. if (dataSet == null || dataSet.size() == 0) {
  51. initDataSet();
  52. }
  53. dataSetLength = dataSet.size();
  54. if (k > dataSetLength) {
  55. k = dataSetLength;
  56. }
  57. center = initCenters();
  58. cluster = initCluster();
  59. jc = new ArrayList<Float>();
  60. }
  61. /**
  62. * 如果调用者未初始化数据集,则采用内部测试数据集
  63. */
  64. private void initDataSet() {
  65. dataSet = new ArrayList<float[]>();
  66. // 其中{6,3}是一样的,所以长度为15的数据集分成14簇和15簇的误差都为0
  67. float[][] dataSetArray = new float[][] { { 8, 2 }, { 3, 4 }, { 2, 5 },
  68. { 4, 2 }, { 7, 3 }, { 6, 2 }, { 4, 7 }, { 6, 3 }, { 5, 3 },
  69. { 6, 3 }, { 6, 9 }, { 1, 6 }, { 3, 9 }, { 4, 1 }, { 8, 6 } };
  70. for (int i = 0; i < dataSetArray.length; i++) {
  71. dataSet.add(dataSetArray[i]);
  72. }
  73. }
  74. /**
  75. * 初始化中心数据链表,分成多少簇就有多少个中心点
  76. *
  77. * @return 中心点集
  78. */
  79. private ArrayList<float[]> initCenters() {
  80. ArrayList<float[]> center = new ArrayList<float[]>();
  81. int[] randoms = new int[k];
  82. boolean flag;
  83. int temp = random.nextInt(dataSetLength);
  84. randoms[0] = temp;
  85. for (int i = 1; i < k; i++) {
  86. flag = true;
  87. while (flag) {
  88. temp = random.nextInt(dataSetLength);
  89. int j = 0;
  90. // 不清楚for循环导致j无法加1
  91. // for(j=0;j<i;++j)
  92. // {
  93. // if(temp==randoms[j]);
  94. // {
  95. // break;
  96. // }
  97. // }
  98. while (j < i) {
  99. if (temp == randoms[j]) {
  100. break;
  101. }
  102. j++;
  103. }
  104. if (j == i) {
  105. flag = false;
  106. }
  107. }
  108. randoms[i] = temp;
  109. }
  110. // 测试随机数生成情况
  111. // for(int i=0;i<k;i++)
  112. // {
  113. // System.out.println("test1:randoms["+i+"]="+randoms[i]);
  114. // }
  115. // System.out.println();
  116. for (int i = 0; i < k; i++) {
  117. center.add(dataSet.get(randoms[i]));// 生成初始化中心链表
  118. }
  119. return center;
  120. }
  121. /**
  122. * 初始化簇集合
  123. *
  124. * @return 一个分为k簇的空数据的簇集合
  125. */
  126. private ArrayList<ArrayList<float[]>> initCluster() {
  127. ArrayList<ArrayList<float[]>> cluster = new ArrayList<ArrayList<float[]>>();
  128. for (int i = 0; i < k; i++) {
  129. cluster.add(new ArrayList<float[]>());
  130. }
  131. return cluster;
  132. }
  133. /**
  134. * 计算两个点之间的距离
  135. *
  136. * @param element
  137. *            点1
  138. * @param center
  139. *            点2
  140. * @return 距离
  141. */
  142. private float distance(float[] element, float[] center) {
  143. float distance = 0.0f;
  144. float x = element[0] - center[0];
  145. float y = element[1] - center[1];
  146. float z = x * x + y * y;
  147. distance = (float) Math.sqrt(z);
  148. return distance;
  149. }
  150. /**
  151. * 获取距离集合中最小距离的位置
  152. *
  153. * @param distance
  154. *            距离数组
  155. * @return 最小距离在距离数组中的位置
  156. */
  157. private int minDistance(float[] distance) {
  158. float minDistance = distance[0];
  159. int minLocation = 0;
  160. for (int i = 1; i < distance.length; i++) {
  161. if (distance[i] < minDistance) {
  162. minDistance = distance[i];
  163. minLocation = i;
  164. } else if (distance[i] == minDistance) // 如果相等,随机返回一个位置
  165. {
  166. if (random.nextInt(10) < 5) {
  167. minLocation = i;
  168. }
  169. }
  170. }
  171. return minLocation;
  172. }
  173. /**
  174. * 核心,将当前元素放到最小距离中心相关的簇中
  175. */
  176. private void clusterSet() {
  177. float[] distance = new float[k];
  178. for (int i = 0; i < dataSetLength; i++) {
  179. for (int j = 0; j < k; j++) {
  180. distance[j] = distance(dataSet.get(i), center.get(j));
  181. // System.out.println("test2:"+"dataSet["+i+"],center["+j+"],distance="+distance[j]);
  182. }
  183. int minLocation = minDistance(distance);
  184. // System.out.println("test3:"+"dataSet["+i+"],minLocation="+minLocation);
  185. // System.out.println();
  186. cluster.get(minLocation).add(dataSet.get(i));// 核心,将当前元素放到最小距离中心相关的簇中
  187. }
  188. }
  189. /**
  190. * 求两点误差平方的方法
  191. *
  192. * @param element
  193. *            点1
  194. * @param center
  195. *            点2
  196. * @return 误差平方
  197. */
  198. private float errorSquare(float[] element, float[] center) {
  199. float x = element[0] - center[0];
  200. float y = element[1] - center[1];
  201. float errSquare = x * x + y * y;
  202. return errSquare;
  203. }
  204. /**
  205. * 计算误差平方和准则函数方法
  206. */
  207. private void countRule() {
  208. float jcF = 0;
  209. for (int i = 0; i < cluster.size(); i++) {
  210. for (int j = 0; j < cluster.get(i).size(); j++) {
  211. jcF += errorSquare(cluster.get(i).get(j), center.get(i));
  212. }
  213. }
  214. jc.add(jcF);
  215. }
  216. /**
  217. * 设置新的簇中心方法
  218. */
  219. private void setNewCenter() {
  220. for (int i = 0; i < k; i++) {
  221. int n = cluster.get(i).size();
  222. if (n != 0) {
  223. float[] newCenter = { 0, 0 };
  224. for (int j = 0; j < n; j++) {
  225. newCenter[0] += cluster.get(i).get(j)[0];
  226. newCenter[1] += cluster.get(i).get(j)[1];
  227. }
  228. // 设置一个平均值
  229. newCenter[0] = newCenter[0] / n;
  230. newCenter[1] = newCenter[1] / n;
  231. center.set(i, newCenter);
  232. }
  233. }
  234. }
  235. /**
  236. * 打印数据,测试用
  237. *
  238. * @param dataArray
  239. *            数据集
  240. * @param dataArrayName
  241. *            数据集名称
  242. */
  243. public void printDataArray(ArrayList<float[]> dataArray,
  244. String dataArrayName) {
  245. for (int i = 0; i < dataArray.size(); i++) {
  246. System.out.println("print:" + dataArrayName + "[" + i + "]={"
  247. + dataArray.get(i)[0] + "," + dataArray.get(i)[1] + "}");
  248. }
  249. System.out.println("===================================");
  250. }
  251. /**
  252. * Kmeans算法核心过程方法
  253. */
  254. private void kmeans() {
  255. init();
  256. // printDataArray(dataSet,"initDataSet");
  257. // printDataArray(center,"initCenter");
  258. // 循环分组,直到误差不变为止
  259. while (true) {
  260. clusterSet();
  261. // for(int i=0;i<cluster.size();i++)
  262. // {
  263. // printDataArray(cluster.get(i),"cluster["+i+"]");
  264. // }
  265. countRule();
  266. // System.out.println("count:"+"jc["+m+"]="+jc.get(m));
  267. // System.out.println();
  268. // 误差不变了,分组完成
  269. if (m != 0) {
  270. if (jc.get(m) - jc.get(m - 1) == 0) {
  271. break;
  272. }
  273. }
  274. setNewCenter();
  275. // printDataArray(center,"newCenter");
  276. m++;
  277. cluster.clear();
  278. cluster = initCluster();
  279. }
  280. // System.out.println("note:the times of repeat:m="+m);//输出迭代次数
  281. }
  282. /**
  283. * 执行算法
  284. */
  285. public void execute() {
  286. long startTime = System.currentTimeMillis();
  287. System.out.println("kmeans begins");
  288. kmeans();
  289. long endTime = System.currentTimeMillis();
  290. System.out.println("kmeans running time=" + (endTime - startTime)
  291. + "ms");
  292. System.out.println("kmeans ends");
  293. System.out.println();
  294. }
  295. }

4、说明:具体代码是从网上找的,根据自己的理解加了注释和进行部分修改,若注释有误还望指正

5、测试

[java] view plain copy
  1. package org.test;
  2. import java.util.ArrayList;
  3. import org.algorithm.Kmeans;
  4. public class KmeansTest {
  5. public  static void main(String[] args)
  6. {
  7. //初始化一个Kmean对象,将k置为10
  8. Kmeans k=new Kmeans(10);
  9. ArrayList<float[]> dataSet=new ArrayList<float[]>();
  10. dataSet.add(new float[]{1,2});
  11. dataSet.add(new float[]{3,3});
  12. dataSet.add(new float[]{3,4});
  13. dataSet.add(new float[]{5,6});
  14. dataSet.add(new float[]{8,9});
  15. dataSet.add(new float[]{4,5});
  16. dataSet.add(new float[]{6,4});
  17. dataSet.add(new float[]{3,9});
  18. dataSet.add(new float[]{5,9});
  19. dataSet.add(new float[]{4,2});
  20. dataSet.add(new float[]{1,9});
  21. dataSet.add(new float[]{7,8});
  22. //设置原始数据集
  23. k.setDataSet(dataSet);
  24. //执行算法
  25. k.execute();
  26. //得到聚类结果
  27. ArrayList<ArrayList<float[]>> cluster=k.getCluster();
  28. //查看结果
  29. for(int i=0;i<cluster.size();i++)
  30. {
  31. k.printDataArray(cluster.get(i), "cluster["+i+"]");
  32. }
  33. }
  34. }

6、总结:测试代码已经通过。并对聚类的结果进行了查看,结果基本上符合要求。至于有没有更精确的算法有待发现。具体的实践还有待挖掘

算法——K均值聚类算法(Java实现)相关推荐

  1. matlab实现k-l算法,K均值聚类算法的MATLAB实现

    K-means算法是最简单的一种聚类算法.算法的目的是使各个样本与所在类均值的误差平方和达到最小(这也是评价K-means算法最后聚类效果的评价标准) K-means聚类算法的一般步骤: 初始化.输入 ...

  2. Thinking in SQL系列之五:数据挖掘K均值聚类算法与城市分级

    原创: 牛超   2017-02-21   Mail:10867910@qq.com 引言:前一篇文章开始不再介绍简单算法,而是转到数据挖掘之旅.感谢CSDN将我前一篇机器学习C4.5决策树算法的博文 ...

  3. K-Means(K均值聚类算法)

    K-Means(K均值聚类算法) 1.前言 要学习聚类算法就要知道聚类学习算法是什么,为什么要学习聚类学习聚类学习算法,有什么用途,下面就简单的做一下介绍,并且详细的说明k-means均值聚类学习算法 ...

  4. 【模式识别】K均值聚类算法应用实验报告及MATLAB仿真

    一. 实验目的 1.掌握K均值聚类算法的原理和实现过程: 2.掌握K均值聚类算法的应用方法. 二. 实验内容 1.彩色图像分割 选择一幅图像,分别按三种颜色数进行彩色图像分割的结果(原图和分割图).步 ...

  5. k均值聚类算法优缺点_Grasshopper实现K均值聚类算法

    本文很长很长,有很多很多图,包含以下部分: 1.算法简介 2.如何分类平面点 3.如何分类空间点 4.如何分类多维数据 5.后记 提醒:以下内容包括:智障操作,无中生友,重复造轮子 等 1.算法简介 ...

  6. K均值聚类算法(HCM,K-Means)

    K均值聚类核心思想如下: 算法把n个向量分为个组,并求每组的聚类中心,使得非相似性(或距离)指标的价值函数(或目标函数)达到最小.当选择欧几里德距离为组j中向量与相应聚类中心间的非相似性指标时,价值函 ...

  7. K均值聚类算法(Kmeans)讲解及源码实现

    K均值聚类算法(Kmeans)讲解及源码实现 算法核心 K均值聚类的核心目标是将给定的数据集划分成K个簇,并给出每个数据对应的簇中心点.算法的具体步骤描述如下. 数据预处理,如归一化.离群点处理等. ...

  8. k均值聚类算法python_K均值和其他聚类算法:Python快速入门

    k均值聚类算法python This post was originally published here 这篇文章最初发表在这里 Clustering is the grouping of obje ...

  9. python(scikit-learn)实现k均值聚类算法

    k均值聚类算法原理详解 示例为链接中的例题 直接调用python机器学习的库scikit-learn中k均值算法的相关方法 from sklearn.cluster import KMeans imp ...

  10. 机器学习之无监督学习-K均值聚类算法

    机器学习之无监督学习-K均值聚类算法 对于无监督学习,有两类重要的应用,一个是聚类,一个是降维.我们今天主要学习聚类中的K均值聚类. 我们先看看下图,图a为原始的数据点,我们想要对图a的数据点进行分类 ...

最新文章

  1. 使用vagrant基于官方的box制作自己的基础box
  2. 谈谈java面向对象之抽象,手把手带你搞定java面试之面向对象
  3. 8. An Introduction to MCMC for Machine Learning (2)
  4. 一步步教你如何用别人的无线上网,附带破解软件
  5. Cocos 2d-x 3.3版本升级 五大维度提升3D品质
  6. 命令行调用dubbo服务
  7. 《Win测试的学习笔记》——Introduction
  8. 入门 RISC-V 编程的五大技巧
  9. Async Python 竟不比sync Python 快,怎么回事?
  10. 新冠全球蔓延,AI+大数据拿什么拯救全人类? | AI 技术生态论
  11. 读书笔记:普林斯顿微积分读本
  12. C++ 双声道PCM音频分成单声道音频
  13. 大学计算机excel高级筛选,excel高级筛选的使用方法(入门 进阶 高级)
  14. (七)Kotlin简单易学 基础语法- 自定义异常与先决条件函数
  15. python笑脸猫图案_酷叮猫编程课堂:python生成字符画
  16. Kotlin扩展方法进化之Context Receiver
  17. Foreground-aware Pyramid Reconstruction for Alignment-free Occluded Person Re-identification
  18. Problem G: 零起点学算法106——首字母变大写
  19. ARP攻击原理与实践
  20. 列车运行图的编制原则是什么_列车运行图的编制有什么要求?

热门文章

  1. hdu1010 Tempter of the Bone---DFS+奇偶剪枝
  2. 数据库MySql阶段总结
  3. 电商设计中的一些概念
  4. ASP.NET MVC Framework体验(1):从一个简单实例开始(转)
  5. Android开发:setAlpha()方法
  6. codeforces 360B
  7. 使用jQuery实现网页技术(无数据库)
  8. SQL Server 2016新特性: 对JSON的支持
  9. VIM设置-发现VIM的美
  10. [ios] 申请账号,发布应用