栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

日撸java 三百行 趁热打铁(03)kMeans 聚类

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

日撸java 三百行 趁热打铁(03)kMeans 聚类

KMeans是无监督学习的算法之一,在KNN中我们明确的已经知道了每个数据对象事物分类,而KMeans则没有数据所对应的类别,我们需要将数据中相似的可能是一类的给聚在一起。同一类我们把它称为一个簇。
今天用的数据集和之前kNN的是同一个,但是我们要忽略掉类别那一列(最后一列)
算法思想:
首先我们要虚拟出K个簇心,为了方便,直接取数据集的前K个成为簇心,然后遍历数据集,让每个数据对象都归顺于最近的那个簇心,由于数据变动簇心很可能也会变动(如果不变了,分类也就完成了),当然也有可能运气好第一次随机取的点就是最后的簇心(根本不可能),这个算法要做的就是不断的归顺簇心,然后更新簇心,直到簇心不变了,也就归顺的过程稳定了,每个数据对象都认死一个大哥,不会三心二意了,分簇也就算完成了。

今天的核心代码就一个(其余声明于KNN的一样包括数据集的随机打乱过程):

 public void clustering() {
        int[] tempOldClusterArray = new int[dataset.numInstances()];
        tempOldClusterArray[0] = -1;
        int[] tempClusterArray = new int[dataset.numInstances()];
        Arrays.fill(tempClusterArray, 0);
        double[][] tempCenters = new double[numClusters][dataset.numAttributes() - 1];
        int[] tempRandomOrders = getRandomIndices(dataset.numInstances());
        for (int i = 0; i < numClusters; i++) {
            for (int j = 0; j < tempCenters[0].length; j++) {
                tempCenters[i][j] = dataset.instance(tempRandomOrders[i]).value(j);
            } // Of for j
        } // Of for i
        int[] tempClusterLengths = null;
        while (!Arrays.equals(tempOldClusterArray, tempClusterArray)) {
            System.out.println("New loop ...");
            tempOldClusterArray = tempClusterArray;
            tempClusterArray = new int[dataset.numInstances()];
            int tempNearestCenter;
            double tempNearestDistance;
            double tempDistance;
            for (int i = 0; i < dataset.numInstances(); i++) {
                tempNearestCenter = -1;
                tempNearestDistance = Double.MAX_VALUE;
                for (int j = 0; j < numClusters; j++) {
                    tempDistance = distance(i, tempCenters[j]);
                    if (tempNearestDistance > tempDistance) {
                        tempNearestDistance = tempDistance;
                        tempNearestCenter = j;
                    } // Of if
                } // Of for j
                tempClusterArray[i] = tempNearestCenter;
            } // Of for i
            tempClusterLengths = new int[numClusters];
            Arrays.fill(tempClusterLengths, 0);
            double[][] tempNewCenters = new double[numClusters][dataset.numAttributes() - 1];
            // Arrays.fill(tempNewCenters, 0);
            for (int i = 0; i < dataset.numInstances(); i++) {
                for (int j = 0; j < tempNewCenters[0].length; j++) {
                    tempNewCenters[tempClusterArray[i]][j] += dataset.instance(i).value(j);
                } // Of for j
                tempClusterLengths[tempClusterArray[i]]++;
            } // Of for i
            for (int i = 0; i < tempNewCenters.length; i++) {
                for (int j = 0; j < tempNewCenters[0].length; j++) {
                    tempNewCenters[i][j] /= tempClusterLengths[i];
                } // Of for j
            } // Of for i
            System.out.println("Now the new centers are: " + Arrays.deepToString(tempNewCenters));
            tempCenters = tempNewCenters;
        } // Of while
        clusters = new int[numClusters][];
        int[] tempCounters = new int[numClusters];
        for (int i = 0; i < numClusters; i++) {
            clusters[i] = new int[tempClusterLengths[i]];
        } // Of for i

        for (int i = 0; i < tempClusterArray.length; i++) {
            clusters[tempClusterArray[i]][tempCounters[tempClusterArray[i]]] = i;
            tempCounters[tempClusterArray[i]]++;
        } // Of for i

        System.out.println("The clusters are: " + Arrays.deepToString(clusters));
    }// Of clustering

tempOldClusterArray[]与tempClusterArray[]表示每个对象所对应的簇号,数组下标i表示第i个数据对象,对应的数组值表示当前所属的簇号。两个数组一个表示当前的分簇情况,另一个是上一次的分簇情况,两个数组相同时分簇完成(初始化时得保证他两不一样,不然第一个循环就跳出了)。

tempClusterLengths[]的下标 i 表示簇号,本身的值代表簇号为 i 的簇当前有多少个归顺的小弟,这个总数之后算平均值的时候用到。

clusters[][]是记录最终聚类情况的二维数组,第一个下标 i 表示簇号,第二个下标 j 表示当前簇的第j个数据,本身的值代表原数据集中的编号。clusters[0][9]表示第0号簇的第九号元素的编号。

主方法:

 public static void testClustering() {
        KMeans tempKMeans = new KMeans("C:/Users/胡来的魔术师/Desktop/sampledata-main/iris.arff");
        tempKMeans.setNumClusters(3);
        tempKMeans.clustering();
    }// Of testClustering

    
    public static void main(String arags[]) {
        testClustering();
    }// Of main

}// Of class KMeans

运行结果:

总结:感觉这几个算法的核心部分都是大同小异,反倒是数据的管理与记录花的功夫要大一些。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/859478.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号