Kmeans聚类算法 java精简版设计实现编程

网上有许多Kmeans写的java算法,当然依据个人编码风格的不同,导致编写出来的代码,各有不同。所以在理解原理的基础上,最好就是按照自己设计思路将代码自己写出来。

度娘搜Kmeans的基本原理吧,直接上代码,代码中都有注释:

package net.codeal.suanfa.kmeans;

import java.util.Set;

/**
 *
 * @ClassName: Distancable
 * @Description: TODO(可计算两点之间距离的可中心化的父类)
 * @author fuhuaguo
 * @date 2015年9月1日 上午11:41:23
 *
 */
public class Kmeansable<E> {

	/**
	 * 获取两点之间的距离
	 * @param other
	 * @return
	 */
	public double getDistance(E other){
		return 0;
	}
	/**
	 * 获取新的中心点
	 * @param eSet
	 * @return
	 */
	public E getNewCenter(Set<E> eSet){
		return null;
	}
}
package net.codeal.suanfa.kmeans;

import java.util.Set;

/**
 *
 * @ClassName: Point
 * @Description: TODO(聚类的维度信息bean,可以分为K个维度,相似度计算是自身行为,放在bean内部才合适,取消注解使用)
 * @author fuhuaguo
 * @email [email protected]
 * @date 2015年9月1日 上午10:43:25
 *
 */
public class Point extends Kmeansable<Point>{

	private String id;
	//维度1
	private double k1;
	//维度2
	private double k2;
	//维度3
	private double k3;
	public Point() {
	}
	public Point(String id,double k1,double k2,double k3) {
		this.id = id;
		this.k1 = k1;
		this.k2 = k2;
		this.k3 = k3;
	}

	/**
	 * 计算和另一个点的距离,采用欧几里得算法 ,计算维度算数平方和的sqrt值,即:相异度
	 * @param other
	 * @return
	 */
	@Override
	public double getDistance(Point other){
		return Math.sqrt((this.k1-other.getK1())*(this.k1-other.getK1())
		+ (this.k2-other.getK2())*(this.k2-other.getK2())
		+ (this.k3-other.getK3())*(this.k3-other.getK3()));
	}
	@Override
	public Point getNewCenter(Set<Point> eSet) {
		if(eSet == null || eSet.size() == 0){
			return this;
		}
		Point temp = new Point();
		int count = 0;
		for (Point p : eSet) {
			temp.setK1(temp.getK1() + p.getK1());
			temp.setK2(temp.getK2() + p.getK2());
			temp.setK3(temp.getK3() + p.getK3());
			count++;
		}
		temp.setK1(temp.getK1()/count);
		temp.setK2(temp.getK2()/count);
		temp.setK3(temp.getK3()/count);

		return temp;
	}

	@Override
	public boolean equals(Object obj) {
		if(obj == null || !(obj instanceof Point))
			return false;
		Point other = (Point) obj;

		return (this.k1 == other.getK1()) && (this.k2 == other.getK2()) && (this.k3 == other.getK3());
	}

	@Override
	public int hashCode() {
		return new Double(k1+k2+k3).hashCode();
	}
	@Override
	public String toString() {
		return "("+k1+","+k2+","+k3+")";
	}
	public String getId() {
		return id;
	}
	public void setId(String id) {
		this.id = id;
	}
	public double getK1() {
		return k1;
	}
	public void setK1(double k1) {
		this.k1 = k1;
	}
	public double getK2() {
		return k2;
	}
	public void setK2(double k2) {
		this.k2 = k2;
	}
	public double getK3() {
		return k3;
	}
	public void setK3(double k3) {
		this.k3 = k3;
	}
}
package net.codeal.suanfa.kmeans;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class KmeansAlgorithm<E extends Kmeansable<E>> {

	/**
	 * 对Set进行K个值聚类,计算深度最大为depth
	 */
	public void kmeans(Set<E> dataSet, int k, int depth){
		//分类数设置不合适
		if(k <= 1 || dataSet.size() <= k){
			return;
		}
		Set<E> kSet = new HashSet<E>();

		int count = 0;
		//随机确定K个中心点
		for (E e : dataSet) {
			if(count++ >= k)
				break;
			kSet.add(e);
		}
		//计算每个值距离各个中心点的距离,分配到距离最小的那个中心上
		boolean flag = true;
		while(flag && depth > 0){
			Map<E, Set<E>> kMap = new HashMap<E, Set<E>>();
			for (E e : kSet) {
				kMap.put(e, new HashSet<E>());
			}
			//完成聚类
			for (E data : dataSet) {
				double d = Double.MAX_VALUE;
				E e = null;
				for (E center : kSet) {
					double d1 = data.getDistance(center);
					if (d > d1){
						e = center;
						d = d1;
					}
				}
				kMap.get(e).add(data);
			}
			//第一组计算完毕,同时获取新的中心点
			System.out.println("这是第"+depth+"次聚类");
			for (Map.Entry<E, Set<E>> m : kMap.entrySet()) {
				System.out.println(m.getKey()+":"+m.getValue());
			}
			//获取新的聚类中心
			Set<E> oldSet = kSet;
			kSet = getNewCenters(kMap);
			flag = !isSameCenters(kSet,oldSet);

			depth--;
		}
	}
	/**
	 * 获取新的中心点 列表
	 */
	public Set<E> getNewCenters(Map<E, Set<E>> kMap){
		Set<E> eSet = new HashSet<E>();

		for (Map.Entry<E, Set<E>> m : kMap.entrySet()) {
			eSet.add(m.getKey().getNewCenter(m.getValue()));
		}

		return eSet;
	}
	/**
	 * 判断是否为同一个中心列表
	 */
	public boolean isSameCenters(Set<E> oldSet,Set<E> newSet){
		//两个集合只要交集为0就是相同的
		return oldSet.containsAll(newSet);
	}
	public static void main(String[] args) {
		Set<Point> dataSet = new HashSet<Point>();
		dataSet.add(new Point("1",1,1,1));
		dataSet.add(new Point("1",2,2,2));
		dataSet.add(new Point("1",5,6,1));
		dataSet.add(new Point("1",10,10,10));
		dataSet.add(new Point("1",11,11,11));

		new KmeansAlgorithm<Point>().kmeans(dataSet, 2,10);
	}
}

结果:

这是第10次聚类

(1.0,1.0,1.0):[(1.0,1.0,1.0), (2.0,2.0,2.0), (5.0,6.0,1.0)]

(10.0,10.0,10.0):[(10.0,10.0,10.0), (11.0,11.0,11.0)]

这是第9次聚类

(10.5,10.5,10.5):[(10.0,10.0,10.0), (11.0,11.0,11.0)]

(2.6666666666666665,3.0,1.3333333333333333):[(1.0,1.0,1.0), (2.0,2.0,2.0), (5.0,6.0,1.0)]

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-28 11:05:51

Kmeans聚类算法 java精简版设计实现编程的相关文章

Kmeans聚类算法原理与实现

Kmeans聚类算法 1 Kmeans聚类算法的基本原理 K-means算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一.K-means算法的基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类.通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果. 假设要把样本集分为k个类别,算法描述如下: (1)适当选择k个类的初始中心,最初一般为随机选取: (2)在每次迭代中,对任意一个样本,分别求其到k个中心的欧式距离,将该样本归到距离最短的中心所在的类: (3)利用

孙其功陪你学之——Spark MLlib之K-Means聚类算法

看到 程序员的自我修养 – SelfUp.cn 里面有Spark MLlib之K-Means聚类算法. 但是是java 语言的,于是我按照例程用Scala写了一个,分享在此. 由于在学习 spark mllib 但是如此详细的资料真的很难找,在此分享. 测试数据 0.0 0.0 0.0 0.1 0.1 0.1 0.2 0.2 0.2 9.0 9.0 9.0 9.1 9.1 9.1 9.2 9.2 9.2 15.1 15.1 15.1 18.0 17.0 19.0 20.0 21.0 22.0 p

03-01 K-Means聚类算法

目录 K-Means聚类算法 一.K-Means聚类算法学习目标 二.K-Means聚类算法详解 2.1 K-Means聚类算法原理 2.2 K-Means聚类算法和KNN 三.传统的K-Means聚类算法流程 3.1 输入 3.2 输出 3.3 流程 四.K-Means初始化优化之K-Means++ 五.K-Means距离计算优化之elkan K-Means 六.大数据优化之Mini Batch K-Means 七.K-Means聚类算法优缺点 7.1 优点 7.2 缺点 八.小结 更新.更全

Spark MLlib KMeans聚类算法

1.1 KMeans聚类算法 1.1.1 基础理论 KMeans算法的基本思想是初始随机给定K个簇中心,按照最邻近原则把待分类样本点分到各个簇.然后按平均法重新计算各个簇的质心,从而确定新的簇心.一直迭代,直到簇心的移动距离小于某个给定的值. K-Means聚类算法主要分为三个步骤: (1)第一步是为待聚类的点寻找聚类中心: (2)第二步是计算每个点到聚类中心的距离,将每个点聚类到离该点最近的聚类中去: (3)第三步是计算每个聚类中所有点的坐标平均值,并将这个平均值作为新的聚类中心: 反复执行(

K-Means 聚类算法

K-Means 概念定义: K-Means 是一种基于距离的排他的聚类划分方法. 上面的 K-Means 描述中包含了几个概念: 聚类(Clustering):K-Means 是一种聚类分析(Cluster Analysis)方法.聚类就是将数据对象分组成为多个类或者簇 (Cluster),使得在同一个簇中的对象之间具有较高的相似度,而不同簇中的对象差别较大. 划分(Partitioning):聚类可以基于划分,也可以基于分层.划分即将对象划分成不同的簇,而分层是将对象分等级. 排他(Exclu

k-means聚类算法python实现

K-means聚类算法 算法优缺点: 优点:容易实现缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢使用数据类型:数值型数据 算法思想 k-means算法实际上就是通过计算不同样本间的距离来判断他们的相近关系的,相近的就会放到同一个类别中去. 1.首先我们需要选择一个k值,也就是我们希望把数据分成多少类,这里k值的选择对结果的影响很大,Ng的课说的选择方法有两种一种是elbow method,简单的说就是根据聚类的结果和k的函数关系判断k为多少的时候效果最好.另一种则是根据具体的需求确定,比

视觉SLAM之词袋(bag of words) 模型与K-means聚类算法浅析(2)

聚类概念: 聚类:简单地说就是把相似的东西分到一组.同 Classification (分类)不同,分类应属于监督学习.而在聚类的时候,我们并不关心某一类是什么,我们需要实现的目标只是把相似的东西聚到一起,因此,一个聚类算法通常只需要知道如何计算相似 度就可以开始工作了.聚类不需要使用训练数据进行学习,应属于无监督学习. 我们经常接触到的聚类分析,一般都是数值聚类,一种常见的做法是同时提取 N 种特征,将它们放在一起组成一个 N 维向量,从而得到一个从原始数据集合到 N 维向量空间的映射,然后基

视觉SLAM之词袋(bag of words) 模型与K-means聚类算法浅析(1)

在目前实际的视觉SLAM中,闭环检测多采用DBOW2模型https://github.com/dorian3d/DBoW2,而bag of words 又运用了数据挖掘的K-means聚类算法,笔者只通过bag of words 模型用在图像处理中进行形象讲解,并没有涉及太多对SLAM的闭环检测的应用. 1.Bag-of-words模型简介 Bag-of-words模型是信息检索领域常用的文档表示方法.在信息检索中,BOW模型假定对于一个文档,忽略它的单词顺序和语法.句法等要素,将其仅仅看作是若

沙湖王 | 用Scipy实现K-means聚类算法

沙湖王 | 用Scipy实现K-means聚类算法 用Scipy实现K-means聚类算法沙湖王 | 用Scipy实现K-means聚类算法,布布扣,bubuko.com