`
oliver1000
  • 浏览: 16690 次
  • 性别: Icon_minigender_1
  • 来自: 广州
最近访客 更多访客>>
社区版块
存档分类
最新评论

K-means算法Java实现

阅读更多

K-means算法Java实现

算法设计 1》什么是K-means算法
step1 从数据中随机抽取K个点作为初始聚类的中心。
step2 计算数据中所有的点到这K个点的距离,将点归到离其最近的聚类里。
step3 调整聚类中心。
step4 重复step2,直到误差小于阈值或者聚类中心及聚类成员不在改变。

2》java实现

 Point.java
package cn.edu.shu.kmeans;
public class Point {
    int x;//坐标
    int y;
    int id; //名称
    public Point(int id, int x, int y) {
        this.x = x;
        this.y = y;
        this.id = id;
    }
    public int getX() {
        return x;
    }
    public void setX(int x) {
        this.x = x;
    }
    public int getY() {
        return y;
    }
    public void setY(int y) {
        this.y = y;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
    @Override
    public String toString() {
        return "P"+id+"("+x+","+y+")";
    }    
}

 

 Cluster.java
package cn.edu.shu.kmeans;
import java.util.ArrayList;
public class Cluster {
    double error=0.0;//聚类内部误差
    int center;//聚类中心point的id
    ArrayList<Point> ofCluster = new ArrayList<Point>();//属于这个聚类的点的集合
    public double getError() {
        return error;
    }
    public void setError(double error) {
        this.error = this.error+ error;
    }
    public int getCenter() {
        return center;
    }
    public void setCenter(int center) {
        this.center = center;
    }
    public ArrayList<Point> getOfCluster() {
        return ofCluster;
    }
    public void setOfCluster(ArrayList<Point> ofCluster) {
        this.ofCluster = ofCluster;
    }
    public void addPoints(Point point){
        if(!(this.ofCluster.contains(point)))
        this.ofCluster.add(point);
    }
}

     

 Distence.java
package cn.edu.shu.kmeans;
public class Distence {
    int dest;
    int source;
    double dist;
    public int getDest() {
        return dest;
    }
    public void setDest(int dest) {
        this.dest = dest;
    }
    public int getSource() {
        return source;
    }
    public void setSource(int source) {
        this.source = source;
    }
    public double getDist() {
        return dist;
    }
    public void setDist(double dist) {
        this.dist = dist;
    }
    public Distence(int dest, int source, double dist) {
        super();
        this.dest = dest;
        this.source = source;
        this.dist = dist;
    }
    public Distence() {
    }
    @Override
    public boolean equals(Object obj) {
        if(obj!=null){
            Distence d = (Distence)obj;
        if(this.dest==d.dest&&this.source==d.source&&this.dist==d.dist){
            return true;
        }
        else{
            return false;
        }
        }
        return false;
    }    
}

  

 Kmeans.java
package cn.edu.shu.kmeans;
import java.io.*;
import java.util.*;
public class Kmeans {

    int K; //聚类参数,聚成几个类。
    int Generation=100;//聚类次数,聚类结束条件之一。
    double E=7.1;//误差参数,聚类结束的条件之一。
    static ArrayList<Point> allPoints = new ArrayList<Point>();//参与聚类的所有点
    int totalNumber = 0;//聚类的点的个数

    //初始化数据
    //data.txt
    //2
    //1 1
    //2 2
    //4 4
    //5 5
    //8 8
    public void prepare() throws IOException {
        File file = new File("D:\\eclipse\\workspace\\algorithm\\db\\data.txt");
        FileReader fr = new FileReader(file);
        BufferedReader br = new BufferedReader(fr);
        String data = "0";
        int x = 0;
        int y = 0;
        String[] temp = null;
        Point p = null;
        K = Integer.parseInt(br.readLine());
        while ((data = br.readLine()) != null) {
            temp = data.split(" ");
            x = Integer.parseInt(temp[0]);
            y = Integer.parseInt(temp[1]);
            p = new Point(totalNumber++, x, y);
            allPoints.add(p);
        }
    }

    // 第一次随机选取聚类中心
    public Set<Integer> firstChoose() {
        Set<Integer> center = new HashSet<Integer>();//聚类中心的点的id,采用set保证不会有重复id
        Random ran = new Random();
        int roll = ran.nextInt(totalNumber);
        while (center.size() < K) {
            roll = ran.nextInt(totalNumber);
            center.add(roll);
        }
        return center;
    }
    
    //根据聚类中心初始化聚类信息
    public ArrayList<Cluster> beforCP(Set<Integer> center) {
        ArrayList<Cluster> cluster = new ArrayList<Cluster>();//存放几个类的信息
        Iterator<Integer> it = center.iterator();
        while (it.hasNext()) {
            Cluster c = new Cluster();//代表一个聚类
            c.setCenter(it.next());
            cluster.add(c);
        }
        return cluster;
    }

    //第一次聚类
    public ArrayList<Cluster> clusterProcess(ArrayList<Cluster> cluster,
            Set<Integer> center) {
        ArrayList<Distence> distence = new ArrayList<Distence>();//存放距离信息
        Point source = null;
        Point dest = null;
        int id = 0;
        int id2 = 0;
        Object[] p = center.toArray();
        boolean flag = false;
        for (int i = 0; i < totalNumber; i++) {
            distence.clear();
            for (int j = 0; j < center.size(); j++) {
                if (!(center.contains(i))) {
                    flag = true;
                    // 计算距离
                    source = allPoints.get(i);
                    dest = allPoints.get((Integer) p[j]);
                    distence.add(new Distence((Integer) p[j], i, (Double) Math
                            .sqrt(StrictMath
                                    .pow(source.getX() - dest.getX(), 2)
                                    + StrictMath.pow(source.getY()
                                            - dest.getY(), 2))));
                } else {
                    flag = false;
                }
            }
            if (flag == true) {
                // 排序比较一个点到各个中心的距离的大小
                double min = distence.get(0).getDist();
                for (int k = 1; k < distence.size(); k++) {
                    if (min > distence.get(k).getDist()) {
                        min = distence.get(k).getDist();
                        id = distence.get(k).getDest();
                        id2 = distence.get(k).getSource();
                    } else {
                        id = distence.get(0).getDest();
                        id2 = distence.get(0).getSource();
                    }
                }
                for (int n = 0; n < cluster.size(); n++) {
                    if (cluster.get(n).getCenter() == id) {
                        cluster.get(n).setError(min);
                        cluster.get(n).addPoints(allPoints.get(id2));
                    }
                }
            }
        }
        return cluster;
    }

    // 更新聚类中心
    public ArrayList<Cluster> stack(ArrayList<Cluster> cluster) {
        double te = 0;
        for (int m = 0; m < Generation; m++) {
            te = 0;
            Set<Integer> center = new HashSet<Integer>();
            // 重新计算聚类中心
            // 方法二:在聚类中,按照距离重新计算聚类中心
            Point source = null;
            Point dest = null;
            int id = 0;
            ArrayList<Distence> distence = new ArrayList<Distence>();
            for (int j = 0; j < K; j++) {
                distence.clear();
                ArrayList<Point> ps = cluster.get(j).getOfCluster();
                ps.add(allPoints.get(cluster.get(j).getCenter()));
                int size = ps.size();
                if (size > 2) {//一个聚类只有1个或2个点就不重新更新聚类中心
                    // 计算距离
                    for (int k1 = 0; k1 < size; k1++) {
                        for (int k2 = 0; k2 < size; k2++) {
                            if (k1 != k2) {
                                source = ps.get(k1);
                                dest = ps.get(k2);
                                distence.add(new Distence(dest.getId(), source
                                        .getId(), (Double) Math.sqrt(StrictMath
                                        .pow(source.getX() - dest.getX(), 2)
                                        + StrictMath.pow(source.getY()
                                                - dest.getY(), 2))));
                            }
                        }
                    }
                    // 比较大小
                    double min = distence.get(0).getDist();
                    for (int k = 1; k < distence.size(); k++) {
                        if (min > distence.get(k).getDist()) {
                            min = distence.get(k).getDist();
                            id = distence.get(k).getSource();
                        } else {
                            id = distence.get(0).getSource();
                        }
                    }
                    center.add(id);
                } else {
                    center.add(cluster.get(j).getCenter());
                }
            }
            // 方法一:采用随机产生新的聚类中心
            // center = firstChoose();
            // 重新聚类
            cluster = clusterProcess(beforCP(center), center);
            for (int nz = 0; nz < K; nz++) {
                te = te + cluster.get(nz).getError();//计算误差
            }
            if (te < E)
                break;
        }
        return cluster;
    }

    //输出聚类信息
    public static void print(ArrayList<Cluster> cs) {
        double e = 0;
        for (int i = 0; i < cs.size(); i++) {
            e = e + cs.get(i).getError();
        }
        System.out.print("---e ");
        System.out.printf("%8.6f", e);
        System.out.println("-------------");
        for (int i = 0; i < cs.size(); i++) {
            Cluster c = cs.get(i);
            System.out.println("center: " +allPoints.get(c.center) + " error: " + c.getError());
            ArrayList<Point> p = c.getOfCluster();
            for (int j = 0; j < p.size(); j++) {
                System.out.print(p.get(j));
            }
            System.out.println();
        }
    }
    
    public static void main(String[] args) throws IOException {
        Kmeans kmeans = new Kmeans();
        kmeans.prepare();
        Set<Integer> center = kmeans.firstChoose();
        ArrayList<Cluster> cs = kmeans.clusterProcess(kmeans.beforCP(center),center);
        print(cs);
        ArrayList<Cluster> cs2 = kmeans.stack(cs);
        print(cs2);
    }
}

  
3》结果

分享到:
评论

相关推荐

    K-Means算法java实现

    Java作为一种通用且广泛使用的编程语言,提供了实现K-Means算法的良好平台,尤其适合初学者学习数据挖掘技术。 K-Means算法的核心步骤包括初始化中心点、计算样本到中心点的距离、重新分配样本点所属类别以及更新...

    k-means算法Java实现

    在Java中实现k-means算法,我们需要以下几个关键步骤: 1. **初始化质心**:从数据集中随机选择k个数据点作为初始质心,可以使用`Random`类来实现。 2. **数据分配**:遍历每个数据点,计算它与所有质心的距离,将...

    K-means算法 java实现

    在Java中实现K-means算法,我们可以遵循以下步骤: 1. **初始化**:首先,我们需要选择K个初始质心(centroid)。通常,这些质心可以从数据集中随机选取或者基于某种策略(如K-means++)来确定。 2. **分配样本**...

    k-means 算法java实现

    在Java中实现k-means算法,可以让我们在各种数据集上进行有效的数据分组,从而揭示数据的潜在结构。以下是对k-means算法及其Java实现的详细说明。 **k-means算法原理** 1. **目标**: k-means算法旨在将数据集划分...

    K-means算法java实现

    k-means 算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。... &lt;br&gt;这是个基于多线程的java实现的K-means算法程序

    详解Java实现的k-means聚类算法

    Java实现的k-means聚类算法详解 k-means聚类算法是一种常用的无监督学习算法,用于对数据进行聚类分析。该算法的主要思想是将相似的数据点聚类到一起,形成不同的簇。Java语言是实现k-means聚类算法的不二之选。 ...

    数据挖掘 k-means算法 java实现

    在Java环境下实现k-means算法,可以为数据分析和预测模型提供强大的支持。 k-means算法的核心思想是通过迭代过程将数据集中的样本点分配到预先设定的k个聚类中,使得同一类内的样本点彼此相似,不同类的样本点相异...

    国外实现k-means算法

    本篇文章将详细解读一个由国外开发者提供的K-Means算法Java实现案例,并深入分析其代码结构与算法流程。 #### K-Means算法原理 在开始分析具体实现之前,我们先简要回顾一下K-Means算法的基本原理。K-Means的目标...

    k-means算法java实现

    K-Means 是一种基于距离的排他的聚类划分方法。K-Means 问题描述: 给定一个 n 个对象的数据集,它可以构建数据的 k 个划分,每个划分就是一个簇,并且 k ≤ n。同时还需满足: 每个组至少包含一个对象。 每个对象...

    java实现k-means算法

    Java 实现 K-Means 算法是一个在数据挖掘领域常见的任务,它主要用于聚类分析,即将数据分组成不同的类别或簇。K-Means 是一种迭代算法,旨在找到数据点的最佳分配,使得每个簇内的数据点尽可能相似,而不同簇之间的...

    k-means算法

    在Java中实现k-means算法,我们可以遵循以下几个关键步骤: 1. **初始化**:首先,需要选择k个初始质心(cluster centers)。通常,这可以通过随机选择数据集中的k个点来完成。这些初始质心将成为我们簇的代表。 2...

    java k-means可视化程序

    在Java中实现K-Means算法,需要使用数组或集合来存储数据点和质心,使用循环结构进行迭代,以及计算欧氏距离等数学操作。同时,为了实现可视化,还需要利用Java的图形库,如JavaFX或Swing,创建窗口并绘制二维坐标...

    K-means聚类算法JAVA程序实现

    在JAVA程序实现中,K-means算法的关键步骤包括初始化、迭代和终止条件。 首先,我们需要初始化聚类中心。通常,我们随机选择数据集中的K个点作为初始聚类中心。这里的K是用户指定的类别数量,也是我们想要找到的...

    基于Java的K-means实验算法设计与实现.zip

    1. 编程实现K-means算法,并在红酒数据集上运行。 2. 设置不同K值,不同初始中心,在红酒数据集上进行实验比较。 3. 分析k-means的优缺点,并对其中一个或几个缺点进行改进。 所用语言: Java 实验数据分析: 红酒...

    多维k-means聚类算法java实现,导入直接运行

    在Java中实现多维k-means算法,可以为数据分析和大数据处理提供高效且灵活的工具。下面我们将详细探讨这个算法以及如何在Java中进行实现。 首先,我们需要理解k-means算法的基本原理。k-means算法的目标是通过迭代...

    数据挖掘中考k-means算法的java实现

    在这个场景下,我们关注的是k-means算法的Java实现。k-means是一种广泛应用的无监督学习算法,用于聚类分析,即将数据集分成多个离散的、具有相似属性的簇。 k-means算法的基本思想是通过迭代过程将数据点分配到...

    k-means_K-Means算法实现_K._聚类可视化_数据可视化、_

    K-Means算法是机器学习领域中广泛应用的一种无监督学习方法,主要用于数据的聚类分析。这个算法的主要目标是将数据集分割成K个不同的类别(或簇),使得每个簇内的数据点彼此相似,而不同簇之间的数据点差异较大。...

    【毕业设计】基于 K-means 算法的校园微博热点话题发现系统.rar

    本文从微博独有的短文本特征及国内外相关微博研究出发,通过对校园微博进行分类处理后使 用K-means聚类算法对校园微博短文本聚类,并改进热度计算公式,通过话题热度提取校园微博热点话题,实现对校园微博热点话题的...

Global site tag (gtag.js) - Google Analytics