k均值聚类算法优缺点_Grasshopper实现K均值聚类算法

本文很长很长,有很多很多图,包含以下部分:

1.算法简介

2.如何分类平面点

3.如何分类空间点

4.如何分类多维数据

5.后记

提醒:以下内容包括:智障操作,无中生友,重复造轮子 等

1.算法简介

k均值聚类算法(k-means),这东西是什么意思?

k均值聚类算法(k-means clustering algorithm)是一种迭代求解的聚类分析算法,其步骤是随机选取K个对象作为初始的聚类中心,然后计算每个对象与各个种子聚类中心之间的距离,把每个对象分配给距离它最近的聚类中心。聚类中心以及分配给它们的对象就代表一个聚类。每分配一个样本,聚类的聚类中心会根据聚类中现有的对象被重新计算。这个过程将不断重复直到满足某个终止条件。终止条件可以是没有(或最小数目)对象被重新分配给不同的聚类,没有(或最小数目)聚类中心再发生变化,误差平方和局部最小。——百度百科

我用人话解释一下:

假如你有一些平面上的点,大概如下图。你想把它们分组,离得近的点分到同一组去,离得远的分到不同的组。

9bf1dc43fcffdcf2cd72a97aa306e53c.png

你估摸了一下,大概知道要分9组,别的限制条件一概不知,这时候就非常适合用这种简单粗暴的方法。

方法是这样的:

1.在这些点的范围内,随机取9个点,取名为“聚类中心”。注意,是随机的,想怎么取就怎么取。

850900340e733df1997191405a6686dd.png

2.对每一个点,计算它到9个聚类中心的位置,找到最近的聚类中心,并将其划分到那一组中

3db0c3d310d17da8ea6041579f7c976c.png

9c7d2bf3292bc562dd5f4ae38c8f91f2.png

很明显,分组的情况相当糟糕,毕竟聚类中心是随机的嘛。

3.对每一个组内的点,求出平均点,并将其作为新的聚类中心,在下图中,绿色点是新的聚类中心。

539c90b73796a497558e28d6fc475e6c.png

4.重复2、3的步骤,直到分组情况不再变化

437dc1d8d560b57f02c2b709699a6b7f.gif

这就是k均值聚类算法的平面应用方式,接下来介绍在grasshopper里如何实现它。

2.如何分类平面点

首先画一些点,拾取进grasshopper中;求出这些点的bounding box,以此为边界,使用populate 3d/2d生成9个点作为聚类中心。

fc1dabb9dff93e9762ec00b939e14ee7.png

以聚类中心为起始点,生成泰森多边形,泰森多边形内的点就是被分到该组的点。使用Point In Curve搭配 Cull Pattern实现这一步

(当然,可以计算距离然后排序,这两种方法是等效的。只不过在平面的情况下,这里选择了更直观的方法)

1c9cf16e2b4bdcdda75f520e055871a7.png

使用average,求出各组平均点。

564dbc781114f06b900f008576089f82.png

使用插件anemone,根据上文所述,在Populate 3D后设立循环起点,在average后设立循环终点,并让控制循环的两个电池对应,设立最大循环次数。

d8e7c8d43853d5333df707f0109cb87e.png

OK,完美!我们的“平面kmeans.gh”正式完成!

望着简单优雅的电池图和灵巧变动的迭代动画,电脑前的你获得了前所未有的满足感。

7481f8029a1a982d2643787555425eeb.png

然而,你很快发现这个电池并不完美。

首先它没有显示结果。虽然分组完毕,但是并不直观。

你拖出了Convex Hull,解决了这一问题。

fedb781102520a6af99e388c28b198fa.png

显示分组结果之后你马上发现,即便是迭代了十余次,分组结果已经稳定,这个结果还是不能让你满意。

1317a159102492f9f76d4042b9ad8c21.png

首先,本来是要分9组的,现在它只有8组,;而且右边有两组紧挨着的点,凭什么他们不能分到一组去?

原因在于初始聚类中心上。因为它是随机的,所以可能有一个聚类中心和所有点都距离很远,没有点在它那一组,导致它成了光杆司令。

因为第一次分组它就没有组员,所以以后也不再会有,最终导致结果少了一组。

851ef7d52125050b43cec8db08754297.png

同理,两个聚类中心之间存在一大批点,最终会导致两个中心势均力敌,平分这些点。

2edf3505cd2d9a4cca07f982d8439e91.png

要解决这些问题,只能调整随机的种子,直到结果令人满意。

15429b238d48efd7ccfaa13235263e01.png

解决了分组问题,你隐隐约约觉得还有哪里不对劲,没错,就是循环的部分。

现在,运算结果会不停迭代直至最大次数,这就面临着“最大迭代次数设置为多少是合适的”的问题。太大,浪费资源;太小,分组情况不稳定。一般来说,人们习惯性地设为100,当然这只是权宜之计,略有强迫症的你决定做出可以终止迭代的部分。

根据算法定义,当分组情况不变时,停止迭代。

Loop End电池的exit端等于TRUE时,停止迭代。

也就是说,比较一下本次运算和上次运算时的分组情况,如果相同,则输出true到exit端。

“分组情况”是什么?

89768c8334ed0a67e59f36fd2564bd35.png

是每一组内点的数量(列表长度)。把这些数据转换成一个数据,而且还能避免误判的一个最简便的方式,就是Construct Path。

4e936c7bdaef2fb5d1730fcc6bb92c91.png

这样,“分组情况”就能被一行唯一的文字代表,只要用match text把它和上一次迭代时的文字比较就行了。

但是可惜,anemone没有查看迭代过程中的上次数据的功能,(如果有,请教教我)只能自己做了。如下图:

5621fab27e47b85b0b22f0ed9e9adcca.png

这一部分是什么意思呢?

Data Recorder记录所有通过的数据。

List Item列出本次和上次迭代的文字。

Replace Nulls是为了用随便什么别的文字替换掉null。因为如果Data Recorder记录的数据不足两个,list item的-1端会和i端一致,使得循环结束,所以必须将wrap设为false;这样就导致-1端会变成null,所以必须将它替换掉。

最后就是match text,当两输入端一致时输出true,搞定。

最终成果如下

f9094cdf1cf0a98ddf08e68b3311cdbb.png

OK,完美!我们的“平面kmeans改.gh”正式完成!

望着简单粗暴的电池图和完全自动的迭代过程,电脑前的你获得了前所未有的满足感。

7481f8029a1a982d2643787555425eeb.png

随着鼠标的一阵抖动,整个电池图索然无味。

处于贤者时间的你不禁想到,这个方法可以拓展到3维空间里吗?


3.如何分类空间点

灵巧的双手穿针引线,类比的思维高速运转——顷刻,能够处理空间点的电池组横空出世,它在算法上完全继承了“平面kmeans改.gh”的衣钵:

127024f5c7171afd58f3164806b68f94.png

b0657cbe7815f15fa8a9637ecd16d575.gif

2f3d818a223de4059e0f85a3fab0f161.gif

但是,麻烦也如期而至——会建立曲面的Voronoi 3D 和求交集的Point In Brep两个电池大大拖慢了运算速度。在平面情况下,这种方法的劣势还不明显,现在则已经成为必须要解决的问题了。

b268e06cc9a7936dbdb8b26f8cf93557.png

所以只能根据定义中的计算方式来分组了。

首先调整数据结构,计算点到聚类中心的距离,依照距离将聚类中心排序

a3537516d1babdb82a9f42d86cc0f20e.png

可见,现在有1295个点,23个聚类中心,每一条路径都代表着一个点,路径内的23个点依照距离从小到大排列。

重点来了。现在提取每一条路径中的第一个数据——那是距离某一个特定点最近的聚类中心。

现在有1295条路径,也就是每一个点都从23个聚类中心里面,找到了一个距离它最近的。

之后将它flatten,使用Create Set、Member Index和List Item素质三连,就得到了分好组的点。

d46c3a0532e35dd854d7f5611e5dedc1.png

这套连招究竟做了什么?是什么原理?

看一下flatten后的数据。有1295个点物件,他们是1295个点各自对应的最近的聚类中心。

目标是:将要处理的点分组,对应同一个聚类中心的点处在相同路径下。

97dd563f77972cb0c8832569f0057653.png

很明显,图中有很多的重复点,使用Create Set得到一个没有重复点的集合,该集合有23个点物件,正是那23个聚类中心。

c5592bedcd707786fed588dca9193c34.png

Member Index的功能是:对于某个列表中的数据,返回它在这个列表中的索引。输入23个独特的聚类中心,输出这23个聚类中心在原列表中的索引。在原列表中,每个聚类中心都重复了很多次,所以,索引的数目一共1295个。

68eec71773161eb5a0001f45ce6df9c3.png

既然有了索引,只需要用List Item将数据取出来就好了,只不过这次输入的列表要是待处理的点

7bccc11fe354c69e422f3481f9a07b2d.png

费了老鼻子劲,终于得到了分好组的点,接下来只要照搬原先写好的电池就行了。

最终结果如下:

3d2ee1b7a0004ceb97c1bf516f8e3403.png

6ecb6497232ef216b7c5cad17968b90a.gif

OK,完美!我们的“空间kmeans.gh”正式完成!

望着精准高效的电池图和高端酷炫的迭代过程,电脑前的你获得了前所未有的满足感。

7481f8029a1a982d2643787555425eeb.png

随着鼠标的一阵抖动,整个电池图索然无味。

处于贤者时间的你不禁想到,平面点由xy坐标确定,凡是有两个属性的数据(比如某人的身高和体重)就可以用唯一的平面点来代表;同理,有三个属性的数据(比如某人的三围)就可以用唯一的空间点来代表。

而你刚刚做出了可以给这些点自动分类的算法,虽然不知道有什么用——

但是电脑前的你还是获得了前所未有的满足感。

不过你很快就意识到,现实中的数据基本上都有三个及以上的属性,如果不将算法拓展到n维空间,也就无法处理这些数据,算法的能力将大大减弱——而且这个算法本来就不局限于三维空间坐标。

但是由于grasshopper自身的限制,它不支持多维空间中的点和向量。

即便如此,你还是在想:到底能不能拓展到n维空间中呢?

4.如何分类多维数据

幸运的是,grasshopper在关闭一扇门的同时,也打开了一扇窗——

矩阵

32a6f41ae541841214dbeb0b115207c9.png

虽然grasshopper不支持n维向量,但是可以用1行n列的矩阵来代替。通过把多维空间中的点转化成矩阵,你看到了希望。

很快,麻烦来了:

由于人不能理解多维空间,数据的可视化就成了一个大难题。不过可以通过在空间点上附加额外的属性来表示多维点——比如在空间点上画球,用球的半径代表第四维数据

54f3530f2bb0dda3875b8125b95462f0.png

空间点上画立方体,用立方体的长宽高代表第四、五、六维数据

e4272ea98dffb3dc4b4077b2a6a7efc8.png

此外,生成随机点的部分也不再多维点中适用,只能手动求出各维度数据区间,生成随机数再合成一个多维点。下图是 生成随机矩阵和将多维点转化为矩阵的部分。

7428e95dfe5abb2427103b95bb8c5d40.png

由于矩阵不是几何物件,不能用Distance计算距离,若要求矩阵所代表的多维点的欧氏距离,则需要手动计算。而且矩阵本身又自带一层数据结构,处理起来相当麻烦。下图是计算距离的部分。

f92ae433f8dc8721be590d62403caae5.png

其他部分都和三维kmeans相似。

不知过了多长时间,重启了多少次grasshopper,数据结构出错多少次,终于,电池运行成功了。

在最终结果如下:

fe54cf29e4ee88e4bc48a56934edd2d1.png

20a4ae19252a3586121995cc660ea4e2.png

稍加改动,就可以直接从Excel中导入数据并计算了。

caf72d52b69a7c29702430bbf337f83c.png

OK,完美!我们的“多维kmeans.gh”正式完成!

5.后记

望着并不复杂的电池图和前途无量的算法,电脑前的你获得了前所未有的满足感。

7481f8029a1a982d2643787555425eeb.png

随着鼠标的一阵抖动,整个电池图索然无味。

处于贤者时间的你不禁想到,整个过程可以写成文章发到知乎上,或许能帮到别人。

在码字之前,你觉得,也许应该问问之前是否有人做过类似的事情,通过对比学习,一定大有收获。

a545468b2631d0db1428176239f9662c.png

受群友的指引,你下载了owl和最新版的Lunchbox

https://www.food4rhino.com/app/owl

https://provingground.io/tools/lunchbox/download-lunchbox-for-grasshopper/

打开插件的一瞬间,空气凝固了

c04828c2e6a73255a312478b53c01a1c.png

30c6e0e8b668a51fd0feb0647dd33414.png

你倚在阳台上,晚风试图把你从无奈中解救出来。

效果并不怎样。用grasshopper久了,就连月亮都看起来有两个输入端。

“如果我的脑袋是一个电池的话,输出端一定是水。”你抱着这样的想法坐回电脑前。

你没有放弃写知乎,只不过,在羞耻和自嘲的怂恿下,文章用的是第二人称的视角。

文件下载:https://pan.baidu.com/s/1PYaVuVw7dIViXYVeLk0kTQ

提取码:75u1

需要lunchbox(读取Excel)

需要meshedit(建立三维点分组预览)

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

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

相关文章

ip地址异常判定python_python检测异常ip,并查询ip详细信息

#!/usr/local/bin/python3# coding:utf-8import string, subprocess, send_mailfrom time import strftime, gmtime, sleep, reimport urllib.request, redef filter_tags(htmlstr):re_cdata re.compile(//]*//\]\]>, re.I) # 匹配CDATAre_script re.compile(]*>[^, re…

保持充沛的精力

转载的:原文地址:http://www.cnblogs.com/siylz/p/4589134.html不管我们做大事还是小事,最需要的是精力。一个人有了充沛的精力,干什么大事都不成问题。可是有不少人往往把他们那宝贵的精力胡乱挥橄在那些走无意义、自讨苦吃的事情…

php while mysql_我怎么能避免在PHP的While循环中使用MySQL查询

我有一个输出类列表的while循环.在类数据库中,教师名称由用户数据库中的教师ID确定.这是我的数据库结构.Classes Database-----------------------------ID CLASS TEACHER1 product design 3User Database-----------------------------ID NAME3 John Doe因此,当列出我的类时,我…

Jq_网站顶部定时折叠广告

<!DOCTYPE html><html xmlns"http://www.w3.org/1999/xhtml"><head><title>网页顶部定时收起广告jQuery特效 - HoverTree</title><base target"_blank" /><style>a {color:blue;text-decoration:none;}</sty…

fullgc频繁的原因_系统运行缓慢,CPU 100%,Full GC次数过多,这一招帮你全搞定

处理过线上问题的同学基本上都会遇到系统突然运行缓慢&#xff0c;CPU 100%&#xff0c;以及Full GC次数过多的问题。当然&#xff0c;这些问题的最终导致的直观现象就是系统运行缓慢&#xff0c;并且有大量的报警。本文主要针对系统运行缓慢这一问题&#xff0c;提供该问题的排…

python 局域网扫描_Python 简化版扫描局域网存活主机

[code]Python 简化版局域网扫描获取存活主机IP by 郑瑞国1、ping指定IP判断主机是否存活2、ping所有IP获取所有存活主机#注: 若在Linux系统下 ping -n 改为 ping -c若在windows系统下 ping -n 不变import socketimport osimport threadingimport timeIPList []def ping_ip(ip)…

WEKA “Detailed Accuracy By Class”和“Confusion Matrix”含义

原文 Summary &#xff08;总结&#xff09;Correctly Classified Instances&#xff08;正确分类的实例&#xff09; 45 90 %Incorrectly Classified Instances &#xff08;错误分类的实例&#xff09; 5 10 %Kappa …

es删除数据_面试官是怎么来考察你对ES搜索引擎的理解?

来源:http://1t.click/ZdY一. 面试官心理分析问这个&#xff0c;其实面试官就是要看看你了解不了解 es 的一些基本原理&#xff0c;因为用 es 无非就是写入数据&#xff0c;搜索数据。你要是不明白你发起一个写入和搜索请求的时候&#xff0c;es 在干什么&#xff0c;那你真的是…

thinkphp mysql函数_thinkphp对数据库操作有哪些内置函数

getModelName() 获取当前Model的名称getTableName() 获取当前Model的数据表名称switchModel(type,varsarray()) 动态切换模型table() 设置当前操作的数据表field() 设置要查询的数据字段where() 设置查询或者操作条件data(data) 设置数据对象order(order) 设置排序limit(limit)…

一个分布式服务器集群架构方案

0x01.大型网站演化 简单说&#xff0c;分布式是以缩短单个任务的执行时间来提升效率的&#xff0c;而集群则是通过提高单位时间内执行的任务数来提升效率。 集群主要分为&#xff1a;高可用集群(High Availability Cluster)&#xff0c;负载均衡集群(Load Balance Cluster&…

python数据预处理_Python数据预处理——缺失值、重复值

一、缺失值处理 isnull( ) 、fillna( ) 、dropna( )&#xff08;1&#xff09;查看缺失查看数据集缺失&#xff0c;返回每列的缺失个数 df.isnull().sum() 查看某字段有缺失的行 df[df.a.isnull()] 查看某字段每行的缺失情况&#xff1a;返回T/F&#xff1a;df.score.isnull() …

vb如何测试连接mysql_VB怎么连接访问Access数据库?

VB是我们常常会见到的一款可视化程序设计语言&#xff0c;它的功能十分强大&#xff0c;因此有很多人会使用它&#xff0c;但是有时候我们需要用到VB来连接Access数据库&#xff0c;但是却无从下手&#xff0c;那么VB怎么连接访问Access数据库呢&#xff1f;不懂的朋友请看以下…

pthread 简要使用指南

http://www.2cto.com/kf/201208/151995.html http://www.2cto.com/kf/201208/151997.html转载于:https://www.cnblogs.com/alanhu/p/4677399.html

textarea如何在文字后面_FLASH如何制作风吹文字的效果

使用动作补间动画可以制作各种各样的动态效果&#xff0c;树叶飘落、蝴蝶飞舞等。这里再使用引导层动画结合动作补间动画制作风吹文字飞起的效果。主要知识点&#xff1a;引导层动画、动作补间动画FLASH如何制作树叶飘落​jingyan.baidu.comFlash如何制作飞舞的蝴蝶​jingyan.b…

ef mysql 外键 一对一_EFCore-一对一配置外键小记2

前后两次遇到这样的错误&#xff1a;The property xx on entity type xxxx has a temporary value. Either set a permanent value explicitly or ensure that the database is configured to generate values for this property.多数情况下是表配置关系会出现这样的问题。我实…

矩阵快速幂 HDU3483

1 #include <iostream>2 #include <cstring>3 4 using namespace std;5 6 //矩阵大小上限7 const int SIZ100;8 int MOD;9 10 //矩阵大小为n*m&#xff0c;初始化全部为011 struct mat12 {13 int n,m;14 long long ar[SIZ][SIZ];15 mat()16 {17 …

哲学家就餐问题python_Python实现哲学家就餐问题实例代码

哲学家就餐问题&#xff1a; 哲学家就餐问题是典型的同步问题&#xff0c;该问题描述的是五个哲学家共用一张圆桌&#xff0c;分别坐在五张椅子上&#xff0c;在圆桌上有五个盘子和五个叉子&#xff08;如下图&#xff09;&#xff0c;他们的生活方式是交替的进行思考和进餐&am…

mongodb 库数量限制_MongoDB in 数量限制

1、查询语句本身其实是一个document&#xff0c; 最大为16MB(3.4&#xff0c;4.0 的限制&#xff0c;官方文档)2、查询语句本身&#xff0c;也就是{ : { $in : [] }}&#xff0c; 大小为 22字节3、每增加一个字段名&#xff0c;增加一位字节4、in里面每增加一个参数&#xff0…

Webx框架:Pipeline基本介绍

Pipeline。它是管道的含义。一个管道阀门可以安装非常多。有许多可能的分支。它是用来控制页处理。它需要在被定义pipeline.xml文件。该文件是为每个阀的标签。该文件可以放一些简单的控制语句。在项目。这条管线有以下配置足够好。 <services:pipeline xmlns"http://w…

fpga摄像头模块_FPGA开源项目:双目测距(一)之双目图像采集显示以及图片保存...

1.简述这个项目是大三下学期暑假(也就是2019年8份)完成的&#xff0c;当时的视频效果已发布在bilibili上&#xff0c;这是我们的省级的科研立项&#xff0c;其实就我一个人负责完成。发布bilibili后很多人比较感兴趣&#xff0c;打算年初回学校完成毕设期间开源的&#xff0c;一…