聚类算法(2)--- ISODATA算法

       本篇文章是博主在人工智能等领域学习时,用于个人学习、研究或者欣赏使用,并基于博主对人工智能等领域的一些理解而记录的学习摘录和笔记,若有不当和侵权之处,指出后将会立即改正,还望谅解。文章分类在AI学习笔记

      AI学习笔记(8)---聚类算法(2)--- ISODATA算法》

聚类算法(2)--- ISODATA算法

目录

一、 ISODATA算法

1.1算法原理

1.2实验应用

二、 ISODATA算法python实现

2.1 算法流程

2.2 算法python程序

2.3 算法注意事项

三、 ISODATA算法实验结果

四、小结


一、 ISODATA算法

        ISODATA算法(Iterative Self-Organizing Data Analysis Technique Algorithm)是一种经典的聚类算法,结合了K-均值和层次聚类的特点。该算法通过动态调整簇的数量和簇的中心点,能够根据数据特点自适应地调整聚类情况。

其他聚类算法见:

聚类算法(1)---最大最小距离、C-均值算法

1.1算法原理

        SODATA算法采用迭代的方式动态地更新簇的数目和簇的中心,根据设定的参数来调整簇的数量以及样本点与簇之间的距离等。算法首先初始化聚类中心并对样本进行初步的分组,然后根据一定

1.2实验应用

        ISODATA算法在实际应用中有着广泛的应用,特别是在数据挖掘、图像处理和生物信息学等领域。例如在地理信息系统(GIS)领域,ISODATA算法可以用于空间数据的聚类分析,对地理位置数据进行聚类,以实现地理空间上的模式识别和区域划分。


二、 ISODATA算法python实现

        ISODATA(Iterative Self-Organizing Data Analysis Technique)算法是一种自组织数据分析技术,主要用于聚类分析。其算法流程如下:

2.1 算法流程

(1)初始化参数:选择初始的簇中心数量K、设定其他参数(如每个簇的最小样本数、簇内样本方差阈值等),并随机选择K个点作为初始的簇中心。

(2)分配样本:对于数据集中的每个样本点,计算它与各个簇中心的距离,并将其分配到距离最近的簇中。

(3)簇合并:检查每个簇的样本方差是否大于预设的阈值,如果是,则将该簇进行分裂,生成新的簇中心。

(4)簇分裂:重复执行步骤2和步骤3,直至满足终止条件(如簇中心不再发生大的变化、达到最大迭代次数等)。

(5)更新簇中心:根据当前的簇分配情况,重新计算每个簇中所有样本点的均值,以此更新簇中心的位置。

(6)重复迭代:重复执行步骤2至步骤5,直至满足终止条件(如簇中心不再发生大的变化、达到最大迭代次数等)。

(7)输出结果:得到K个簇,每个簇包含若干个样本点,完成聚类过程。

2.2 算法python程序

导入需要的python库

import numpy as np
import matplotlib.pyplot as plt
from sklearn.metrics import euclidean_distances
import copy

ISODATA聚类算法

class ISODATA():def __init__(self, designCenterNum, Nc, LeastSampleNum, StdThred, LeastCenterDist, L, iterationNum):#  指定预期的聚类数、初始聚类中心个数、每类的最小样本数、标准差阈值、最小中心距离、每次可合并的最多对数、迭代次数self.K = designCenterNumself.centerNum = Ncself.thetaN = LeastSampleNumself.thetaS = StdThredself.thetaC = LeastCenterDistself.L = Lself.iteration = iterationNumself.data = np.stack([[0, 0], [0, 1], [4, 4], [4, 5], [5, 4], [5, 5], [1, 0]], dtype=np.float64)self.label = np.stack([0, 0, 0, 0, 0, 0, 0])# 随机选取NC个初始聚类中心center_ind = np.random.choice(np.arange(len(self.data), dtype=np.int32), Nc, replace=False)self.center = np.stack([copy.deepcopy(self.data[center_ind[i], :]) for i in range(Nc)])self.centerMeanDist = 0# 更新def updateLabel(self):# 计算样本到中心的距离distance = euclidean_distances(self.data, self.center.reshape((self.centerNum, -1)))# 选出每个模式到各个中心的最小距离,并为样本重新分配标签self.label = np.argmin(distance, 1)for i in range(self.centerNum):# 找出同一类样本index = np.argwhere(self.label == i).squeeze()sameClassSample = self.data[index, :]# 更新中心if len(sameClassSample.shape) >= 2:self.center[i, :] = np.mean(sameClassSample, 0)# 计算所有类到各自中心的平均距离之和for i in range(self.centerNum):# 找出同一类样本index = np.argwhere(self.label == i).squeeze()sameClassSample = self.data[index, :]if len(sameClassSample.shape) < 2:sameClassSample = sameClassSample.reshape((1,-1))# 计算样本到中心距离的平均值distance = np.mean(euclidean_distances(sameClassSample, self.center[i, :].reshape((1, -1))))# 更新中心self.centerMeanDist += distanceself.centerMeanDist /= self.centerNumdef divide(self):# 临时保存更新后的中心集合,否则在删除和添加的过程中顺序会乱newCenterSet = self.center# 计算每个类的样本在每个维度的标准差for i in range(self.centerNum):# 找出同一类样本index = np.argwhere(self.label == i).squeeze()sameClassSample = self.data[index, :]# 计算样本到中心每个维度的标准差stdEachDim = np.mean((sameClassSample - self.center[i, :])**2, axis=0)if type(stdEachDim) is not np.ndarray:maxStd = stdEachDimsameClassSample = sameClassSample.reshape(1,-1)# 找出其中维度的最大标准差else:maxIndex = np.argmax(stdEachDim)maxStd = stdEachDim[maxIndex]# 计算样本到本类中心的距离distance = np.mean(euclidean_distances(sameClassSample, self.center[i, :].reshape((1, -1))))# 如果最大标准差超过了阈值if maxStd > self.thetaS:# 还需要该类的样本数大于于阈值很多 且 太分散才进行分裂if self.centerNum <= self.K//2 or \sameClassSample.shape[0] > 2 * (self.thetaN+1) and distance >= self.centerMeanDist:newCenterFirst = self.center[i, :].copy()newCenterSecond = self.center[i, :].copy()newCenterFirst[maxIndex] += 0.5 * maxStdnewCenterSecond[maxIndex] -= 0.5 * maxStd# 删除原始中心newCenterSet = np.delete(newCenterSet, i, axis=0)# 添加新中心newCenterSet = np.vstack((newCenterSet, newCenterFirst))newCenterSet = np.vstack((newCenterSet, newCenterSecond))else:continue# 更新中心集合self.center = newCenterSetself.centerNum = self.center.shape[0]def combine(self):# 临时保存更新后的中心集合,否则在删除和添加的过程中顺序会乱delIndexList = []# 计算中心之间的距离centerDist = euclidean_distances(self.center, self.center)centerDist += (np.eye(self.centerNum)) * 10**10# 把中心距离小于阈值的中心对找出来,每次和并数量少于L对for i in range(self.L):# 如果最小的中心距离都大于阈值的话,则不再进行合并minDist = np.min(centerDist)if minDist >= self.thetaC:break# 否则合并(两个中心距离太近合并)index = np.argmin(centerDist)row = index // self.centerNumcol = index % self.centerNum# 找出合并的两个类别index = np.argwhere(self.label == row)classNumFirst = len(index)index = np.argwhere(self.label == col)classNumSecond = len(index)newCenter = self.center[row, :] * (classNumFirst / (classNumFirst+ classNumSecond)) + \self.center[col, :] * (classNumSecond / (classNumFirst+ classNumSecond))# 记录被合并的中心delIndexList.append(row)delIndexList.append(col)# 增加合并后的中心self.center = np.vstack((self.center, newCenter))self.centerNum -= 1# 标记,以防下次选中centerDist[row, :] = float("inf")centerDist[col, :] = float("inf")centerDist[:, col] = float("inf")centerDist[:, row] = float("inf")# 更新中心self.center = np.delete(self.center, delIndexList, axis=0)self.centerNum = self.center.shape[0]def drawResult(self):color = ['r', 'b', 'g', 'c', 'm', 'y']ax = plt.gca()ax.clear()for i in range(self.centerNum):index = np.argwhere(self.label == i).squeeze()ax.scatter(self.data[index, 0], self.data[index, 1], c=color[i], label=f'Cluster { i}')ax.scatter(self.center[i,0], self.center[i,1], c=color[i], marker='x',label=f'Centroid { i}')# ax.set_aspect(1)# 坐标信息plt.title('ISODATA Clustering')plt.xlabel('X')plt.ylabel('Y')plt.legend()plt.show()def start(self):# 初始化中心和labelself.updateLabel()self.drawResult()# 到设定的次数自动退出for i in range(self.iteration):# 如果是偶数次迭代或者中心的数量太多,那么进行合并if self.centerNum < self.K //2:self.divide()# 偶数次迭代或者中心数大于预期的一半,进行合并elif (i > 0 and i % 2 == 0) or self.centerNum > 2 * self.K:self.combine()else:self.divide()# 更新中心self.updateLabel()print("中心数量:{}".format(self.centerNum))self.drawResult()

主函数

if __name__ == "__main__":isoData = ISODATA(designCenterNum=2, Nc=3, LeastSampleNum=1, StdThred=0.1, LeastCenterDist=2, L=3, iterationNum=5)isoData.start()

2.3 算法注意事项

        ISODATA算法相比于传统的K-means算法增加了簇合并和簇分裂的步骤,这使得算法能够动态地调整簇的数量和形状,适应数据的复杂性。在实际应用中,还可以根据具体情况对参数进行调整,以获得更好的聚类效果。


三、 ISODATA算法实验结果

相关参数设置:

参数类型

数值

预期的聚类数

2

初始聚类中心个数

3

每类的最小样本数

3

标准差阈值

0.1

最小中心距离

2

每次可合并的最多对数

3

迭代次数

5

(1)数据可视化聚类单步输出结果:

第一步                                                 第二步

第三步                                                 第四步

第五步 

        由多次实验结果可知,一般运行到五步以内即可达到聚类目的,合理设置相关参数可以达到满足聚类的要求。

(1)调整预期聚类数:

预期的聚类数=3时,

第一步运行结果                                 最终运行结果

预期的聚类数=5时,

第一步运行结果                                    最终运行结果

        由此实验可知,设置预期的聚类数为3或者5,聚类的最终结果分类为2类。后续经过多次其他预期的聚类数设置,得到结果聚类分类为2类,初步推算,预期聚类数的设置不影响最终聚类的结果。若修改其他参数,也可分析相应的实验输出结果。


四、小结

        ISODATA算法是基于C-均值算法的改进,增加了簇的合并和分裂机制,使其能够动态地调整簇的数量和形状,适应数据的复杂性。这使得ISODATA算法更适用于数据集具有复杂形状、密度不均匀、簇的数量变化较大的情况。然而,对于该算法来说,需要合理设置参数,并且算法复杂度较高,需要更多的计算资源和时间。

        通过合理选择算法、优化参数和评估结果,可以实现对提供的数据成功的进行聚类。在实际应用中,通常会根据具体情况综合考虑算法的优缺点,选择合适的算法,并不断优化参数,以获得满足实际需求的聚类效果。


     文章若有不当和不正确之处,还望理解与指出。由于部分文字、图片等来源于互联网,无法核实真实出处,如涉及相关争议,请联系博主删除。如有错误、疑问和侵权,欢迎评论留言联系作者,或者私信联系作者。

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

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

相关文章

专业技能篇---计算机网络

文章目录 前言计算机网络基础一、网络分层模型 HTTP一、从输入URL到页面显示发生了什么&#xff1f;二、Http的状态码有哪些&#xff1f;三、 HTTP与HTTPS有什么区别&#xff1f;四、URI 和 URL 的区别是什么?五、Cookie和Session有什么区别&#xff1f;六、GET与POST WebSock…

初阶 《数组》 4. 数组作为函数参数

4. 数组作为函数参数 往往我们在写代码的时候&#xff0c;会将数组作为参数传给函数。比如&#xff1a;我要实现一个冒泡排序函数&#xff08;将一个整形数组排序&#xff09; 4.1 冒泡排序函数的错误设计 #include <stdio.h> void bubble_sort(int arr[]) {int sz s…

智慧工厂监控可视化解决方案(160页WORD)

方案介绍&#xff1a; 本智慧工厂监控可视化解决方案通过集成先进的物联网和大数据技术&#xff0c;为制造业企业提供了全面的数字化转型支持。通过实时监控、数据分析、可视化展示等功能&#xff0c;帮助企业提升生产效率、降低运营成本、优化产品质量和能源利用率&#xff0…

【Python】从基础到进阶(一):了解Python语言基础以及变量的相关知识

&#x1f525; 个人主页&#xff1a;空白诗 文章目录 引言一、Python简介1.1 历史背景1.2 设计哲学1.3 语言特性1.4 应用场景1.5 为什么选择Python 二、Python语言基础2.1 注释规则2.1.1 单行注释2.1.2 多行注释2.1.3 文件编码声明注释 2.2 代码缩进2.3 编码规范2.3.1 命名规范…

【pytorch02】手写数字问题引入

1.数据集 现实生活中遇到的问题 车牌识别身份证号码识别快递单的识别 都会涉及到数字识别 MNIST&#xff08;收集了很多人手写的0到9数字的图片&#xff09; 每个数字拥有7000个图像train/test splitting:60k vs 10k 图片大小28 28 数据集划分成训练集和测试集合的意义…

springboot + Vue前后端项目(第十七记)

项目实战第十七记 写在前面1. 个人信息1.1 Person.vue1.2 设置路由并改动Header.vue1.3 动态刷新头像1.3.1 在保存个人信息时&#xff0c;触发方法1.3.2 父组件Manage.vue1.3.3 再将user以prop方式传递给子组件Header.vue1.3.4 Header.vue使用user 1.4 效果图 2. 修改密码2.1 前…

配置 python 脚本操作Excel 环境

在已装python的前提下 一、安装依赖库 pip install pandas pip install openpyxl安装完后&#xff0c;可以在 Python 中运行以下命令来查看 pandas 或 openpyxl 的安装路径&#xff1a; import pandas as pd print(pd.__path__)import openpyxl print(openpyxl.__path__)二、测…

【CT】LeetCode手撕—415. 字符串相加

目录 题目1- 思路2- 实现⭐415. 字符串相加——题解思路 3- ACM 实现 题目 原题连接&#xff1a;415. 字符串相加 1- 思路 模式识别&#xff1a;字符串相加 逆向遍历过程模拟 数据结构 ① String res &#xff1a;记录res 、② carry 记录进位值① 定义两个整数遍历 nums1 …

本地项目上传到gitee

本地项目通过webstorm上传到gitee 1.登录gitee选择新建仓库 2.输入新建仓库的名字&#xff08;名字与本地项目名一致&#xff09; 3.复制链接 4.找到本地项目&#xff0c;选中地址输入cmd打开命令提示框 5.输入git init初始化git&#xff0c;生成.git文件 6.webstorm中打开项目…

Android修行手册-ImageView的adjustViewBounds和设置透明度

点击跳转>GameFramework文档系列&#xff08;二&#xff09;- 场景相关 点击跳转>GameFramework文档系列&#xff08;三&#xff09;- 日志管理和UI 点击跳转>GameFramework文档系列&#xff08;四&#xff09;- 事件订阅 点击跳转>保姆式Cocos合成大西瓜案例 …

JDK19特性

JDK19特性 一、JAVA19概述 JDK 19 2022 年 9 月 20 日正式发布以供生产使用,非长期支持版本。不过,JDK 19 中有一些比较重要的新特性值得关注。 JDK 19 只有 7 个新特性: JEP 405: Record Patterns(记录模式)[1] (预览)JEP 422: Linux/RISC-V Port[2]JEP 424: Foreign …

qt 一个可以拖拽的矩形

1.概要 2.代码 2.1 mycotrl.h #ifndef MYCOTRL_H #define MYCOTRL_H#include <QWidget> #include <QMouseEvent>class MyCotrl: public QWidget {Q_OBJECT public://MyCotrl();MyCotrl(QWidget *parent nullptr); protected:void paintEvent(QPaintEvent *even…

DVWA 靶场 CSP Bypass 通关解析

前言 DVWA代表Damn Vulnerable Web Application&#xff0c;是一个用于学习和练习Web应用程序漏洞的开源漏洞应用程序。它被设计成一个易于安装和配置的漏洞应用程序&#xff0c;旨在帮助安全专业人员和爱好者了解和熟悉不同类型的Web应用程序漏洞。 DVWA提供了一系列的漏洞场…

高速公路声光预警定向广播助力安全出行

近年来&#xff0c;高速重大交通事故屡见不鲜&#xff0c;安全管控一直是高速运营的重中之重。如何利用现代化技术和信息化手段&#xff0c;创新、智能、高效的压降交通事故的发生概率&#xff0c;优化交通安全管控质量&#xff0c;是近年来交管部门的主要工作&#xff0c;也是…

STM32人工智能检测-筛选机器人

前言 本文描述了一种使用STM32进行机器人筛选的办法。筛选对象是我的粉s&#xff0c;删选办法是瞪眼法。 问题现象 每次当我的STM32 向外界发出一篇新的的报文&#xff0c;总能在1H之内得到focus&#xff0c;格式如下 [title][body][tail]于是我对各个focus 我报文的对象进…

Flask之模板

前言&#xff1a;本博客仅作记录学习使用&#xff0c;部分图片出自网络&#xff0c;如有侵犯您的权益&#xff0c;请联系删除 目录 一、模板的基本用法 1.1、创建模板 1.2、模板语法 1.3、渲染模板 二、模板辅助工具 2.1、上下文 2.2、全局对象 2.3、过滤器 2.4、测试…

C语言| 数组倒置算法

数组倒置 方法一 1 定义两个数组a[5] b[5],两个循环变量i j 2 用for循环&#xff0c;把数组a的最后一个数&#xff0c;赋值给数组b第一个元素 3 输出数组b 【程序代码】 #include <stdio.h> int main(void) { int a[5] {11, 22, 33, 44, 55}; int b[5]; …

进程、线程的区别

进程、线程的关系 开工厂生产手机&#xff0c;制作一条生产线&#xff0c;这个生产线上有很多的器件以及材料。一条生产线就是一个进程。 只有生产线是不够的&#xff0c;使用找五个工人来进行生产&#xff0c;这个工人能够利用这些材料最终一步步的将手机做出来&#xff0c;这…

内外网映射访问内网服务器

如果本地有公网ip&#xff0c;比如连接的宽带有公网ip&#xff0c;可以直接通过路由配置转发就行了&#xff0c;如果本地没有公网ip&#xff0c;那就需要通过下面这种方式来访问内网服务器了。 1&#xff1a;首先内网服务器需要连接外网&#xff0c;可以通过网线或者WiFi都可以…

RabbitMQ实践——交换器(Exchange)绑定交换器

在《RabbitMQ实践——交换器&#xff08;Exchange&#xff09;和绑定&#xff08;Banding&#xff09;》一文中&#xff0c;我们实验了各种交换器。我们可以把交换器看成消息发布的入口&#xff0c;而消息路由规则则是由“绑定关系”&#xff08;Banding&#xff09;来定义&…