如何java编译执行行 kmeans java

Java 实现的KMeans_百度文库
两大类热门资源免费畅读
续费一年阅读会员,立省24元!
Java 实现的KMeans
&&Java 实现的 KMeans 算法, 程序运行良好 没有bug, 本人用心编写 包含注释
阅读已结束,下载文档到电脑
想免费下载本文?
定制HR最喜欢的简历
下载文档到电脑,方便使用
还剩6页未读,继续阅读
定制HR最喜欢的简历
你可能喜欢聚类算法之KMeans&Java实现&
KMeans算法的基本思想是初始随机给定K个簇中心,按照最邻近原则把待分类样本点分到各个簇。然后按平均法重新计算各个簇的质心,从而确定新的簇心。一直迭代,直到簇心的移动距离小于某个给定的值。
当初始簇心选行不好时,KMeans的结果会很差,所以一般是多运行几次,按照一定标准(比如簇内的方差最小化)选择一个比较好的结果。
下图给出对坐标点的聚类结果:
下面给出核心算法的代码:
* Author: Orisun
* Date: Sep 10, 2011
* FileName: KMeans.java
* Function:
import java.io.F
import java.util.ArrayL
import java.util.I
import java.util.R
public class KMeans {
int k; // 指定划分的簇数
// 迭代终止条件,当各个新质心相对于老质心偏移量小于mu时终止迭代
double[][] // 上一次各簇质心的位置
// 重复运行次数
double[] // 存放每次运行的满意度
public KMeans(int k, double mu, int repeat, int len) {
this.repeat =
center = new double[k][];
for (int i = 0; i & i++)
center[i] = new double[len];
crita = new double[repeat];
// 初始化k个质心,每个质心是len维的向量,每维均在left--right之间
public void initCenter(int len, ArrayList&DataObject& objects) {
Random random = new Random(System.currentTimeMillis());
int[] count = new int[k]; // 记录每个簇有多少个元素
Iterator&DataObject& iter = objects.iterator();
while (iter.hasNext()) {
DataObject object = iter.next();
int id = random.nextInt(10000)%k;
count[id]++;
for (int i = 0; i & i++)
center[id][i] += object.getVector()[i];
for (int i = 0; i & i++) {
for (int j = 0; j & j++) {
center[i][j] /= count[i];
// 把数据集中的每个点归到离它最近的那个质心
public void classify(ArrayList&DataObject& objects) {
Iterator&DataObject& iter = objects.iterator();
while (iter.hasNext()) {
DataObject object = iter.next();
double[] vector = object.getVector();
int len = vector.
int index = 0;
double neardist = Double.MAX_VALUE;
for (int i = 0; i & i++) {
// double dist = Global.calEuraDist(vector, center[i], len);
// //使用欧氏距离
double dist = Global.calEditDist(vector, center[i], len); // 使用编辑距离
if (dist & neardist) {
neardist =
object.setCid(index);
// 重新计算每个簇的质心,并判断终止条件是否满足,如果不满足更新各簇的质心,如果满足就返回true.len是数据的维数
public boolean calNewCenter(ArrayList&DataObject& objects, int len) {
boolean end = true;
int[] count = new int[k]; // 记录每个簇有多少个元素
double[][] sum = new double[k][];
for (int i = 0; i & i++)
sum[i] = new double[len];
Iterator&DataObject& iter = objects.iterator();
while (iter.hasNext()) {
DataObject object = iter.next();
int id = object.getCid();
count[id]++;
for (int i = 0; i & i++)
sum[id][i] += object.getVector()[i];
for (int i = 0; i & i++) {
if (count[i] != 0) {
for (int j = 0; j & j++) {
sum[i][j] /= count[i];
// 簇中不包含任何点,及时调整质心
int a=(i+1)%k;
int b=(i+3)%k;
int c=(i+5)%k;
for (int j = 0; j & j++) {
center[i][j] = (center[a][j]+center[b][j]+center[c][j])/3;
for (int i = 0; i & i++) {
// 只要有一个质心需要移动的距离超过了mu,就返回false
// if (Global.calEuraDist(sum[i], center[i], len) &= mu) { //使用欧氏距离
if (Global.calEditDist(sum[i], center[i], len) &= mu) { // 使用编辑距离
end = false;
if (!end) {
for (int i = 0; i & i++) {
for (int j = 0; j & j++)
center[i][j] = sum[i][j];
// 计算各簇内数据和方差的加权平均,得出本次聚类的满意度.len是数据的维数
public double getSati(ArrayList&DataObject& objects, int len) {
double satisfy = 0.0;
int[] count = new int[k];
double[] ss = new double[k];
Iterator&DataObject& iter = objects.iterator();
while (iter.hasNext()) {
DataObject object = iter.next();
int id = object.getCid();
count[id]++;
for (int i = 0; i & i++)
ss[id] += Math.pow(object.getVector()[i] - center[id][i], 2.0);
for (int i = 0; i & i++) {
satisfy += count[i] * ss[i];
public double run(int round, DataSource datasource, int len) {
System.out.println("第" + round + "次运行");
initCenter(len,datasource.objects);
classify(datasource.objects);
while (!calNewCenter(datasource.objects, len)) {
classify(datasource.objects);
datasource.printResult(datasource.objects, k);
double ss = getSati(datasource.objects, len);
System.out.println("加权方差:" + ss);
public static void main(String[] args) {
DataSource datasource = new DataSource();
datasource.readMatrix(new File("/home/orisun/test/dot.mat"));
datasource.readRLabel(new File("/home/orisun/test/dot.rlabel"));
datasource.readMatrix(new File("/home/orisun/text.normalized.mat"));
datasource.readRLabel(new File("/home/orisun/text.rlabel"));
int len = datasource.
// 划分为6个簇,质心移动小于1E-8时终止迭代,重复运行7次
KMeans km = new KMeans(4, 1E-10, 7, len);
int index = 0;
double minsa = Double.MAX_VALUE;
for (int i = 0; i & km. i++) {
double ss = km.run(i, datasource, len);
if (ss & minsa) {
System.out.println("最好的结果是第" + index + "次。");
Copyright (C) , All Rights Reserved.
版权所有 闽ICP备号
processed in 0.040 (s). 12 q(s)2558人阅读
数据挖掘/算法(2)
k-means 算法
接受参数 k ;然后将事先输入的n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。
算法是最为经典的基于划分的聚类方法,是十大经典之一。K-means算法的基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果。
假设要把样本集分为c个类别,算法描述如下:
(1)适当选择c个类的初始中心;
(2)在第k次迭代中,对任意一个样本,求其到c个中心的距离,将该样本归到距离最短的中心所在的类;
(3)利用均值等方法更新该类的中心值;
(4)对于所有的c个中心,如果利用(2)(3)的更新后,值保持不变,则迭代结束,否则继续迭代。
该算法的最大优势在于简洁和快速。算法的关键在于初始中心的选择和距离公式。
实现步骤:
&* 1. 首先是随机获取总体中的K个元素作为总体的K个中心;
&* 2. 接下来对总体中的元素进行分类,每个元素都去判断自己到K个中心的距离,并归类到最近距离中心去;
&* 3. 计算每个聚类的平均值,并作为新的中心点
&* 4. 重复2,3步骤,直到这k个中线点不再变化(收敛了),或执行了足够多的迭代
代码实现:
package com.kM
import java.util.A
import java.util.HashM
import java.util.M
import java.util.R
* k-Means算法,聚类算法;
* 实现步骤:1. 首先是随机获取总体中的K个元素作为总体的K个中心;
* 2. 接下来对总体中的元素进行分类,每个元素都去判断自己到K个中心的距离,并归类到最近距离中心去;
* 3. 计算每个聚类的平均值,并作为新的中心点
* 4. 重复2,3步骤,直到这k个中线点不再变化(收敛了),或执行了足够多的迭代
public class KMeans {
private static double[][] DATA = { { 5.1, 3.5, 1.4, 0.2},
{ 4.9, 3.0, 1.4, 0.2 },{ 4.7, 3.2, 1.3, 0.2 },
{ 4.6, 3.1, 1.5, 0.2 },{ 5.0, 3.6, 1.4, 0.2 },
{ 7.0, 3.2, 4.7, 1.4 },{ 6.4, 3.2, 4.5, 1.5 },
{ 6.9, 3.1, 4.9, 1.5 },{ 5.5, 2.3, 4.0, 1.3 },
{ 6.5, 2.8, 4.6, 1.5 },{ 5.7, 2.8, 4.5, 1.3 },
{ 6.5, 3.0, 5.8, 2.2 },{ 7.6, 3.0, 6.6, 2.1 },
{ 4.9, 2.5, 4.5, 1.7 },{ 7.3, 2.9, 6.3, 1.8 },
{ 6.7, 2.5, 5.8, 1.8 },{ 6.9, 3.1, 5.1, 2.3 } };
//k个中心点
public int[] memberS
public int[] centersI
public double[][]
public int[] elementsInC
public static void main(String[] args) {
KMeans kmeans = new KMeans(5);
String lastMembership = &&;
String nowMembership = &&;
while(true){
kmeans.randomCenters();
System.out.println(&随机选中的中心index为:&+Arrays.toString(kmeans.centersIndex));
kmeans.calMemberShip();
nowMembership = Arrays.toString(kmeans.memberShip);
System.out.println(&DATA聚类之后Membership为:&+nowMembership);
System.out.println(&Elements in centers cnt:&+Arrays.toString(kmeans.elementsInCenters));
if(nowMembership.equals(lastMembership)){
System.out.println(&本次聚类与上次相同,退出执行!&);
System.out.println(&一共聚类了 &+i+& 次!&);
kmeans.calNewCenters();
System.out.println(&新中心点为:&+Arrays.deepToString(kmeans.centers));
double totalDistance = puteTotalDistance();
System.out.println(&totalDistance : &+totalDistance);
lastMembership = nowM
System.out.println(&----------------华丽的分割线----------------&);
public KMeans(int k){
//计算临近距离
public double manhattanDistince(double []paraFirstData,double []paraSecondData){
double tempDistince = 0;
if((paraFirstData!=null && paraSecondData!=null) && paraFirstData.length==paraSecondData.length){
for(int i=0;i&paraFirstData.i++){
tempDistince += Math.abs(paraFirstData[i] - paraSecondData[i]);
System.out.println(&firstData 与 secondData 数据结构不一致&);
return tempD
public void randomCenters(){
centersIndex = new int[k];
Random random = new Random();
Map map = new HashMap();
for(int i=0;i&k;i++){
int index = Math.abs(random.nextInt())%DATA.
if(map.containsKey(index)){
//将中心点的下标存到MAP中,保证下次选出的中心点不是同一个
map.put(index, DATA[index]);
//将中心点的下标存入centers[]中
centersIndex[i] =
public void calMemberShip(){
memberShip = new int[DATA.length];
elementsInCenters = new int[k];
for(int j=0;j&DATA.j++){
double currentDistance = Double.MAX_VALUE;
int currentIndex = -1;
double[] item = DATA[j];
for(int i=0;i&k;i++){
double[] tempCentersValue = DATA[centersIndex[i]];
double distance = this.manhattanDistince(item, tempCentersValue);
if(distance&currentDistance){
currentDistance =
currentIndex =
memberShip[j] = currentI
for(int i=0;i&memberShip.i++){
elementsInCenters[memberShip[i]]++;
public void calNewCenters(){
centers = new double[k][DATA[0].length];
for(int i=0;i&memberShip.i++){
for(int j=0;j&DATA[0].j++){
centers[memberShip[i]][j] += DATA[i][j];
for(int i=0;i&centers.i++){
for(int j=0;j&DATA[0].j++){
centers[i][j] /= elementsInCenters[i];
public double computeTotalDistance() {
double tempTotal = 0;
for (int i = 0; i & DATA. i ++) {
tempTotal += manhattanDistince(DATA[i], centers[memberShip[i]]);
return tempT
运行结果截图:
从上面截图可见,执行了48083次随机质心的选取,聚类,才趋于收敛(即前后两次聚类效果没变化)。
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:38095次
排名:千里之外
原创:20篇
评论:11条
(1)(1)(1)(3)(3)(3)(2)(1)(2)(9)2310人阅读
Java编程(1)
1.K-means算法简述以及代码原型
数据挖掘中一个重要算法是K-means,我这里就不做详细介绍。如果感兴趣的话可以移步陈皓的博客: &&
&&讲得很好
& & 总的来讲,k-means聚类需要以下几个步骤:
& & & & &①.初始化数据
& & & & &②.计算初始的中心点,可以随机选择
& & & & &③.计算每个点到每个聚类中心的距离,并且划分到距离最短的聚类中心簇中
& & & & &④.计算每个聚类簇的平均值,这个均值作为新的聚类中心,重复步骤3
& & & & &⑤.如果达到最大循环或者是聚类中心不再变化或者聚类中心变化幅度小于一定范围时,停止循环。
& & 恩,原理就是这样,超级简单。但是Java算法实现起来代码量并不小。这个代码也不算是完全自己写的啦,也有些借鉴。我把k-means实现封装在了一个类里面,这样就可以随时调用了呢。
import java.util.ArrayL
import java.util.R
public class kmeans {
//迭代次数
private int dataSetL//数据集长度
private ArrayList&double[]& dataS//数据集合
private ArrayList&double[]&//中心链表
private ArrayList&ArrayList&double[]&&//簇
private ArrayList&Float&//误差平方和,这个是用来计算中心聚点的移动哦
//设置原始数据集合
public void setDataSet(ArrayList&double[]& dataSet){
this.dataSet=dataS
//获得簇分组
ArrayList&ArrayList&double[]&& getCluster(){
return this.
//构造函数,传入要分的簇的数量
public kmeans(int k){
private void init(){
random=new Random();
if(dataSet==null||dataSet.size()==0)
initDataSet();
dataSetLength=dataSet.size();
if(k&dataSetLength)
k=dataSetL
center=initCenters();
cluster=initCluster();
jc=new ArrayList&Float&();
//初始化数据集合
private void initDataSet(){
dataSet=new ArrayList&double[]&();
double[][] dataSetArray=new double[][]{{8,2},{3,4},{2,5},{4,2},
{7,3},{6,2},{4,7},{6,3},{5,3},{6,3},{6,9},
{1,6},{3,9},{4,1},{8,6}};
for(int i=0;i&dataSetArray.i++)
dataSet.add(dataSetArray[i]);
//初始化中心链表,分成几簇就有几个中心
private ArrayList&double[]& initCenters(){
ArrayList&double[]& center= new ArrayList&double[]&();
//生成一个随机数列,
int[] randoms=new int[k];
int temp=random.nextInt(dataSetLength);
randoms[0]=
for(int i=1;i&k;i++){
while(flag){
temp=random.nextInt(dataSetLength);
while(j&i){
if(temp==randoms[j])
randoms[i]=
for(int i=0;i&k;i++)
center.add(dataSet.get(randoms[i]));
//初始化簇集合
private ArrayList&ArrayList&double[]&& initCluster(){
ArrayList&ArrayList&double[]&& cluster=
new ArrayList&ArrayList&double[]&&();
for(int i=0;i&k;i++)
cluster.add(new ArrayList&double[]&());
//计算距离
private double distance(double[] element,double[] center){
double distance=0.0f;
double x=element[0]-center[0];
double y=element[1]-center[1];
double z=element[2]-center[2];
double sum=x*x+y*y+z*z;
distance=(double)Math.sqrt(sum);
//计算最短的距离
private int minDistance(double[] distance){
double minDistance=distance[0];
int minLocation=0;
for(int i=0;i&distance.i++){
if(distance[i]&minDistance){
minDistance=distance[i];
minLocation=i;
}else if(distance[i]==minDistance){
if(random.nextInt(10)&5){
minLocation=i;
return minL
//每个点分类
private void clusterSet(){
double[] distance=new double[k];
for(int i=0;i&dataSetLi++){
//计算到每个中心店的距离
for(int j=0;j&k;j++)
distance[j]=distance(dataSet.get(i),center.get(j));
//计算最短的距离
int minLocation=minDistance(distance);
//把他加到聚类里
cluster.get(minLocation).add(dataSet.get(i));
//计算新的中心
private void setNewCenter(){
for(int i=0;i&k;i++){
int n=cluster.get(i).size();
double[] newcenter={0,0};
for(int j=0;j&n;j++){
newcenter[0]+=cluster.get(i).get(j)[0];
newcenter[1]+=cluster.get(i).get(j)[1];
newcenter[0]=newcenter[0]/n;
newcenter[1]=newcenter[1]/n;
center.set(i, newcenter);
//求2点的误差平方
private double errosquare(double[] element,double[] center){
double x=element[0]-center[0];
double y=element[1]-center[1];
double errosquare=x*x+y*y;
//计算误差平方和准则函数
private void countRule(){
float jcf=0;
for(int i=0;i&cluster.size();i++){
for(int j=0;j&cluster.get(i).size();j++)
jcf+=errosquare(cluster.get(i).get(j),center.get(i));
jc.add(jcf);
//核心算法
private void Kmeans(){
//初始化各种变量,随机选定中心,初始化聚类
//开始循环
while(true){
//把每个点分到聚类中去
clusterSet();
//计算目标函数
countRule();
//检查误差变化,因为我规定的计算循环次数为50次,所以就不用计算这个啦,你要愿意用也可以,就是慢一点
if(jc.get(m)-jc.get(m-1)==0)
//否则继续生成新的中心
setNewCenter();
cluster.clear();
cluster=initCluster();
//只暴露一个接口给外部类
public void execute(){
System.out.print(&start kmeans\n&);
System.out.print(&kmeans end\n&);
//用来在外面打印出来已经分好的聚类
public void printDataArray(ArrayList&double[]& data,String dataArrayName){
for(int i=0;i&data.size();i++){
System.out.print(&print:&+dataArrayName+&[&+i+&]={&+data.get(i)[0]+&,&+data.get(i)[1]+&}\n&);
System.out.print(&==========================&);
}& 嗯,代码就是这样。注释写的很详细,也都能看得懂。下面我给一个测试例子。
import java.util.ArrayL
public class Test {
public static void main(String[] args){
kmeans k=new kmeans(2);
ArrayList&double[]& dataSet=new ArrayList&double[]&();
dataSet.add(new double[]{2,2,2});
dataSet.add(new double[]{1,2,2});
dataSet.add(new double[]{2,1,2});
dataSet.add(new double[]{1,3,2});
dataSet.add(new double[]{3,1,2});
dataSet.add(new double[]{-2,-2,-2});
dataSet.add(new double[]{-1,-2,-2});
dataSet.add(new double[]{-2,-1,-2});
dataSet.add(new double[]{-3,-1,-2});
dataSet.add(new double[]{-1,-3,-2});
k.setDataSet(dataSet);
k.execute();
ArrayList&ArrayList&double[]&& cluster=k.getCluster();
for(int i=0;i&cluster.size();i++){
k.printDataArray(cluster.get(i), &cluster[&+i+&]&);
}& &没啥难度,也就是输入写初始数据,然后执行k-means在进行分类,最后打印一下。这个原型代码很粗糙,没有添加聚类个数以及循环次数的变量,这些需要自己动手啦。
2.k-means应用图像分割
& 我们可以把k-means聚类放在图像分割上,也就是说把一个颜色的像素分为一类,然后再涂一个颜色。像这样。
左边就是聚类之前的,右边是聚类之后的,看起来还是满炫酷的。其实聚类算法也是很容易扩展到这里的。
有下面四个提示(因为是作业,我决定先不放马,不然到时候作业雷同我的学分就咖喱gaygay了):
& &①.上面的原型代码是对二维的数据进行分类,那我们也知道,一个颜色有RGB三种原色构成,也就是说我们只需要 在二维的基础上,加上一维数据就吼啦。很简单有木有,改变下数组结构,在距离计算编程三维欧式距离就吼。
& &②.Java有自带的图像处理类,所以读取数据敲击方便。我给一点代码提示哦
//读取指定目录的图片数据,并且写入数组,这个数据要继续处理
private int[][] getImageData(String path){
BufferedImage bi=
bi=ImageIO.read(new File(path));
}catch (IOException e){
e.printStackTrace();
int width=bi.getWidth();
int height=bi.getHeight();
int [][] data=new int[width][height];
for(int i=0;i&i++)
for(int j=0;j&j++)
data[i][j]=bi.getRGB(i, j);
/*测试输出
for(int i=0;i&data.i++)
for(int j=0;j&data[0].j++)
System.out.println(data[i][j]);*/
//用来处理获取的像素数据,提取我们需要的写入dataItem数组
private dataItem[][] InitData(int [][] data){
dataItem[][] dataitems=new dataItem[data.length][data[0].length];
for(int i=0;i&data.i++){
for(int j=0;j&data[0].j++){
dataItem di=new dataItem();
Color c=new Color(data[i][j]);
di.r=(double)c.getRed();
di.g=(double)c.getGreen();
di.b=(double)c.getBlue();
di.group=1;
dataitems[i][j]=
//介货是用来输出图像的
&pre name=&code& class=&java&&
private void ImagedataOut(String path){
Color c0=new Color(255,0,0);
Color c1=new Color(0,255,0);
Color c2=new Color(0,0,255);
Color c3=new Color(128,128,128);
BufferedImage nbi=new BufferedImage(source.length,source[0].length,BufferedImage.TYPE_INT_RGB);
for(int i=0;i&source.i++){
for(int j=0;j&source[0].j++){
if(source[i][j].group==0)
nbi.setRGB(i, j, c0.getRGB());
else if(source[i][j].group==1)
nbi.setRGB(i, j, c1.getRGB());
else if(source[i][j].group==2)
nbi.setRGB(i, j, c2.getRGB());
else if (source[i][j].group==3)
nbi.setRGB(i, j, c3.getRGB());
//Color c=new Color((int)center[source[i][j].group].r,
(int)center[source[i][j].group].g,(int)center[source[i][j].group].b);
//nbi.setRGB(i, j, c.getRGB());
ImageIO.write(nbi, &jpg&, new File(path));
}catch(IOException e){
e.printStackTrace();
& & 很舒爽,你问我dataItem是啥?等我交完作业我就告诉你。
& & ③.有一点不同的是,注意数据格式。胖胖开始用的就是int类型,结果在计算新的聚类中心的时候溢出了呢。。。所幸鹏鹏改成了double,但是鹏鹏在计算距离的时候又写错了,最后还是机智的胖胖鹏解决掉了所有的bug。
& & ④.注意读取图片的时候保护好数据的顺序,也就是用一个二维数组来存储,这样在写的时候就不用记录像素点的位置,输出的时候也很方便。
& &就是这些。。。。等我作业交完就来一次完整的代码讲解!
&&相关文章推荐
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:5526次
排名:千里之外
原创:11篇
(1)(1)(1)(2)(1)(5)(1)k-means聚类算法的java实现描述
1.什么是k-means聚类算法?
&从网上找到了很多定义,这里选取比较典型的几个;
K-Mean分群法是一种分割式分群方法,其主要目标是要在大量高纬的资料点中找出
具有代表性的资料点;这些资料点可以称为群中心,代表点;然后再根据这些
群中心,进行后续的处理,这些处理可以包含
1)资料压缩:以少数的资料点来代表大量的资料,达到资料压缩的功能;
2)资料分类:以少数代表点来代表特点类别的资料,可以降低资料量及计算量;
分割式分群法的目的是希望盡量減小每個群聚中,每一點與群中心的距離平方差(square error)。&
&假設我們現在有一組包含c個群聚的資料,其中第 k 個群聚可以用集合 Gk來表示,假設 Gk包含nk筆
&資料{x1, x2, …,
xnk),此群聚中心為yk,則該群聚的平方差 ek可以定義為:
&&&&&&&&&&&&
ek = Si |xi-yk|2,其中
xi是屬於第
k 群的資料點。
&而這c個群聚的總和平方差E便是每個群聚的平方差總和:
E = Sk=1~c ek
&我們分群的方法,就變成是一個最佳化的問題,換句話說,我們要如何選取
個群聚以及相關的群中心,
E 的值為最小。
2.处理流程
(1)& 从c个数据对象任意选择
k 个对象作为初始聚类中心;(2)& 循环(3)到(4)直到每个聚类不再发生变化为止;(3)& 根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分;(4)& 重新计算每个(有变化)聚类的均值(中心对象)
3. java算法的实现说明
&1)假设给点一组c点资料X =
{x1, ...,
xc},每一点都有d维;给定一个群聚的数目k,求其
最好的聚类结果。
2)BasicKMeans.java主类
&&&&&&& int
coordCount = 250;//原始的资料个树
int dimensions = 100;//每个资料的纬度数目
double[][] coordinates = new
double[coordCount][dimensions];
& 这里假设c点资料为coordinates对象,其中c为coordCount,d为dimensions相应值。
&&&&&&& int mk
= 30; //想要群聚的数目
根据群聚数目定义mk个群聚类对象
&&&&& mProtoClusters =
new ProtoCluster[mK];//见ProtoCluster类说明
&& //首先随机选取mk个原始资料点作为群聚类
&&&& mProtoClusters[i]= new
ProtoCluster (coordinates[j] );//i依此为0到mk的值;j为0到coordCount的值
& 定义一个变量用于记录和跟踪每个资料点属于哪个群聚类
&&& mClusterAssignments = new
int[coordCount];
mClusterAssignments[j]=i;//表示第j个资料点对象属于第i个群聚类
&& //开始循环
&& //依次调用计算每个群聚类的均值
mProtoClusters[i].updateCenter(mCoordinates);//计算第i个聚类对象的均值
&& //依次计算每个资料点到中心点的距离,然后根据最小值划分到相应的群集类中;
采用距离平方差来表示资料点到中心点的距离;
//定义一个变量,来表示资料点到中心点的距离
mDistanceCache = new double[coordCount ][mk];
//其中mDistanceCache[i][j]表示第i个资料点到第j个群聚对象中心点的距离;
//距离算法描述():
a)依次取出每个资料点对象double[] coord = coordinates[i];
&&&&&&&&b)再依次取出每个群聚类中的中心点对象double[] center = mProtoClusters[j].mC
&&&&&&& c)计算coord对象与center对象之间的距离&
&&&& double distance(double[] coord,
double[] center) {
&&&&&&& int len =
&&&&&&& double sumSquared =
&&&&&&& for (int i=0;
i& i++) {
&&&&&&&&&&&
double v = coord[i] - center[i];
&&&&&&&&&&&
sumSquared += v*v;&//平方差
&&&&&&& }
&&&&&&& return
Math.sqrt(sumSquared);
d)循环执行上面的流程,把结果记录在mDistanceCache[i][j]中;
//比较出最小距离,然后根据最小距离重新对相应对象进行划分
&&&& 依次比较每个资料点的
最短中心距离,
nearestCluster(int ndx) {
&&&&&&& int nearest = -1;
&&&&&&& double min =
Double.MAX_VALUE;&&
&&&&&&& for (int c = 0; c
& mK; c++) {
&&&&&&&&&&&&&&&
double d = mDistanceCache[ndx][c];
&&&&&&&&&&&&&&&
if (d & min) {
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&&&&&
&&&&&&&&&&&&&&&
}&&&&&&&&&&
&&&&&& }
& 该方法返回该资料点对应的最短中心距离的群聚类的索引值;
& 比较每个 nearestCluster[coordCount]
的值和mClusterAssignments[coordCount]
& 的值是否相等,如果全相等表示所有的点已经是最佳距离了,直接返回;
& 否则需要重新调整资料点和群聚类的关系,调整完毕后再重新开始循环;
&&调整时需要更新下列数据:
&&& a)更新mProtoClusters[i]中的mCurrentMembership集合;
&&&&&& b)更新mClusterAssignments[i]中对应的值;
然后重行开始循环
3)ProtoCluster.java是一个包含代表点的群聚类,该类有两个最主要的属性"代表点"和"群中心";
mCurrentM//用于表示每个群聚包含的数据资料点集合
double[] mC//用于表示每个聚类对象的均值,也就是中心对象
& void updateCenter(double[][] coordinates)
//该方法计算聚类对象的均值;
//根据mCurrentMembership取得原始资料点对象coord,该对象是coordinates的一个子集;然后取出该子集的均值;
取均值的算法很简单,可以把coordinates想象成一个m*n的距阵,每个均值就是每个纵向列的取和平均值,该值保
存在mCenter中
&for (int i=0; i&
mCurrentMembership. i++)
&&&&&&&&&&&&&&
double[] coord =
coordinates[mCurrentMembership[i]];
&&&&&&&&&&&&&&
for (int j=0; j&coord. j++)
&&&&&&&&&&&&&&&&&&&&&&&
mCenter[j] += coord[j];//得到每个纵向列的和;
&&&&&&&&&&&&&
&&&&&&&&&&&&&&&for (int i=0; i&mCenter.
i++) {
&&&&&&&&&&&&&&&&&&
&mCenter[i] /= mCurrentS
//对每个纵向列取平均值
&&&&&&&&&&&&&&
&&&&&&&&&&&}&
参考文档:
以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

我要回帖

更多关于 多个java文件编译执行 的文章

 

随机推荐