k-means聚类算法的java实现
来源:互联网 发布:网络最热门表情包 编辑:程序博客网 时间:2024/06/06 09:36
聚类就是按照某个特定标准(如距离准则)把一个数据集分割成不同的类或簇,使得同一个簇内的数据对象的相似性尽可能大,同时不在同一个簇中的数据对象的差异性也尽可能地大。即聚类后同一类的数据尽可能聚集到一起,不同数据尽量分离。
聚类技术[2]正在蓬勃发展,对此有贡献的研究领域包括数据挖掘、统计学、机器学习、空间数据库技术、生物学以及市场营销等。各种聚类方法也被不断提出和改进,而不同的方法适合于不同类型的数据,因此对各种聚类方法、聚类效果的比较成为值得研究的课题。
在数据分析的术语之中,聚类和分类是两种技术。分类是指我们已经知道了事物的类别,需要从样品中学习分类的规则,是一种有指导学习;而聚类则是由我们来给定简单的规则,从而得到分类,是一种无指导学习。两者可以说是相反的过程。
K-means聚类算法过程如下:
1、选取K个点作为初始质心(随机);
2、对每个样本分别计算到K个质心的相似度或距离,将该样本划分到相似度最高或距离最短的质心所在类;
3、对该轮计算结果,计算每一个类别的质心,新的质心作为下一轮的质心;
4、判断算法是否满足终止条件(即:前后两个质心数组中前一组的质心是否在后一个质心组出现),满足则结束,否则继续2、3、4;
测试文本如下:
A 2 3
B 2 7
C 1 2
D 1 6
E 2 1
F 3 5
G 8 5
H 9 6
I 7 7
J 7 4
K 8 2
L 8 22
M 8 19
N 7 21
O 7 17
P 9 20
代码实现n个点的聚类:
public class Point { private double X; private double Y; private String name; public String getName() { return name; } public void setName(String name) { this.name = name; } public double getX() { return X; } public void setX(double x) { X = x; } public double getY() { return Y; } public void setY(double y) { Y = y; } @Override public boolean equals(Object obj) { Point point = (Point) obj; if (this.getX() == point.getX() && this.getY() == point.getY()) { return true; } return false; } @Override public String toString() { return "(" + X + "," + Y + ")"; } @Override public int hashCode() { return (int) (X+Y); } }K-means聚类如下:
public class KmeansClustering {private List<Point> dataset = null;public KmeansClustering() throws IOException {initDataSet();}/** * 初始化数据集 * * @throws IOException */private void initDataSet() throws IOException {dataset = new ArrayList<Point>();BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(KmeansClustering.class.getClassLoader().getResourceAsStream("data.txt")));String line = null;while ((line = bufferedReader.readLine()) != null) {String[] s = line.split("\t");Point point = new Point();point.setX(Double.parseDouble(s[1]));point.setY(Double.parseDouble(s[2]));point.setName(s[0]);dataset.add(point);}}/** * @param k * 聚类的数目 */public Map<Point, List<Point>> kcluster(int k) {// 随机从样本集合中选取k个样本点作为聚簇中心// 每个聚簇中心有哪些点Map<Point, List<Point>> nowClusterCenterMap = new HashMap<Point, List<Point>>();for (int i = 0; i < k; i++) {Random random = new Random();int num = random.nextInt(dataset.size());nowClusterCenterMap.put(dataset.get(num), new ArrayList<Point>());}// 上一次的聚簇中心Map<Point, List<Point>> lastClusterCenterMap = null;// 找到离中心最近的点,然后加入以该中心为map键的list中while (true) {for (Point point : dataset) {double shortest = Double.MAX_VALUE;Point key = null;for (Entry<Point, List<Point>> entry : nowClusterCenterMap.entrySet()) {double distance = distance(point, entry.getKey());if (distance < shortest) {shortest = distance;key = entry.getKey();}}nowClusterCenterMap.get(key).add(point);}// 如果结果与上一次相同,则整个过程结束if (isEqualCenter(lastClusterCenterMap, nowClusterCenterMap)) {break;}lastClusterCenterMap = nowClusterCenterMap;nowClusterCenterMap = new HashMap<Point, List<Point>>();// 把中心点移到其所有成员的平均位置处,并构建新的聚簇中心for (Entry<Point, List<Point>> entry : lastClusterCenterMap.entrySet()) {nowClusterCenterMap.put(getNewCenterPoint(entry.getValue()),new ArrayList<Point>());}}return nowClusterCenterMap;}/** * 判断前后两次是否是相同的聚簇中心,若是则程序结束,否则继续,直到相同 * * @param lastClusterCenterMap * @param nowClusterCenterMap * @return bool */private boolean isEqualCenter(Map<Point, List<Point>> lastClusterCenterMap, Map<Point, List<Point>> nowClusterCenterMap) {if (lastClusterCenterMap == null) {return false;} else {for (Entry<Point, List<Point>> entry : lastClusterCenterMap.entrySet()) {if (!nowClusterCenterMap.containsKey(entry.getKey())) {return false;}}}return true;}/** * 计算新的中心 * * @param value * @return Point */private Point getNewCenterPoint(List<Point> value) {double sumX = 0.0, sumY = 0.0;for (Point point : value) {sumX += point.getX();sumY += point.getY();}Point point = new Point();point.setX(sumX / value.size());point.setY(sumY / value.size());return point;}/** * 使用欧几里得算法计算两点之间距离 * * @param point1 * @param point2 * @return 两点之间距离 */private double distance(Point point1, Point point2) {double distance = Math.pow((point1.getX() - point2.getX()), 2) + Math.pow((point1.getY() - point2.getY()), 2);distance = Math.sqrt(distance);return distance;}public static void main(String[] args) throws IOException {KmeansClustering kmeansClustering = new KmeansClustering();Map<Point, List<Point>> result = kmeansClustering.kcluster(3);for (Entry<Point, List<Point>> entry : result.entrySet()) {System.out.println("===============聚簇中心为:" + entry.getKey() + "================");for (Point point : entry.getValue()) {System.out.println(point.getName());}}}}
聚类结果每次会受K值的影响,结果可能会产生不同。几个聚类结果如下:
第一次结果:
===============聚簇中心为:(4.545454545454546,4.363636363636363)================
A
B
C
D
E
F
G
H
I
J
K
===============聚簇中心为:(7.5,18.0)================
M
O
===============聚簇中心为:(8.0,21.0)================
L
N
P
第二次结果:
===============聚簇中心为:(1.8333333333333333,4.0)================
A
B
C
D
E
F
===============聚簇中心为:(7.8,19.8)================
L
M
N
O
P
===============聚簇中心为:(7.8,4.8)================
G
H
I
J
K
第三次结果:
===============聚簇中心为:(1.8333333333333333,4.0)================
A
B
C
D
E
F
===============聚簇中心为:(7.8,19.8)================
L
M
N
O
P
===============聚簇中心为:(7.8,4.8)================
G
H
I
J
K
- 【JAVA实现】K-means聚类算法
- K-Means聚类算法java实现
- k-means聚类算法的java实现
- K-Means聚类算法的实现
- K-means聚类的java实现
- 用java实现K-means算法,k-means聚类算法原理
- k-means算法的java实现
- java实现k-means算法
- K-Means算法Java实现
- K-means算法(Java实现)
- 聚类算法之K-means算法-UCI数据集上的java实现
- Matlab实现k-means聚类算法
- K-Means聚类算法 --Matlab实现
- 聚类算法-K-means-C++实现
- Python实现K-Means聚类算法
- k-means聚类算法python实现
- C#实现简单的K-means聚类算法
- 关于k-means聚类算法的matlab实现
- H5音频<audio/>样式修改,拖拽、点击进度操作、总时长加载
- CMake交叉编译配置
- 在table tr td表格中让英文数字超出一定宽度换行的解决办法
- mvc框架和spring概述
- Android Studio还不知道的一些快捷键
- k-means聚类算法的java实现
- 装饰者设计模式
- mysql悲观锁总结和实践
- React-classnames库
- 表格存储在QCon2017的分享
- MSP430平台下实现Si4432的收发数据
- Netty 时间轮算法实现HashedWheelTimer
- Linux搭建邮件服务器
- SpringBoot整合Netty