Day_56-57kMeans 聚类

目录

Day_56-57 k-Means 聚类

一. 基本概念介绍

二. 具体过程

三. 代码实现与解释

        1. 导入数据与数据初始化

        2. 核心代码

        3. 后续信息的补充

        4. 距离计算和随机排列

四. 后续的数据分析

五. 运行结果


Day_56-57 k-Means 聚类

一. 基本概念介绍

        同我上一篇博客的介绍,机器学习从有无标签的角度有几大分类:监督学习,无监督学习和半监督学习。这里我们介绍的k-Means 算法就是无监督学习里面最具有代表性的一种,与分类(典型knn算法)等任务不同,聚类是在事先并不知道任何样本标签的情况下,通过数据之间的内在关系把样本划分为若干类别,使得同类别样本之间的相似度高,不同类别之间的样本相似度低(即增大类内聚,减少类间距)。

        它的基本过程是随机找寻k个节点作为始节点,然后从数据里面计算每个点到始节点的距离,理哪一个始节点比较近则第一次分类将这个节点分为一类。当所有的节点计算完毕(分类完成)之后,重新计算每个类的簇中心,然后继续上述的过程,直到分类的最终结果和每一个簇中心不再发生改变或者迭代次数用尽为止,最终我们将数据分成了k类。

二. 具体过程

        KMeans的核心目标是将给定的数据集划分成K个簇(K是超参),并给出每个样本数据对应的中心点。具体步骤非常简单,可以分为4步:

        1. 数据预处理,主要是标准化

        2. 随机选取k个中心,记为u_{1}^{(0)}u_{2}^{(0)}......u_{k}^{(0)}

        3. 定义优化目标J(c,u)=min\sum_{i=1}^{n}\left \| x_{i}-u_{j}^{(0)}\right \|

        4. 令t=1,2...为迭代步数,重复如下过程直到J收敛:

                4.1 对于每一个样本x_{i},将其分配到距离最近的中心

                4.2 对于每一个中心k,重新计算该类的中心

初始图
聚类1

聚类2
聚类3

完成图

三. 代码实现与解释

        1. 导入数据与数据初始化

        基本的变量设置MANHATTAN = 0表示曼哈顿计算距离方式,EUCLIDEAN = 1表示欧拉计算距离方式,dataset用来存储导入的数据,numClusters即k的数值(分成多少类),KMeans()函数表示导入的数据(路径为"D:/data/iris.arff"),setNumClusters(3)函数表示设置聚类的类的多少(分成多少类)

    /*** Manhattan distance.*/public static final int MANHATTAN = 0;/*** Euclidean distance.*/public static final int EUCLIDEAN = 1;/*** The distance measure.*/public int distanceMeasure = EUCLIDEAN;/*** A random instance;*/public static final Random random = new Random();/*** The data.*/Instances dataset;/*** The number of clusters.*/int numClusters = 2;/*** The clusters.*/int[][] clusters;/********************************** The first constructor.** @param paraFilename*            The data filename.********************************/public KMeans(String paraFilename) {dataset = null;try {FileReader fileReader = new FileReader(paraFilename);dataset = new Instances(fileReader);fileReader.close();} catch (Exception ee) {System.out.println("Cannot read the file: " + paraFilename + "\r\n" + ee);System.exit(0);} // Of try}// Of the first constructor/********************************** A setter.********************************/public void setNumClusters(int paraNumClusters) {numClusters = paraNumClusters;}// Of the setter

        2. 核心代码

        tempOldClusterArray用于存储每个节点被分为哪一类(1,2,3),tempClusterArray和tempOldClusterArray作用一致,但是是每一轮新的分类,tempOldClusterArray是上一轮的分类结果,tempCenters表示3个中心的位置(第一轮是随机设置中心位置,k=3,属性=4,3×4的一个矩阵),tempClusterLengths用于记录归入每个类的节点个数。

        while循环当新的分类和旧的分类一致时,结束循环。接着第二轮第三轮循环,计算一个节点i到各个中心的距离,记录最小值对应类别,保存到tempClusterArray矩阵里面。

        又有一个循环,用于累加同一个类的位置信息到tempNewCenters并且用于记录每个类的节点个数到tempClusterLengths。

        继续第三个循环,计算每个中心现在的位置到tempNewCenters,将新中心保存到tempCenters矩阵。

    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];// Step 1. Initialize centers.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 iint[] tempClusterLengths = null;while (!Arrays.equals(tempOldClusterArray, tempClusterArray)) {System.out.println("New loop ...");tempOldClusterArray = tempClusterArray;tempClusterArray = new int[dataset.numInstances()];// Step 2.1 Minimization. Assign cluster to each instance.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 jtempClusterArray[i] = tempNearestCenter;} // Of for i// Step 2.2 Mean. Find new centers.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 jtempClusterLengths[tempClusterArray[i]]++;} // Of for i// Step 2.3 Now averagefor (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 iSystem.out.println("Now the new centers are: " + Arrays.deepToString(tempNewCenters));tempCenters = tempNewCenters;} // Of while// Step 3. Form clusters.clusters = new int[numClusters][];int[] tempCounters = new int[numClusters];for (int i = 0; i < numClusters; i++) {clusters[i] = new int[tempClusterLengths[i]];} // Of for ifor (int i = 0; i < tempClusterArray.length; i++) {clusters[tempClusterArray[i]][tempCounters[tempClusterArray[i]]] = i;tempCounters[tempClusterArray[i]]++;} // Of for iSystem.out.println("The clusters are: " + Arrays.deepToString(clusters));}// Of clustering

        3. 后续信息的补充

        clusters为k(聚类的种类数)行矩阵,列还没有确定。接着一个循环创建每一行的长度为一个类的样本数,后面一个循环用于分类每个是哪个类。

        // Step 3. Form clusters.clusters = new int[numClusters][];int[] tempCounters = new int[numClusters];for (int i = 0; i < numClusters; i++) {clusters[i] = new int[tempClusterLengths[i]];} // Of for ifor (int i = 0; i < tempClusterArray.length; i++) {clusters[tempClusterArray[i]][tempCounters[tempClusterArray[i]]] = i;tempCounters[tempClusterArray[i]]++;} // Of for iSystem.out.println("The clusters are: " + Arrays.deepToString(clusters));

        4. 距离计算和随机排列

        这里不再详细说明,欢迎查看第51天博客

   /************************ Get a random indices for data randomization.** @param paraLength*            The length of the sequence.* @return An array of indices, e.g., {4, 3, 1, 5, 0, 2} with length 6.**********************/public static int[] getRandomIndices(int paraLength) {int[] resultIndices = new int[paraLength];// Step 1. Initialize.for (int i = 0; i < paraLength; i++) {resultIndices[i] = i;} // Of for i// Step 2. Randomly swap.int tempFirst, tempSecond, tempValue;for (int i = 0; i < paraLength; i++) {// Generate two random indices.tempFirst = random.nextInt(paraLength);tempSecond = random.nextInt(paraLength);// Swap.tempValue = resultIndices[tempFirst];resultIndices[tempFirst] = resultIndices[tempSecond];resultIndices[tempSecond] = tempValue;} // Of for ireturn resultIndices;}// Of getRandomIndices/************************ The distance between two instances.** @param paraI*            The index of the first instance.* @param paraArray*            The array representing a point in the space.* @return The distance.**********************/public double distance(int paraI, double[] paraArray) {int resultDistance = 0;double tempDifference;switch (distanceMeasure) {case MANHATTAN:for (int i = 0; i < dataset.numAttributes() - 1; i++) {tempDifference = dataset.instance(paraI).value(i) - paraArray[i];if (tempDifference < 0) {resultDistance -= tempDifference;} else {resultDistance += tempDifference;} // Of if} // Of for ibreak;case EUCLIDEAN:for (int i = 0; i < dataset.numAttributes() - 1; i++) {tempDifference = dataset.instance(paraI).value(i) - paraArray[i];resultDistance += tempDifference * tempDifference;} // Of for ibreak;default:System.out.println("Unsupported distance measure: " + distanceMeasure);}// Of switchreturn resultDistance;}// Of distance

四. 后续的数据分析

        1. 时间复杂度分析

        首先对于n个样本,聚类为k个类,现在的时间复杂度为O(kn),再加上迭代次数t,故而最终的时间复杂度为O(knt)(k是聚为多少类,n是数据总量个数,t是迭代次数)

        2. 对于特殊数据的处理

        由于k-means算法是基于"距离"进行计算的,而“距离”却是基于向量的。对于有些数据的某一个向量,若方差较大的话将对数据的聚类结果产生决定性影响,所以对于聚类前的数据进行归一化和单位化相当有必要。此外对于极个别噪声数据应该检测出来,排除它对中心的影响。

        3. 对于k值的选择

        由于聚类的效果收到初始k值的影响,我们可以用试触法确定最佳的k值,即取k为不同的值,每次计算我们的优化目标J(c,u)=min\sum_{i=1}^{n}\left \| x_{i}-u_{j}^{(0)}\right \|的值,最后取一个最合适的值作为k值。

        4. 改进初始值的选择

        之前我们采取随机选择K个中心的做法,可能导致不同的中心点距离很近,就需要更多的迭代次数才能收敛。如果在选择初始中心点时能让不同的中心尽可能远离,效果往往更好。这类算法中,以K-Means++算法最具影响力。

五. 运行结果

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/56.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Linux】打开Linux大门,踏入Linux世界(环境搭建再加一群Linux基本指令就OK啦~)

&#x1f9d1;‍&#x1f393;个人主页&#xff1a;简 料 &#x1f3c6;所属专栏&#xff1a;Linux系统编程与网络编程 &#x1f3c6;个人社区&#xff1a;越努力越幸运社区 &#x1f3c6;简 介&#xff1a;简料简料&#xff0c;简单有料~在校大学生一枚&#x…

MySQL表的约束

目录 前言 1.什么是约束 2.空属性 3.默认值 4.列描述 5.zerofill 6.主键 7.自增长 8.唯一键 9.外键 总结 前言 hello&#xff0c;各位小伙伴大家好&#xff0c;本章内容为大家介绍关于MySQL约束的相关内容&#xff0c;关于约束这个概念&#xff0c;如果是第一次接触可…

redis---基础(部署及常用命令)

目录 前言一、关系型数据库与非关系型数据库1. 关系型数据库2. 非关系型数据库3. 关系型数据库和非关系型数据库区别4. 非关系型数据库产生背景小结&#xff1a; 二、Redis简介1. 单进程快速的原因&#xff1a;2.epoll 机制优势&#xff1a; 三、Redis 具有以下几个优点四、red…

机器学习之LDA算法

目录 LDA算法 LDA目标 LDA原理推导 LDA除法模型 LDA减法模型 LDA除法正则模型 LDA减法正则模型 证明&#xff1a;StSwSb LDA算法流程 LDA优点 LDA缺点 基于LDA的人脸识别 LDA算法 线性判别分析&#xff08;linear discriminant analysis&#xff0c;LDA&#xff0…

计算机网络——物理层

物理层 物理层是计算机网络体系结构中的底层层级&#xff0c;负责处理计算机与物理传输媒介之间的接口和通信细节。它主要关注如何在物理媒介上传输原始比特流&#xff0c;并确保数据能够可靠地从发送方传输到接收方。 物理层的主要任务包括&#xff1a; 传输介质&#xff1a…

2023年第三届陕西省大学生网络安全技能大赛--本科高校组 Reverse题解

文章目录 一. 我的upx -d怎么坏了1. 查看节区信息2. 动态调试脱壳3.输出迷宫图4.走迷宫 二. babypython1.字节码简单分析2. gpt分析3. 程序逻辑4.解题脚本 三. BadCoffee1. 相关文章2.解混淆3.解题脚本 四. Web&Assembly(暂时没复现出来,提供一些相关文章)总结 这次比赛做出…

Qt的基本知识与应用

一、C梳理 1. 面向对象的三大特性 1.1 封装 把类的一些属性和细节隐藏&#xff08;private、protected&#xff09;&#xff0c;根据读写需要重新开放外部调用接口&#xff08;public、protected&#xff09;。 1.2 继承 在已有的类的基础上创建一个新的类&#xff0c;新的类拥…

【网络原理】数据链路层 和 应用层 重点协议

✨个人主页&#xff1a;bit me&#x1f447; ✨当前专栏&#xff1a;Java EE初阶&#x1f447; 目 录 &#x1f340;一. 以太网协议&#xff08;数据链路层&#xff09;&#x1f33b;二. DNS &#xff08;应用层&#xff09;&#x1f33f;三. 网络原理知识面试总结 &#x1f34…

40 # npm 的使用

npm 3n&#xff1a; nrm&#xff1a;node 中源管理工具nvm&#xff1a;node 中的版本管理工具npm&#xff1a;node 的包管理器&#xff0c;管理的都是 node 的模块 第三方模块 分两种&#xff1a; 全局模块&#xff1a;只能在命令行中使用&#xff0c;任何路径都可以本地模…

Vue Router activated deactivated 路由守卫

6.12.activated deactivated activated和deactivated是路由组件所独有的两个钩子&#xff0c;用于捕获路由组件的激活状态具体使用 activated路由组件被激活时触发deactivated路由组件失活时触发 src/pages/News.vue <template><ul><li :style"{opacity}…

Spring Boot定时任务

目录 1.概述 2.Spring Boot定时任务 2.1.快速使用 2.2.cron表达式 3.业务示例 3.1.业务描述 3.2.业务实现 4.实现原理 5.自定义线程池 1.概述 在某些业务场景中&#xff0c;需要定时执行一些任务&#xff0c;有可能是定时统计然后生成报表&#xff0c;有可能是定时发…

一个好看美观的登录注册界面的实现

序言&#xff1a;之前介绍那个博客&#xff0c;然后自己搞了这个界面。最近有人和我要&#xff0c;把代码给大家贴出来&#xff0c;提供参考。 首先是这个界面哈 <!DOCTYPE html> <html lang"en"> <head><script src"../static/lib/jquer…