因為是老師的作業,所以最近就研究了一下k-means演算法,也就做一下關於這個演算法的筆記。
在諸多的聚類方法中,k-means聚類方法是屬於「基於原型的聚類」(也稱為原型聚類)的方法,此類方法均是假設聚類結構能通過一組原型刻畫,在現實聚類中極為常用。通常情況下,該類演算法會先對原型進行初始化,然後再對原型進行迭代更新求解。採用不同的原型表示、不同的求解方式,也將會產生不同的演算法。k-means演算法作為一種經典的「原型聚類」演算法,其原型選擇的是「k個聚類中心」,迭代求解的方式是以相鄰兩次求解的「質心」(同一類所有的點的x,y,z座標的平均值)變化程度而進行的,這也可能就是k-means聚類名字的由來:k個聚類中心+質心(座標平均值)。
過程其實相對簡單:
1、初始化原型,也就是指定k值和k個聚類中心。這其中聚類中心的指定可以人為的輸入、也可以隨機選擇或者其他方式都可以,不過盡量保證聚類中心之間的距離不要選的太近。原始資料圖:2、聚類。遍歷所有資料點,計算每個資料點到這k個聚類中心的距離(我這裡選擇的是歐式距離,也可以選擇馬氏距離或者其他距離),將每個資料點分配給距離該點最近的聚類中心所屬的類別,直到最後乙個資料點。
3、更新聚類中心。也就是計算每一類的質心,並將本次計算出的聚類中心與上一次的聚類中心進行比較,如果所有的聚類中心都沒有變化,則停止;如果有所變化,則將本次的聚類中心作為新的聚類中心,重複上述的2、3過程,直到所有的聚類中心都沒有變化時停止該過程。
**如下:
main.cpp:
#include
"kmeans.h"
#include
#include
#include
using
namespace kmeans;
intmain()
std::stof(vec[1]), std::stof(vec[2]));
std::stringstream words
(line)
; words >> x;
//可以通過這種方式來提取出相應的字串數值,不用使用分割函式
words >> y;
words >> z;
/*x = static_cast(atof(_x.c_str()));
y = static_cast(-atof(_z.c_str()));
z = static_cast(atof(_y.c_str()));*/
pointcloud.
emplace_back
(x,y,z);}
input.
close()
; kmeans<
float
>
k_mean(2
,pointcloud)
; std::vector<:vector>> cluster = k_mean.
getclusterpoint()
; std::ofstream output;
for(
int i =
0; i < cluster.
size()
; i++
) output.
close()
;}std::cout <<
"執行成功!"
<< std::endl;
system
("pause");
return0;
}
point3.h:
#ifndef point3
#define point3
#include
namespace kmeans
~point3()
point3 operator-(
const point3& other)
point3 operator+(
const point3& other)
t getsquareddistanceto
(const point3& other)
private:}
;}#endif
// !point3
pointdatasource.h:
#ifndef pointdatasource
#define pointdatasource
#include
"point3.h"
namespace kmeans
pointdatasource
(const std::vector>
& points)
:m_ptr
(&points[0]
),m_count
(points.
size()
)pointdatasource()
:m_ptr
(nullptr),
m_count(0
) pointdatasource&
operator=(
const pointdatasource& other)
=default;~
pointdatasource()
size_t size()
const
const point3
&operator
(size_t index)
const
const point3
*begin()
const
const point3
*end()
const
private
:const point3
* m_ptr;
//點的指標
size_t m_count;};
}#endif
// !pointdatasource
kmeans.h:
#ifndef kmeans
#define kmeans
#include
#include
"point3.h"
#include
"pointdatasource.h"
namespace kmeans
return point3
(x / clusterpoints.
size()
, y / clusterpoints.
size()
, z / clusterpoints.
size()
);}public
:kmeans()
=default
;kmeans
(int k,
const std::vector>
& pointcloud):k
(k),
pointcloud
(pointcloud)
~kmeans()
std::vector<:vector>>
getclusterpoint()
std::vector> clustercenter,oldclustercenter;
clustercenter.
resize
(k);
for(
int i =
0; i < k; i++
)//迭代迴圈進行聚類運算
while
(true)}
cluster[maxdistindex]
.push_back
(i);
}//更新各個聚類簇的中心點
oldclustercenter = clustercenter;
int unupdateflag =0;
for(
int i =
0; i < k; i++)}
//判斷聚類中心是否均未更新
if(unupdateflag == k)
//清除所有聚類簇中的資料
for(
int i =
0; i < k; i++)}
return cluster;}}
;}#endif
處理效果:
從處理效果圖可以看出,k-means演算法可以很好的將在距離上有著明顯差異的地物進行聚類識別,但是該演算法也會對雜訊進行聚類。所以如果資料量很大,那麼在使用該方法時可以先進行簡單的去噪處理,這樣可以降低k-means演算法進行聚類時的計算量。
K Means聚類演算法
k means聚類演算法 intergret kmeans演算法的基本思想是初始隨機給定k個簇中心,按照最鄰近原則把待分類樣本點分到各個簇。然後按平均法重新計算各個簇的質心,從而確定新的簇心。一直迭代,直到簇心的移動距離小於某個給定的值。k means聚類演算法主要分為三個步驟 1 第一步是為待聚類...
聚類演算法 K means
演算法接受引數 k 然後將事先輸入的n個資料物件劃分為 k個聚類以便使得所獲得的聚類滿足 同一聚類中的物件相似度較高 而不同聚類中的物件相似度較小。聚類相似度是利用各聚類中物件的均值所獲得乙個 中心物件 引力中心 來進行計算的。k means演算法是最為經典的基於劃分的聚類方法,是十大經典資料探勘演...
k means聚類演算法
說到聚類,得跟分類區別開來,分類是按人為給定的標準將樣本歸到某個類別中去,在機器學習中多是監督學習,也就是訓練樣本要給標籤 正確的類別資訊 而聚類是在某種規則下自動將樣本歸類,在機器學習中是無監督學習,不需要提前給樣本打標籤。k means聚類演算法,就是在某種度量方式下,將樣本自動劃分到k個類別中...