java k means_K-Means算法的Java实现

packagecom.coshaho.learn.kmeans;importjava.io.BufferedReader;importjava.io.BufferedWriter;importjava.io.FileReader;importjava.io.FileWriter;importjava.io.IOException;importjava.util.ArrayList;public classKMeans

{//聚类的数目

final static int ClassCount = 3;//样本数目(测试集)

final static int InstanceNumber = 150;//样本属性数目(测试)

final static int FieldCount = 5;//设置异常点阈值参数(每一类初始的最小数目为InstanceNumber/ClassCount^t)

final static double t = 2.0;//存放数据的矩阵

private float[][] data;//每个类的均值中心

private float[][] classData;//噪声集合索引

private ArrayListnoises;//存放每次变换结果的矩阵

private ArrayList>result;publicKMeans()

{//最后一位用来储存结果

data = new float[InstanceNumber][FieldCount+1];

classData= new float[ClassCount][FieldCount];

result= new ArrayList>(ClassCount);

noises= new ArrayList();

}public voidreadData(String TrainDataFile)

{

FileReader fr= null;

BufferedReader br= null;try{

fr= newFileReader(TrainDataFile);

br= newBufferedReader(fr);//存放数据的临时变量

String lineData = null;

String[] splitData= null;int line = 0;while( br.ready())

{

lineData=br.readLine();

System.out.println(lineData);

splitData= lineData.split(",");for(int i = 0 ; i < splitData.length ;i++)

{

data[line][i]=Float.parseFloat(splitData[i]);

}

line++;

}

}catch(Exception e)

{

e.printStackTrace();

}finally{if(null !=br)

{try{

br.close();

}catch(IOException e)

{

e.printStackTrace();

}

}if(null !=fr)

{try{

fr.close();

}catch(IOException e)

{

e.printStackTrace();

}

}

}

}public voidcluster()

{//数据归一化

normalize();//标记是否需要重新找初始点

boolean needUpdataInitials = true;//找初始点的迭代次数

int times = 1;//找初始点

while(needUpdataInitials)

{

needUpdataInitials= false;

result.clear();

System.out.println("Find Initials Iteration"+(times++)+"time(s)");//一次找初始点的尝试和根据初始点的分类

findInitials();

firstClassify();for(int i = 0;i < result.size();i++)

{if(result.get(i).size() < InstanceNumber/Math.pow(ClassCount,t))

{

needUpdataInitials= true;

noises.addAll(result.get(i));

}

}

}

Adjust();

}/*** 数据归一化

*@authorcoshaho*/

private voidnormalize()

{//计算数据每个维度最大值max

float[] max = new float[FieldCount];for(int i = 0;i < InstanceNumber;i++)

{for(int j = 0;j < FieldCount;j++)

{if(data[i][j] >max[j])

{

max[j]=data[i][j];

}

}

}//每个维度归一化值=原始值/max

for(int i = 0;i < InstanceNumber;i++)

{for(int j = 0;j < FieldCount;j++)

{

data[i][j]= data[i][j]/max[j];

}

}

}/*** 寻找初始聚类中心

*@authorcoshaho*/

private voidfindInitials()

{inti, j, a, b;

i= j = a = b = 0;float maxDis = 0;int alreadyCls = 2;//选取距离最远的两个点a,b作为聚类中心点

ArrayList initials = new ArrayList();for (; i < InstanceNumber; i++)

{//噪声点不参与计算

if(noises.contains(i))

{continue;

}

j= i + 1;for (; j < InstanceNumber; j++)

{//噪声点不参与计算

if(noises.contains(j))

{continue;

}float newDis =calDis(data[i], data[j]);if (maxDis

{

a=i;

b=j;

maxDis=newDis;

}

}

}//initials添加初始聚类中心点序号a,b

initials.add(a);

initials.add(b);//classData添加聚类中心点data[a],data[b]

classData[0] =data[a];

classData[1] =data[b];//新增两个聚类,并添加聚类成员

ArrayList resultOne = new ArrayList();

ArrayList resultTwo = new ArrayList();

resultOne.add(a);

resultTwo.add(b);

result.add(resultOne);

result.add(resultTwo);//1、计算剩下每个点x与其他点的最小距离l,并记录Map//2、选取Map中的最大l,并以对应的点x作为新的聚类中心

while (alreadyCls

{

i= j = 0;float maxMin = 0;int newClass = -1;for (; i < InstanceNumber; i++)

{float min = 0;float newMin = 0;if(initials.contains(i))

{continue;

}if(noises.contains(i))

{continue;

}for (j = 0; j < alreadyCls; j++)

{

newMin=calDis(data[i], classData[j]);if (min == 0 || newMin

{

min=newMin;

}

}if (min >maxMin)

{

maxMin=min;

newClass=i;

}

}//initials添加新的聚类中心点序号newClass

initials.add(newClass);//classData添加新的聚类中心点data[newClass]

classData[alreadyCls++] =data[newClass];//新增一个聚类,并添加成员

ArrayList rslt = new ArrayList();

rslt.add(newClass);

result.add(rslt);

}

}/*** 首次聚类分配

* 点x到哪个聚类中心点最近,则划分到哪个聚类

*@authorcoshaho*/

public voidfirstClassify()

{for (int i = 0; i < InstanceNumber; i++)

{float min =0f;int clsId = -1;for (int j = 0; j < classData.length; j++)

{//欧式距离

float newMin =calDis(classData[j], data[i]);if (clsId == -1 || newMin

{

clsId=j;

min=newMin;

}

}if (!result.get(clsId).contains(i))

{

result.get(clsId).add(i);

}

}

}//迭代分类,直到各个类的数据不再变化

public voidAdjust()

{//记录是否发生变化

boolean change = true;//循环的次数

int times = 1;while(change)

{//复位

change = false;

System.out.println("Adjust Iteration" + (times++) + "time(s)");//重新计算每个类的均值

for (int i = 0; i < ClassCount; i++)

{//原有的数据

ArrayList cls =result.get(i);//新的均值

float[] newMean = new float[FieldCount];//计算均值

for(Integer index : cls)

{for (int j = 0; j < FieldCount; j++)

newMean[j]+=data[index][j];

}for (int j = 0; j < FieldCount; j++)

{

newMean[j]/=cls.size();

}if (!compareMean(newMean, classData[i]))

{

classData[i]=newMean;

change= true;

}

}//清空之前的数据

for (ArrayListcls : result)

{

cls.clear();

}//重新分配

for (int i = 0; i < InstanceNumber; i++)

{float min =0f;int clsId = -1;for (int j = 0; j < classData.length; j++)

{float newMin =calDis(classData[j], data[i]);if (clsId == -1 || newMin

{

clsId=j;

min=newMin;

}

}

data[i][FieldCount]=clsId;

result.get(clsId).add(i);

}

}

}/*** 计算a样本和b样本的欧式距离作为不相似度

*

*@parama 样本a

*@paramb 样本b

*@return欧式距离长度*/

private float calDis(float[] aVector, float[] bVector) {double dis = 0;int i = 0;/*最后一个数据在训练集中为结果,所以不考虑*/

for (; i < aVector.length; i++)

dis+= Math.pow(bVector[i] - aVector[i], 2);

dis= Math.pow(dis, 0.5);return (float) dis;

}/*** 判断两个均值向量是否相等

*

*@parama 向量a

*@paramb 向量b

*@return

*/

private boolean compareMean(float[] a, float[] b) {if (a.length !=b.length)return false;for (int i = 0; i < a.length; i++) {if (a[i] > 0 && b[i] > 0 && a[i] !=b[i]) {return false;

}

}return true;

}/*** 将结果输出到一个文件中

*

*@paramfileName*/

public voidprintResult(String fileName)

{

FileWriter fw= null;

BufferedWriter bw= null;try{

fw= newFileWriter(fileName);

bw= newBufferedWriter(fw);//写入文件

for (int i = 0; i < InstanceNumber; i++)

{

bw.write(String.valueOf(data[i][FieldCount]).substring(0, 1));

bw.newLine();

}//统计每类的数目,打印到控制台

for (int i = 0; i < ClassCount; i++)

{

System.out.println("第" + (i + 1) + "类数目: "

+result.get(i).size());

}

}catch(IOException e)

{

e.printStackTrace();

}finally{//关闭资源

if (bw != null)

{try{

bw.close();

}catch(IOException e)

{

e.printStackTrace();

}

}if (fw != null)

{try{

fw.close();

}catch(IOException e)

{

e.printStackTrace();

}

}

}

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值