kmeans实际应用例子 java_k-means聚类JAVA实例

本文详细介绍了K-means聚类算法的原理和步骤,并通过Java代码实现了算法的具体过程,包括初始化簇心、迭代调整、计算簇心新位置等。在示例中,数据集被成功地分为两个簇,并在多次迭代后达到收敛。
摘要由CSDN通过智能技术生成

《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 li=new Vector();

//static List li=new ArrayList();

static List> list=new ArrayList>(); //每次迭代保存结果,一个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

Vector 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

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

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

Point p=new Point();

p=li.get(i);

int index = -1;

double neardist = Double.MAX_VALUE;

for(int k=0;k

Point centre=list.get(k).get(0);

double currentdist=DistanceMeasure(p,centre);

if(currentdist

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

Vector vect=new Vector();

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

Point p=new Point();

p=li.get(i);

int index = -1;

double neardist = Double.MAX_VALUE;

for(int k=0;k

Point centre=list.get(k).get(0);

double currentdist=DistanceMeasure(p,centre);

if(currentdist

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值