《mahout in action》第六章。

datafile/cluster/simple_k-means.txt数据集例如以下:

1 1
2 1
1 2
2 2
3 3
8 8
8 9
9 8
9 9

1. k-means聚类算法原理

1、从D中随机取k个元素。作为k个簇的各自的中心。

2、分别计算剩下的元素到k个簇中心的相异度,将这些元素分别划归到相异度最低的簇。

3、依据聚类结果。又一次计算k个簇各自的中心,计算方法是取簇中全部元素各自维度的算术平均数。

4、将D中所有元素依照新的中心又一次聚类。

5、反复第4步,直到聚类结果不再变化。

6、将结果输出。

2. 举例说明


2.1 从D中随机取k个元素,作为k个簇的各自的中心。

private final static Integer K=2; //选K=2,也就是估算有两个簇。
以下选1 1,2,1两个点。

C0:1 1

C1:2 1

2.2 分别计算剩下的元素到k个簇中心的相异度,将这些元素分别划归到相异度最低的簇。

结果为:
C0 : 1 1
C0:的点为:1.0,2.0
C1: 2 1
C1:的点为:2.0,2.0
C1:的点为:3.0,3.0
C1:的点为:8.0,8.0
C1:的点为:8.0,9.0
C1:的点为:9.0,8.0
C1:的点为:9.0,9.0


2.3 依据2.2的聚类结果。又一次计算k个簇各自的中心,计算方法是取簇中全部元素各自维度的算术平均数。

採取欧区距离公式。
C0 新的簇心为:1.0,1.5

C1 新的簇心为:5.857142857142857,5.714285714285714

2.4 将D中所有元素依照新的中心又一次聚类。

第2次迭代
C0:的点为:1.0,1.0
C0:的点为:2.0,1.0
C0:的点为:1.0,2.0
C0:的点为:2.0,2.0
C0:的点为:3.0,3.0
C1:的点为:8.0,8.0
C1:的点为:8.0,9.0
C1:的点为:9.0,8.0
C1:的点为:9.0,9.0

2.5  反复第4步,直到聚类结果不再变化。

当距离小于某个值的时候。就觉得聚类已经聚类了。不须要再迭代,这里的值选0.001
private final static Double converge=0.001;

------------------------------------------------
C0的簇心为:1.6666666666666667,1.75
C1的簇心为:7.971428571428572,7.942857142857143
各个簇心移动中最小的距离为,move=0.7120003121097943
第3次迭代
C0:的点为:1.0,1.0
C0:的点为:2.0,1.0
C0:的点为:1.0,2.0
C0:的点为:2.0,2.0
C0:的点为:3.0,3.0
C1:的点为:8.0,8.0
C1:的点为:8.0,9.0
C1:的点为:9.0,8.0
C1:的点为:9.0,9.0
------------------------------------------------
C0的簇心为:1.777777777777778,1.7916666666666667
C1的簇心为:8.394285714285715,8.388571428571428
各个簇心移动中最小的距离为。move=0.11866671868496578
第4次迭代
C0:的点为:1.0,1.0
C0:的点为:2.0,1.0
C0:的点为:1.0,2.0
C0:的点为:2.0,2.0
C0:的点为:3.0,3.0
C1:的点为:8.0,8.0
C1:的点为:8.0,9.0
C1:的点为:9.0,8.0
C1:的点为:9.0,9.0
------------------------------------------------
C0的簇心为:1.7962962962962965,1.7986111111111114
C1的簇心为:8.478857142857143,8.477714285714285
各个簇心移动中最小的距离为,move=0.019777786447494432
第5次迭代
C0:的点为:1.0,1.0
C0:的点为:2.0,1.0
C0:的点为:1.0,2.0
C0:的点为:2.0,2.0
C0:的点为:3.0,3.0
C1:的点为:8.0,8.0
C1:的点为:8.0,9.0
C1:的点为:9.0,8.0
C1:的点为:9.0,9.0
------------------------------------------------
C0的簇心为:1.799382716049383,1.7997685185185184
C1的簇心为:8.495771428571429,8.495542857142857
各个簇心移动中最小的距离为。move=0.003296297741248916
第6次迭代
C0:的点为:1.0,1.0
C0:的点为:2.0,1.0
C0:的点为:1.0,2.0
C0:的点为:2.0,2.0
C0:的点为:3.0,3.0
C1:的点为:8.0,8.0
C1:的点为:8.0,9.0
C1:的点为:9.0,8.0
C1:的点为:9.0,9.0
------------------------------------------------
C0的簇心为:1.7998971193415638,1.7999614197530864
C1的簇心为:8.499154285714287,8.499108571428572
各个簇心移动中最小的距离为。move=5.49382956874724E-4

3. JAVA实现

package mysequence.machineleaning.clustering.kmeans;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Vector; import mysequence.machineleaning.clustering.canopy.Point; public class MyKmeans { static Vector<Point> li=new Vector<Point>();
//static List<Point> li=new ArrayList<Point>();
static List<Vector<Point>> list=new ArrayList<Vector<Point>>(); //每次迭代保存结果,一个vector代表一个簇
private final static Integer K=2; //选K=2,也就是估算有两个簇。
private final static Double converge=0.001; //当距离小于某个值的时候。就觉得聚类已经聚类了,不须要再迭代,这里的值选0.001 //读取数据
public static final void readF1() throws IOException {
String filePath="datafile/cluster/simple_k-means.txt";
BufferedReader br = new BufferedReader(new InputStreamReader(
new FileInputStream(filePath)));
for (String line = br.readLine(); line != null; line = br.readLine()) {
if(line.length()==0||"".equals(line))continue;
String[] str=line.split(" ");
Point p0=new Point();
p0.setX(Double.valueOf(str[0]));
p0.setY(Double.valueOf(str[1]));
li.add(p0);
//System.out.println(line);
}
br.close();
}
//math.sqrt(double n)
//扩展下。假设要给m开n次方就用java.lang.StrictMath.pow(m,1.0/n);
//採用欧氏距离
public static Double DistanceMeasure(Point p1,Point p2){ Double tmp=StrictMath.pow(p2.getX()-p1.getX(), 2)+StrictMath.pow(p2.getY()-p1.getY(), 2);
return Math.sqrt(tmp);
} //计算新的簇心
public static Double CalCentroid(){
System.out.println("------------------------------------------------");
Double movedist=Double.MAX_VALUE;
for(int i=0;i<list.size();i++){
Vector<Point> subli=list.get(i);
Point po=new Point();
Double sumX=0.0;
Double sumY=0.0;
Double Clusterlen=Double.valueOf(subli.size());
for(int j=0;j<Clusterlen;j++){
Point nextp=subli.get(j);
sumX=sumX+nextp.getX();
sumY=sumY+nextp.getY();
}
po.setX(sumX/Clusterlen);
po.setY(sumY/Clusterlen);
//新的点与旧点之间的距离
Double dist=DistanceMeasure(subli.get(0),po);
//在多个簇心移动的过程中,返回移动距离最小的值
if(dist<movedist)movedist=dist;
list.get(i).clear();
list.get(i).add(po);
System.out.println("C"+i+"的簇心为:"+po.getX()+","+po.getY());
}
String test="ll";
return movedist;
}
//本次的簇心
//下一次移动的簇心 private static Double move=Double.MAX_VALUE;//移动距离
//不断地迭代,直到收敛
public static void RecursionKluster(){
for(int times=2;move>converge;times++){
System.out.println("第"+times+"次迭代");
//默认每个list里的Vector第0个元素是质心
for(int i=0;i<li.size();i++){
Point p=new Point();
p=li.get(i);
int index = -1; double neardist = Double.MAX_VALUE;
for(int k=0;k<K;k++){
Point centre=list.get(k).get(0);
double currentdist=DistanceMeasure(p,centre);
if(currentdist<neardist){
neardist=currentdist;
index=k;
}
} System.out.println("C"+index+":的点为:"+p.getX()+","+p.getY());
list.get(index).add(p); }
//又一次计算簇心,并返回移动的距离,最小的那个距离 move=CalCentroid();
System.out.println("各个簇心移动中最小的距离为。move="+move);
}
} public static void Kluster(){ for(int k=0;k<K;k++){
Vector<Point> vect=new Vector<Point>();
Point p=new Point();
p=li.get(k);
vect.add(p);
list.add(vect);
}
System.out.println("第1次迭代");
//默认每个list里的Vector第0个元素是质心
for(int i=K;i<li.size();i++){
Point p=new Point();
p=li.get(i);
int index = -1; double neardist = Double.MAX_VALUE;
for(int k=0;k<K;k++){
Point centre=list.get(k).get(0);
double currentdist=DistanceMeasure(p,centre);
if(currentdist<neardist){
neardist=currentdist;
index=k;
}
} System.out.println("C"+index+":的点为:"+p.getX()+","+p.getY());
list.get(index).add(p); } } public static void main(String[] args) throws IOException {
// TODO Auto-generated method stub
//读取数据
readF1();
//第一次迭代
Kluster();
//第一次迭代后计算簇心
CalCentroid();
//不断迭代,直到收敛
RecursionKluster();
} }

4.执行结果:

C0:1 1

C1:2 1
第1次迭代

C0:的点为:1.0,2.0

C1:的点为:2.0,2.0

C1:的点为:3.0,3.0

C1:的点为:8.0,8.0

C1:的点为:8.0,9.0

C1:的点为:9.0,8.0

C1:的点为:9.0,9.0

------------------------------------------------

C0的簇心为:1.0,1.5

C1的簇心为:5.857142857142857,5.714285714285714

第2次迭代

C0:的点为:1.0,1.0

C0:的点为:2.0,1.0

C0:的点为:1.0,2.0

C0:的点为:2.0,2.0

C0:的点为:3.0,3.0

C1:的点为:8.0,8.0

C1:的点为:8.0,9.0

C1:的点为:9.0,8.0

C1:的点为:9.0,9.0

------------------------------------------------

C0的簇心为:1.6666666666666667,1.75

C1的簇心为:7.971428571428572,7.942857142857143

各个簇心移动中最小的距离为,move=0.7120003121097943

第3次迭代

C0:的点为:1.0,1.0

C0:的点为:2.0,1.0

C0:的点为:1.0,2.0

C0:的点为:2.0,2.0

C0:的点为:3.0,3.0

C1:的点为:8.0,8.0

C1:的点为:8.0,9.0

C1:的点为:9.0,8.0

C1:的点为:9.0,9.0

------------------------------------------------

C0的簇心为:1.777777777777778,1.7916666666666667

C1的簇心为:8.394285714285715,8.388571428571428

各个簇心移动中最小的距离为。move=0.11866671868496578

第4次迭代

C0:的点为:1.0,1.0

C0:的点为:2.0,1.0

C0:的点为:1.0,2.0

C0:的点为:2.0,2.0

C0:的点为:3.0,3.0

C1:的点为:8.0,8.0

C1:的点为:8.0,9.0

C1:的点为:9.0,8.0

C1:的点为:9.0,9.0

------------------------------------------------

C0的簇心为:1.7962962962962965,1.7986111111111114

C1的簇心为:8.478857142857143,8.477714285714285

各个簇心移动中最小的距离为。move=0.019777786447494432

第5次迭代

C0:的点为:1.0,1.0

C0:的点为:2.0,1.0

C0:的点为:1.0,2.0

C0:的点为:2.0,2.0

C0:的点为:3.0,3.0

C1:的点为:8.0,8.0

C1:的点为:8.0,9.0

C1:的点为:9.0,8.0

C1:的点为:9.0,9.0

------------------------------------------------

C0的簇心为:1.799382716049383,1.7997685185185184

C1的簇心为:8.495771428571429,8.495542857142857

各个簇心移动中最小的距离为。move=0.003296297741248916

第6次迭代

C0:的点为:1.0,1.0

C0:的点为:2.0,1.0

C0:的点为:1.0,2.0

C0:的点为:2.0,2.0

C0:的点为:3.0,3.0

C1:的点为:8.0,8.0

C1:的点为:8.0,9.0

C1:的点为:9.0,8.0

C1:的点为:9.0,9.0

------------------------------------------------

C0的簇心为:1.7998971193415638,1.7999614197530864

C1的簇心为:8.499154285714287,8.499108571428572

各个簇心移动中最小的距离为。move=5.49382956874724E-4

k-means聚类JAVA实例的更多相关文章

  1. 机器学习实战5:k-means聚类:二分k均值聚类+地理位置聚簇实例

    k-均值聚类是非监督学习的一种,输入必须指定聚簇中心个数k.k均值是基于相似度的聚类,为没有标签的一簇实例分为一类. 一 经典的k-均值聚类 思路: 1 随机创建k个质心(k必须指定,二维的很容易确定 ...

  2. 【转】算法杂货铺——k均值聚类(K-means)

    k均值聚类(K-means) 4.1.摘要 在前面的文章中,介绍了三种常见的分类算法.分类作为一种监督学习方法,要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别与之对应.但是很多时 ...

  3. 5-Spark高级数据分析-第五章 基于K均值聚类的网络流量异常检测

    据我们所知,有‘已知的已知’,有些事,我们知道我们知道:我们也知道,有 ‘已知的未知’,也就是说,有些事,我们现在知道我们不知道.但是,同样存在‘不知的不知’——有些事,我们不知道我们不知道. 上一章 ...

  4. 第十篇:K均值聚类(KMeans)

    前言 本文讲解如何使用R语言进行 KMeans 均值聚类分析,并以一个关于人口出生率死亡率的实例演示具体分析步骤. 聚类分析总体流程 1. 载入并了解数据集:2. 调用聚类函数进行聚类:3. 查看聚类 ...

  5. (ZT)算法杂货铺——k均值聚类(K-means)

    https://www.cnblogs.com/leoo2sk/category/273456.html 4.1.摘要 在前面的文章中,介绍了三种常见的分类算法.分类作为一种监督学习方法,要求必须事先 ...

  6. ML: 聚类算法-K均值聚类

    基于划分方法聚类算法R包: K-均值聚类(K-means)                   stats::kmeans().fpc::kmeansruns() K-中心点聚类(K-Medoids) ...

  7. Java-Runoob-高级教程-实例-方法:10. Java 实例 – 标签(Label)

    ylbtech-Java-Runoob-高级教程-实例-方法:10. Java 实例 – 标签(Label) 1.返回顶部 1. Java 实例 - 标签(Label)  Java 实例 Java 中 ...

  8. Java-Runoob-高级教程-实例-时间处理:04. Java 实例 - 时间戳转换成时间

    ylbtech-Java-Runoob-高级教程-实例-时间处理:04. Java 实例 - 时间戳转换成时间 1.返回顶部 1. Java 实例 - 时间戳转换成时间  Java 实例 以下实例演示 ...

  9. Java-Runoob-高级教程-实例-数组:10. Java 实例 – 查找数组中的重复元素-un

    ylbtech-Java-Runoob-高级教程-实例-数组:10. Java 实例 – 查找数组中的重复元素 1.返回顶部 1. Java 实例 - 查找数组中的重复元素  Java 实例 以下实例 ...

随机推荐

  1. CDB和PDB基本管理

    CDB和PDB基本管理 这篇文章主要介绍CDB和PDB的基本管理,资料来源oracle官方. 基本概念: Multitenant Environment:多租户环境 CDB(Container Dat ...

  2. 基类,派生类,内存分配情况 .xml

    pre{ line-height:1; color:#1e1e1e; background-color:#d2d2d2; font-size:16px;}.sysFunc{color:#627cf6; ...

  3. C#面向对象基础01

    面向对象不是取代面向过程的类.对象."人"是类,"张三"是人这个类的对象.类是抽象的,对象是具体的.按钮就是类,某个按钮就是对象.对象可以叫做类的实例.类就像i ...

  4. failback 和failover

    dubbo 和motan都有在注册中心中都有这个概念 Failover 失效转移通俗地说,即当A无法为客户服务时,系统能够自动地切换,使B能够及时地顶上继续为客户提供服务,且客户感觉不到这个为他提供服 ...

  5. Flex里的命名空间,fx、mx、s【转】

    Flex 4带给我们的,是全新的命名空间.了解这些命名空间必定是一件好事情.Flex 4有三个非常重要的命名空间,分别是: xmlns:fx=”http://ns.adobe.com/mxml/200 ...

  6. webservice注释

    @WebService 1.serviceName: 对外发布的服务名,指定 Web Service 的服务名称:wsdl:service.缺省值为 Java 类的简单名称 + Service.(字符 ...

  7. Spark RDD概念学习系列之RDD的缺点(二)

        RDD的缺点? RDD是Spark最基本也是最根本的数据抽象,它具备像MapReduce等数据流模型的容错性,并且允许开发人员在大型集群上执行基于内存的计算. 为了有效地实现容错,(详细见ht ...

  8. cocos2dx使用了第三方库照样移植android平台-解决iconv库的移植问题

    当我写这篇文章的时候我是怀着激动的心情的,因为我又解决了一个技术问题.你可能对题目还一知半解,这是什么意思,我之所以要写这篇文章就是要解决当我们在cocos2dx中使用了第三方库的时候,移植到andr ...

  9. Flex布局如何让子类在超出边界时隐藏掉

    在flex4中,因为必须添加<s:Scroller>标签才能出现滚动条,如果一个容器例如Panel没有添加滚动条,那么添加到Panel中的child的位置如果超出了Panel的边界,那么这 ...

  10. C#中字符串与byte[]相互转换

    字符串转换为byte[] 给定一个string,转换为byte[],有以下几种方法. 方法1: static byte[] GetBytes(string str) { byte[] bytes = ...