数据挖掘 java开发_数据挖掘之聚类(java 实现)

packagecn.edu.pku.ss.dm.cluster;import Java.io.BufferedReader;importjava.io.BufferedWriter;importjava.io.FileNotFoundException;importjava.io.FileReader;importjava.io.FileWriter;importjava.io.IOException;importjava.util.ArrayList;/*** K-means算法实现

*

*@authoreagle

**/

public classKMeans {//聚类的数目

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

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

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

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

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

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

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

private ArrayList>result;/*** 构造函数,初始化*/

publicKMeans()

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

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

classData= new float[ClassCount][FieldCount];

result= new ArrayList>(ClassCount);

noises= new ArrayList();

}/*** 主函数入口

* 测试集的文件名称为"测试集.data",其中又1000*57大小的数据

* 每一行为一个样本,有57个属性

* 主要分为两个步骤

* 1.读取数据

* 2.进行聚类

* 最后统计了运行的时间和消耗的内存

*@paramargs*/

public static voidmain(String[] args) {long startTime =System.currentTimeMillis();

KMeans cluster= newKMeans();//读取数据

cluster.readData("测试集.data");//聚类过程

cluster.cluster();//输出结果

cluster.printResult("clusterResult.data");long endTime =System.currentTimeMillis();

System.out.println("Total Time: " + (endTime - startTime)/1000 + " s");

System.out.println("Memory Consuming: " + (float)(Runtime.getRuntime().totalMemory() -Runtime.getRuntime().freeMemory())/1000000 + " MB");

}/*** 读取测试集的数据

*

*@paramtrainingFileName 测试集文件名*/

public voidreadData(String trainingFileName){try{

FileReader fr= newFileReader(trainingFileName);

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

String lineData = null;

String[] splitData= null;int line = 0;//按行读取

while(br.ready())

{//得到原始的字符串

lineData =br.readLine();

splitData= lineData.split(",");//转化为数据

for(int i = 0;i

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

line++;

}

}catch(FileNotFoundException e) {

e.printStackTrace();

}catch(IOException e) {

e.printStackTrace();

}

}/*** 聚类过程,主要分为两步

* 1.循环找初始点

* 2.不断调整直到分类不再发生变化*/

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() < InstanseNumber /Math.pow(ClassCount, t)){

needUpdataInitials= true;

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

}

}

}//找到合适的初始点后//不断的调整均值中心和分类、直到不再发生任何变化

Adjust();

}/*** 对数据进行归一化

* 1.找每一个属性的最大值

* 2.对某个样本的每个属性除以其最大值*/

public voidnormalize(){//找最大值

float[] max = new float[FieldCount];for(int i = 0;imax[j])

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

}

}//归一化

for(int i = 0;i

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

}

}

}/*** 关于初始向量的一次找寻尝试*/

public voidfindInitials(){//a,b为标志距离最远的两个向量的索引

inti,j,a,b;

i= j = a = b = 0;//最远距离

float maxDis = 0;//已经找到的初始点个数

int alreadyCls = 2;//存放已经标记为初始点的向量索引

ArrayList initials = new ArrayList();//从两个开始

for(;i < InstanseNumber;i++)

{//噪声点

if(noises.contains(i))continue;//long startTime = System.currentTimeMillis();

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

{//噪声点

if(noises.contains(j))continue;//找到最大的距离并记录下来

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

{

a=i;

b=j;

maxDis=newDis;

}

}//long endTime = System.currentTimeMillis();//System.out.println(i + " Vector Caculation Time:" + (endTime - startTime) + " ms");

}//将前两个初始点记录下来

initials.add(a);

initials.add(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);//找到剩余的几个初始点

while( alreadyCls

i= j = 0;float maxMin = 0;int newClass = -1;//找最小值中的最大值

for(;i < InstanseNumber;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;

}

}//添加到均值集合和结果集合中//System.out.println("NewClass " + newClass);

initials.add(newClass);

classData[alreadyCls++] =data[newClass];

ArrayList rslt = new ArrayList();

rslt.add(newClass);

result.add(rslt);

}

}/*** 第一次分类*/

public voidfirstClassify()

{//根据初始向量分类

for(int i = 0;i < InstanseNumber;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 < InstanseNumber;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);

}//测试聚类效果(训练集)//for(int i = 0;i < ClassCount;i++){//int positives = 0;//int negatives = 0;//ArrayList cls = result.get(i);//for(Integer instance:cls)//if (data[instance][FieldCount - 1] == 1f)//positives ++;//else//negatives ++;//System.out.println(" " + i + " Positive: " + positives + " Negatives: " + negatives);//}//System.out.println();

}

}/*** 计算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 < InstanseNumber;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、付费专栏及课程。

余额充值