由于项目需要,需要对数据进行处理,故而又要滚回来看看paper,做点小功课,这篇文章只是简单的总结一下基础的Kmeans算法思想以及实现;

正文:

    1.基础Kmeans算法.

  Kmeans算法的属于基础的聚类算法,它的核心思想是: 从初始的数据点集合,不断纳入新的点,然后再从新计算集合的“中心”,再以改点为初始点重新纳入新的点到集合,在计算”中心”,依次往复,直到这些集合不再都不能再纳入新的数据为止.

图解:

    假如我们在坐标轴中存在如下A,B,C,D,E一共五个点,然后我们初始化(或者更贴切的说指定)两个特征点(意思就是将五个点分成两个类),采用欧式距离计算距离.

  数据挖掘之聚类算法K-Means总结

 

注意的点:

    1.中心计算方式不固定,常用的有使用距离(欧式距离,马式距离,曼哈顿距离,明考斯距离)的中点,还有重量的质心,还有属性值的均值等等,虽然计算方式不同,但是整体上Kmeans求解的思路相同.

    2.初始化的特征点(选取的K个特征数据)会对整个收据聚类产生影响.所以为了得到需要的结果,需要预设指定的凸显的特征点,然后再用Kmeans进行聚类.

代码实现:   

  1 package com.data.algorithm;
  2 
  3 import java.util.ArrayList;
  4 import java.util.List;
  5 
  6 /**
  7  * *********************************************************
  8  * <p/>
  9  * Author:     XiJun.Gong
 10  * Date:       2017-01-17 15:57
 11  * Version:    default 1.0.0
 12  * Class description:
 13  * <p/>
 14  * *********************************************************
 15  */
 16 public class Kmeans {
 17     private final double exp = 1e-6;
 18 
 19     private List<KMeanData> topk;
 20 
 21     public List<KMeanData> getTopk() {
 22         return topk;
 23     }
 24 
 25     public void setTopk(List<KMeanData> topk) {
 26         this.topk = topk;
 27     }
 28 
 29     class KMeanData {
 30 
 31         private float x;    //x坐标
 32         private float y;    //y坐标
 33         private int flag;   //隶属于哪一个簇
 34 
 35         public int getFlag() {
 36             return flag;
 37         }
 38 
 39         public void setFlag(int flag) {
 40             this.flag = flag;
 41         }
 42 
 43         public float getX() {
 44             return x;
 45         }
 46 
 47         public void setX(float x) {
 48             this.x = x;
 49         }
 50 
 51         public float getY() {
 52             return y;
 53         }
 54 
 55         public void setY(float y) {
 56             this.y = y;
 57         }
 58     }
 59 
 60     public boolean max(float a, float b) {
 61         return a > b + exp ? true : false;
 62     }
 63 
 64     public float distance(KMeanData a, KMeanData b) {
 65 
 66         return (float) Math.sqrt(Math.pow(a.getX() - b.getX(), 2)
 67                 + Math.pow(a.getY() - b.getY(), 2));
 68     }
 69 
 70     public boolean Kequal(KMeanData a, KMeanData b) {
 71         if (Math.abs(a.getY() - b.getY()) < exp && Math.abs(a.getX() - b.getX()) < exp)
 72             return true;
 73         return false;
 74     }
 75 
 76     public KMeanData[] produce(int size, int range) {
 77         KMeanData[] kmData = new KMeanData[size];
 78         for (int i = 0; i < size; i++) {
 79             kmData[i] = new KMeanData();
 80             kmData[i].setX((float) (Math.random() * range));
 81             kmData[i].setY(((float) Math.random() * range));
 82             kmData[i].setFlag(0);
 83         }
 84         return kmData;
 85     }
 86 
 87     public void kprint(KMeanData[] data, final int k) {
 88         for (int i = 1; i <= k; i++) {
 89             System.out.println("第" + i + "簇集合: ( " + this.topk.get(i - 1).getX() + " , " + this.topk.get(i - 1).getY() + " )");
 90             for (int j = 0; j < data.length; j++) {
 91                 if (data[j].getFlag() == i) {
 92                     System.out.print("( " + data[j].getX() + " , " + data[j].getY() + " )");
 93                 }
 94             }
 95             System.out.println("\n");
 96         }
 97     }
 98 
 99     public KMeanData[] kmeans(KMeanData[] data, final int k) {
100         if (null == data || data.length < 1) {
101             System.out.println("data is empty");
102             return null;
103         }
104         if (k > data.length) {
105             System.out.println("k " + k + " is too larger than data size " + data.length);
106             return null;
107         }
108        /*随机选取k个点*/
109         topk = new ArrayList<KMeanData>();
110         int stride = data.length / k;
111         //均值步长取k的初始簇
112         for (int i = 0; i < data.length; i += stride) {
113             data[i].setFlag((i / stride) + 1);
114             topk.add(data[i]);
115         }
116         //聚合
117         while (true) {
118             for (int i = 0; i < data.length; i++) {
119                 float min = (float) 1e9, dist;
120                 int pos = 0;
121                 for (KMeanData kter : topk) {
122                     if (!Kequal(kter, data[i]) && min > (dist = distance(data[i], kter))) {
123                         min = dist;
124                         pos = i;
125                     }
126                 }
127                 data[pos].setFlag((i / stride) + 1);
128             }
129             //重新计算质心
130             KMeanData[] ntopk = new KMeanData[k + 1];
131             int[] kcnt = new int[k + 1];
132             for (int i = 0; i < data.length; i++) {
133                 kcnt[data[i].getFlag()]++;
134                 ntopk[data[i].getFlag()] = new KMeanData();
135                 ntopk[data[i].getFlag()].setX(ntopk[data[i].getFlag()].getX() + data[i].getX());
136                 ntopk[data[i].getFlag()].setY(ntopk[data[i].getFlag()].getY() + data[i].getY());
137             }
138             for (int i = 1; i <= k; i++) {
139                 ntopk[i].setX(ntopk[i].getX() / kcnt[i]);
140             }
141             //判断一下是否是已经收敛了
142             boolean flag = false;
143             for (int i = 0; i < k; i++) {
144                 if (!Kequal(topk.get(i), ntopk[i + 1])) {
145                     flag = true;
146                     topk.set(i, ntopk[i + 1]);
147                 }
148             }
149             if (!flag) break;
150         }
151         return data;
152     }
153 }
View Code

相关文章:

  • 2022-02-07
  • 2021-05-01
  • 2022-02-14
  • 2021-12-20
  • 2021-07-12
  • 2022-12-23
  • 2021-11-30
  • 2021-07-20
猜你喜欢
  • 2021-09-21
  • 2021-10-18
  • 2021-10-16
  • 2021-12-05
  • 2021-06-15
  • 2022-12-23
  • 2022-12-23
相关资源
相似解决方案