k均值聚类算法优缺点_Grasshopper实现K均值聚类算法
本文很長很長,有很多很多圖,包含以下部分:
1.算法簡介
2.如何分類平面點
3.如何分類空間點
4.如何分類多維數(shù)據(jù)
5.后記
提醒:以下內(nèi)容包括:智障操作,無中生友,重復造輪子 等
1.算法簡介
k均值聚類算法(k-means),這東西是什么意思?
k均值聚類算法(k-means clustering algorithm)是一種迭代求解的聚類分析算法,其步驟是隨機選取K個對象作為初始的聚類中心,然后計算每個對象與各個種子聚類中心之間的距離,把每個對象分配給距離它最近的聚類中心。聚類中心以及分配給它們的對象就代表一個聚類。每分配一個樣本,聚類的聚類中心會根據(jù)聚類中現(xiàn)有的對象被重新計算。這個過程將不斷重復直到滿足某個終止條件。終止條件可以是沒有(或最小數(shù)目)對象被重新分配給不同的聚類,沒有(或最小數(shù)目)聚類中心再發(fā)生變化,誤差平方和局部最小。——百度百科我用人話解釋一下:
假如你有一些平面上的點,大概如下圖。你想把它們分組,離得近的點分到同一組去,離得遠的分到不同的組。
你估摸了一下,大概知道要分9組,別的限制條件一概不知,這時候就非常適合用這種簡單粗暴的方法。
方法是這樣的:
1.在這些點的范圍內(nèi),隨機取9個點,取名為“聚類中心”。注意,是隨機的,想怎么取就怎么取。
2.對每一個點,計算它到9個聚類中心的位置,找到最近的聚類中心,并將其劃分到那一組中
很明顯,分組的情況相當糟糕,畢竟聚類中心是隨機的嘛。
3.對每一個組內(nèi)的點,求出平均點,并將其作為新的聚類中心,在下圖中,綠色點是新的聚類中心。
4.重復2、3的步驟,直到分組情況不再變化
這就是k均值聚類算法的平面應(yīng)用方式,接下來介紹在grasshopper里如何實現(xiàn)它。
2.如何分類平面點
首先畫一些點,拾取進grasshopper中;求出這些點的bounding box,以此為邊界,使用populate 3d/2d生成9個點作為聚類中心。
以聚類中心為起始點,生成泰森多邊形,泰森多邊形內(nèi)的點就是被分到該組的點。使用Point In Curve搭配 Cull Pattern實現(xiàn)這一步
(當然,可以計算距離然后排序,這兩種方法是等效的。只不過在平面的情況下,這里選擇了更直觀的方法)
使用average,求出各組平均點。
使用插件anemone,根據(jù)上文所述,在Populate 3D后設(shè)立循環(huán)起點,在average后設(shè)立循環(huán)終點,并讓控制循環(huán)的兩個電池對應(yīng),設(shè)立最大循環(huán)次數(shù)。
OK,完美!我們的“平面kmeans.gh”正式完成!
望著簡單優(yōu)雅的電池圖和靈巧變動的迭代動畫,電腦前的你獲得了前所未有的滿足感。
然而,你很快發(fā)現(xiàn)這個電池并不完美。
首先它沒有顯示結(jié)果。雖然分組完畢,但是并不直觀。
你拖出了Convex Hull,解決了這一問題。
顯示分組結(jié)果之后你馬上發(fā)現(xiàn),即便是迭代了十余次,分組結(jié)果已經(jīng)穩(wěn)定,這個結(jié)果還是不能讓你滿意。
首先,本來是要分9組的,現(xiàn)在它只有8組,;而且右邊有兩組緊挨著的點,憑什么他們不能分到一組去?
原因在于初始聚類中心上。因為它是隨機的,所以可能有一個聚類中心和所有點都距離很遠,沒有點在它那一組,導致它成了光桿司令。
因為第一次分組它就沒有組員,所以以后也不再會有,最終導致結(jié)果少了一組。
同理,兩個聚類中心之間存在一大批點,最終會導致兩個中心勢均力敵,平分這些點。
要解決這些問題,只能調(diào)整隨機的種子,直到結(jié)果令人滿意。
解決了分組問題,你隱隱約約覺得還有哪里不對勁,沒錯,就是循環(huán)的部分。
現(xiàn)在,運算結(jié)果會不停迭代直至最大次數(shù),這就面臨著“最大迭代次數(shù)設(shè)置為多少是合適的”的問題。太大,浪費資源;太小,分組情況不穩(wěn)定。一般來說,人們習慣性地設(shè)為100,當然這只是權(quán)宜之計,略有強迫癥的你決定做出可以終止迭代的部分。
根據(jù)算法定義,當分組情況不變時,停止迭代。
Loop End電池的exit端等于TRUE時,停止迭代。
也就是說,比較一下本次運算和上次運算時的分組情況,如果相同,則輸出true到exit端。
“分組情況”是什么?
是每一組內(nèi)點的數(shù)量(列表長度)。把這些數(shù)據(jù)轉(zhuǎn)換成一個數(shù)據(jù),而且還能避免誤判的一個最簡便的方式,就是Construct Path。
這樣,“分組情況”就能被一行唯一的文字代表,只要用match text把它和上一次迭代時的文字比較就行了。
但是可惜,anemone沒有查看迭代過程中的上次數(shù)據(jù)的功能,(如果有,請教教我)只能自己做了。如下圖:
這一部分是什么意思呢?
Data Recorder記錄所有通過的數(shù)據(jù)。
List Item列出本次和上次迭代的文字。
Replace Nulls是為了用隨便什么別的文字替換掉null。因為如果Data Recorder記錄的數(shù)據(jù)不足兩個,list item的-1端會和i端一致,使得循環(huán)結(jié)束,所以必須將wrap設(shè)為false;這樣就導致-1端會變成null,所以必須將它替換掉。
最后就是match text,當兩輸入端一致時輸出true,搞定。
最終成果如下
OK,完美!我們的“平面kmeans改.gh”正式完成!
望著簡單粗暴的電池圖和完全自動的迭代過程,電腦前的你獲得了前所未有的滿足感。
隨著鼠標的一陣抖動,整個電池圖索然無味。
處于賢者時間的你不禁想到,這個方法可以拓展到3維空間里嗎?
3.如何分類空間點
靈巧的雙手穿針引線,類比的思維高速運轉(zhuǎn)——頃刻,能夠處理空間點的電池組橫空出世,它在算法上完全繼承了“平面kmeans改.gh”的衣缽:
但是,麻煩也如期而至——會建立曲面的Voronoi 3D 和求交集的Point In Brep兩個電池大大拖慢了運算速度。在平面情況下,這種方法的劣勢還不明顯,現(xiàn)在則已經(jīng)成為必須要解決的問題了。
所以只能根據(jù)定義中的計算方式來分組了。
首先調(diào)整數(shù)據(jù)結(jié)構(gòu),計算點到聚類中心的距離,依照距離將聚類中心排序
可見,現(xiàn)在有1295個點,23個聚類中心,每一條路徑都代表著一個點,路徑內(nèi)的23個點依照距離從小到大排列。
重點來了。現(xiàn)在提取每一條路徑中的第一個數(shù)據(jù)——那是距離某一個特定點最近的聚類中心。
現(xiàn)在有1295條路徑,也就是每一個點都從23個聚類中心里面,找到了一個距離它最近的。
之后將它flatten,使用Create Set、Member Index和List Item素質(zhì)三連,就得到了分好組的點。
這套連招究竟做了什么?是什么原理?
看一下flatten后的數(shù)據(jù)。有1295個點物件,他們是1295個點各自對應(yīng)的最近的聚類中心。
目標是:將要處理的點分組,對應(yīng)同一個聚類中心的點處在相同路徑下。
很明顯,圖中有很多的重復點,使用Create Set得到一個沒有重復點的集合,該集合有23個點物件,正是那23個聚類中心。
Member Index的功能是:對于某個列表中的數(shù)據(jù),返回它在這個列表中的索引。輸入23個獨特的聚類中心,輸出這23個聚類中心在原列表中的索引。在原列表中,每個聚類中心都重復了很多次,所以,索引的數(shù)目一共1295個。
既然有了索引,只需要用List Item將數(shù)據(jù)取出來就好了,只不過這次輸入的列表要是待處理的點
費了老鼻子勁,終于得到了分好組的點,接下來只要照搬原先寫好的電池就行了。
最終結(jié)果如下:
OK,完美!我們的“空間kmeans.gh”正式完成!
望著精準高效的電池圖和高端酷炫的迭代過程,電腦前的你獲得了前所未有的滿足感。
隨著鼠標的一陣抖動,整個電池圖索然無味。
處于賢者時間的你不禁想到,平面點由xy坐標確定,凡是有兩個屬性的數(shù)據(jù)(比如某人的身高和體重)就可以用唯一的平面點來代表;同理,有三個屬性的數(shù)據(jù)(比如某人的三圍)就可以用唯一的空間點來代表。
而你剛剛做出了可以給這些點自動分類的算法,雖然不知道有什么用——
但是電腦前的你還是獲得了前所未有的滿足感。
不過你很快就意識到,現(xiàn)實中的數(shù)據(jù)基本上都有三個及以上的屬性,如果不將算法拓展到n維空間,也就無法處理這些數(shù)據(jù),算法的能力將大大減弱——而且這個算法本來就不局限于三維空間坐標。
但是由于grasshopper自身的限制,它不支持多維空間中的點和向量。
即便如此,你還是在想:到底能不能拓展到n維空間中呢?
4.如何分類多維數(shù)據(jù)
幸運的是,grasshopper在關(guān)閉一扇門的同時,也打開了一扇窗——
矩陣
雖然grasshopper不支持n維向量,但是可以用1行n列的矩陣來代替。通過把多維空間中的點轉(zhuǎn)化成矩陣,你看到了希望。
很快,麻煩來了:
由于人不能理解多維空間,數(shù)據(jù)的可視化就成了一個大難題。不過可以通過在空間點上附加額外的屬性來表示多維點——比如在空間點上畫球,用球的半徑代表第四維數(shù)據(jù)
空間點上畫立方體,用立方體的長寬高代表第四、五、六維數(shù)據(jù)
此外,生成隨機點的部分也不再多維點中適用,只能手動求出各維度數(shù)據(jù)區(qū)間,生成隨機數(shù)再合成一個多維點。下圖是 生成隨機矩陣和將多維點轉(zhuǎn)化為矩陣的部分。
由于矩陣不是幾何物件,不能用Distance計算距離,若要求矩陣所代表的多維點的歐氏距離,則需要手動計算。而且矩陣本身又自帶一層數(shù)據(jù)結(jié)構(gòu),處理起來相當麻煩。下圖是計算距離的部分。
其他部分都和三維kmeans相似。
不知過了多長時間,重啟了多少次grasshopper,數(shù)據(jù)結(jié)構(gòu)出錯多少次,終于,電池運行成功了。
在最終結(jié)果如下:
稍加改動,就可以直接從Excel中導入數(shù)據(jù)并計算了。
OK,完美!我們的“多維kmeans.gh”正式完成!
5.后記
望著并不復雜的電池圖和前途無量的算法,電腦前的你獲得了前所未有的滿足感。
隨著鼠標的一陣抖動,整個電池圖索然無味。
處于賢者時間的你不禁想到,整個過程可以寫成文章發(fā)到知乎上,或許能幫到別人。
在碼字之前,你覺得,也許應(yīng)該問問之前是否有人做過類似的事情,通過對比學習,一定大有收獲。
受群友的指引,你下載了owl和最新版的Lunchbox
https://www.food4rhino.com/app/owl
https://provingground.io/tools/lunchbox/download-lunchbox-for-grasshopper/
打開插件的一瞬間,空氣凝固了
你倚在陽臺上,晚風試圖把你從無奈中解救出來。
效果并不怎樣。用grasshopper久了,就連月亮都看起來有兩個輸入端。
“如果我的腦袋是一個電池的話,輸出端一定是水。”你抱著這樣的想法坐回電腦前。
你沒有放棄寫知乎,只不過,在羞恥和自嘲的慫恿下,文章用的是第二人稱的視角。
文件下載:https://pan.baidu.com/s/1PYaVuVw7dIViXYVeLk0kTQ
提取碼:75u1
需要lunchbox(讀取Excel)
需要meshedit(建立三維點分組預覽)
總結(jié)
以上是生活随笔為你收集整理的k均值聚类算法优缺点_Grasshopper实现K均值聚类算法的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 光大时尚cosmo信用卡额度一般是多少
- 下一篇: java文件上传maven_ssm+ma