① 使用K-Means 演算法進行聚類分析程序
你這是四維數據,我這是一維數據kmeans,你試試吧
#include<iostream>
#include<math.h>
#include<stdlib.h>
#include<stdio.h>
using namespace std;
int N; //數據個數
int K; //集合個數
int *CenterIndex; //質心索引集合,即屬於第幾個參考點
double *Center; //質心集合
double *CenterCopy;
double *DataSet;
double **Cluster;
int *Top;
/*演算法描述:
C-Fuzzy均值聚類演算法採用的是給定類的個數K,將N個元素(對象)分配到K個類中去使得類內對象之間的相似性最大,而類之間的相似性最小 */
//函數聲明部分
void InitData();
void InitCenter();
void CreateRandomArray(int n,int k,int *centerIndex);
void CopyCenter();
void UpdateCluster();
void UpdateCenter();
int GetIndex(double value,double *centerIndex);
void AddtoCluster(int index,double value);
void print();
bool IsEqual(double *center,double *center);
int main()
{
int Flag=1;
InitData();
while(Flag)//無限次循環
{
UpdateCluster();
UpdateCenter();
if(IsEqual(Center,CenterCopy))
{
Flag=0;
}
else
{
CopyCenter();
}
}
print();
getchar();
system("pause");
}
void InitData()
{
int i=0;
int a;
cout<<"請輸入數據元素的個數: ";
cin>>N;
cout<<"請輸入分類數: ";
cin>>K;
if(K>N)
{
return;
}
CenterIndex =new int [sizeof(int)];
Center =new double [sizeof(double)*K];
CenterCopy =new double [sizeof(double)*K];
DataSet =new double [sizeof(double)*N];
Cluster =new double* [sizeof(double*)*K];
Top =new int [sizeof(int)*K];
//初始化K個類的集合
for(i=0;i<K;i++)
{
Cluster[i]=new double [sizeof(double)*N];
Top[i]=0;
}
cout<<"請輸入數據"<<endl;
for(i=0;i<N;i++)
{
cin>>a;
DataSet[i]=a;
}
//初始化質心集合
InitCenter();
UpdateCluster();
}
void InitCenter()//初始化中心點(參照點)
{
int i=0;
//產生隨即的K個<N的不同的序列
CreateRandomArray(N,K,CenterIndex);
for(i=0;i<K;i++)
{
Center[i]=DataSet[CenterIndex[i]];
}
CopyCenter();
}
void CreateRandomArray(int n,int k,int *centerIndex)//產生可以隨輸出控制的 k與n (可舍棄)
{
int i=0,j=0;
for(i=0;i<K;i++)
{
int a=rand()%n;
for(j=0;j<i;j++)
{
if(centerIndex[j]==a)
break;
}
if(j>=i)
{
centerIndex[i]=a;
}
else
{
i--;
}
}
}
void CopyCenter()//將舊的中心點保留以作比較
{
int i=0;
for(i=0;i<K;i++)
{
CenterCopy[i]=Center[i];
}
}
void UpdateCluster()//
{
int i=0;
int tindex;
for(;i<K;i++)
{
Top[i]=0;
}
for(i=0;i<N;i++)
{
tindex=GetIndex(DataSet[i],Center);
AddtoCluster(tindex,DataSet[i]);
}
}
int GetIndex(double value,double *center)//判斷屬於哪個參照點
{
int i=0;
int index=i;
double min=fabs(value-center[i]);
for(i=0;i<K;i++)
{
if(fabs(value-center[i])<min)
{
index=i;
min=fabs(value-center[i]);
}
}
return index;
}
void AddtoCluster(int index,double value)//統計每組個數(用於均值法求新的參照點)
{
Cluster[index][Top[index]]=value;
Top[index]++;
}
void UpdateCenter()//更新參照點
{
int i=0,j=0;
double sum;
for(i=0;i<K;i++)
{
sum=0.0;
for(j=0;j<Top[i];j++)
{
sum+=Cluster[i][j];
}
if(Top[i]>0)
{
Center[i]=sum/Top[i];
}
}
}
bool IsEqual(double *center,double*center)//
{
int i;
for(i=0;i<K;i++)
{
if(fabs(center[i]!=center[i]))
return 0;
}
return 1;
}
void print()//
{
int i,j;
cout<<"===================================="<<endl;
for(i=0;i<K;i++)
{
cout<<"第"<<i<<"組:質心為:"<<Center[i]<<endl;
cout<<"數據元素為:\n";
for(j=0;j<Top[i];j++)
{
cout<<Cluster[i][j]<<'\t';
}
cout<<endl;
}
}
② 模糊C均值聚類演算法(FCM)
【嵌牛導讀】FCM演算法是一種基於劃分的聚類演算法,它的思想就是使得被劃分到同一簇的對象之間相似度最大,而不同簇之間的相似度最小。模糊C均值演算法是普通C均值演算法的改進,普通C均值演算法對於數據的劃分是硬性的,而FCM則是一種柔性的模糊劃分。
【嵌牛提問】FCM有什麼用?
【嵌牛鼻子】模糊C均值聚類演算法
【嵌牛正文】
聚類分析是多元統計分析的一種,也是無監督模式識別的一個重要分支,在模式分類、圖像處理和模糊規則處理等眾多領域中獲得最廣泛的應用。它把一個沒有類別標記的樣本按照某種准則劃分為若乾子集,使相似的樣本盡可能歸於一類,而把不相似的樣本劃分到不同的類中。硬聚類把每個待識別的對象嚴格的劃分某類中,具有非此即彼的性質,而模糊聚類建立了樣本對類別的不確定描述,更能客觀的反應客觀世界,從而成為聚類分析的主流。
模糊聚類演算法是一種基於函數最優方法的聚類演算法,使用微積分計算技術求最優代價函數,在基於概率演算法的聚類方法中將使用概率密度函數,為此要假定合適的模型,模糊聚類演算法的向量可以同時屬於多個聚類,從而擺脫上述問題。 模糊聚類分析演算法大致可分為三類:
1)分類數不定,根據不同要求對事物進行動態聚類,此類方法是基於模糊等價矩陣聚類的,稱為模糊等價矩陣動態聚類分析法。
2)分類數給定,尋找出對事物的最佳分析方案,此類方法是基於目標函數聚類的,稱為模糊C 均值聚類。
3)在攝動有意義的情況下,根據模糊相似矩陣聚類,此類方法稱為基於攝動的模糊聚類分析法。
我所學習的是模糊C 均值聚類演算法,要學習模糊C 均值聚類演算法要先了解慮屬度的含義,隸屬度函數是表示一個對象x 隸屬於集合A 的程度的函數,通常記做μA (x),其自變數范圍是所有可能屬於集合A 的對象(即集合A 所在空間中的所有點),取值范圍是[0,1],即0<=μA (x)<=1。μA (x)=1表示x 完全隸屬於集合A ,相當於傳統集合概念上的x ∈A 。一個定義在空間X={x}上的隸屬度函數就定義了一個模糊集合A ,或者叫定義在論域X={x}上的模糊子集A 。對於有限個對象x 1,x 2,……,x n 模糊集合A 可以表示為:A ={(μA (x i ), x i ) |x i ∈X } (6.1)
有了模糊集合的概念,一個元素隸屬於模糊集合就不是硬性的了,在聚類的問題中,可以把聚類生成的簇看成模糊集合,因此,每個樣本點隸屬於簇的隸屬度就是[0,1]區間裡面的值。
FCM 演算法需要兩個參數一個是聚類數目C ,另一個是參數m 。一般來講C 要遠遠小於聚類樣本的總個數,同時要保證C>1。對於m ,它是一個控制演算法的柔性的參數,如果m 過大,則聚類效果會很次,而如果m 過小則演算法會接近HCM 聚類演算法。演算法的輸出是C 個聚類中心點向量和C*N的一個模糊劃分矩陣,這個矩陣表示的是每個樣本點屬於每個類的隸屬度。根據這個劃分矩陣按照模糊集合中的最大隸屬原則就能夠確定每個樣本點歸為哪個類。聚類中心表示的是每個類的平均特徵,可以認為是這個類的代表點。從演算法的推導過程中我們不難看出,演算法對於滿足正態分布的數據聚類效果會很好。
通過實驗和演算法的研究學習,不難發現FCM演算法的優缺點:
首先,模糊c 均值泛函Jm 仍是傳統的硬c 均值泛函J1 的自然推廣。J1 是一個應用很廣泛的聚類准則,對其在理論上的研究已經相當的完善,這就為Jm 的研究提供了良好的條件。
其次,從數學上看,Jm與Rs的希爾伯特空間結構(正交投影和均方逼近理論) 有密切的關聯,因此Jm 比其他泛函有更深厚的數學基礎。
最後,FCM 聚類演算法不僅在許多鄰域獲得了非常成功的應用,而且以該演算法為基礎,又提出基於其他原型的模糊聚類演算法,形成了一大批FCM類型的演算法,比如模糊c線( FCL) ,模糊c面(FCP) ,模糊c殼(FCS) 等聚類演算法,分別實現了對呈線狀、超平面狀和「薄殼」狀結構模式子集(或聚類) 的檢測。
模糊c均值演算法因設計簡單,解決問題范圍廣,易於應用計算機實現等特點受到了越來越多人的關注,並應用於各個領域。但是,自身仍存在的諸多問題,例如強烈依賴初始化數據的好壞和容易陷入局部鞍點等,仍然需要進一步的研究。
③ 急求:k-Means聚類演算法實現
K-MEANS演算法:
k-means 演算法接受輸入量 k ;然後將n個數據對象劃分為 k個聚類以便使得所獲得的聚類滿足:同一聚類中的對象相似度較高;而不同聚類中的對象相似度較小。聚類相似度是利用各聚類中對象的均值所獲得一個「中心對象」(引力中心)來進行計算的。
k-means 演算法的工作過程說明如下:首先從n個數據對象任意選擇 k 個對象作為初始聚類中心;而對於所剩下其它對象,則根據它們與這些聚類中心的相似度(距離),分別將它們分配給與其最相似的(聚類中心所代表的)聚類;然後再計算每個所獲新聚類的聚類中心(該聚類中所有對象的均值);不斷重復這一過程直到標准測度函數開始收斂為止。一般都採用均方差作為標准測度函數. k個聚類具有以下特點:各聚類本身盡可能的緊湊,而各聚類之間盡可能的分開。
具體如下:
輸入:k, data[n];
(1) 選擇k個初始中心點,例如c[0]=data[0],…c[k-1]=data[k-1];
(2) 對於data[0]….data[n], 分別與c[0]…c[n-1]比較,假定與c[i]差值最少,就標記為i;
(3) 對於所有標記為i點,重新計算c[i]={ 所有標記為i的data[j]之和}/標記為i的個數;
(4) 重復(2)(3),直到所有c[i]值的變化小於給定閾值。
演算法實現起來應該很容易,就不幫你編寫代碼了。
④ 一道k-means演算法的c++程序,幫幫看看哪裡出了錯
K-means演算法是很典型的基於距離的聚類演算法,採用距離作為相似性的評價指標,即認為兩個對象的距離越近,其相似度就越大。該演算法認為簇是由距離靠近的對象組成的,因此把得到緊湊且獨立的簇作為最終目標。
k個初始類聚類中心點的選取對聚類結果具有較大的影響,因為在該演算法第一步中是隨機的選取任意k個對象作為初始聚類的中心,初始地代表一個簇。該演算法在每次迭代中對數據集中剩餘的每個對象,根據其與各個簇中心的距離將每個對象重新賦給最近的簇。當考察完所有數據對象後,一次迭代運算完成,新的聚類中心被計算出來。如果在一次迭代前後,J的值沒有發生變化,說明演算法已經收斂。
演算法過程如下:
1)從N個文檔隨機選取K個文檔作為質心
2)對剩餘的每個文檔測量其到每個質心的距離,並把它歸到最近的質心的類
3)重新計算已經得到的各個類的質心
4)迭代2~3步直至新的質心與原質心相等或小於指定閾值,演算法結束
具體如下:
輸入:k,data[n];
(1)選擇k個初始中心點,例如c[0]=data[0],…c[k-1]=data[k-1];
(2)對於data[0]….data[n],分別與c[0]…c[k-1]比較,假定與c[i]差值最少,就標記為i;
(3)對於所有標記為i點,重新計算c[i]={所有標記為i的data[j]之和}/標記為i的個數;
(4)重復(2)(3),直到所有c[i]值的變化小於給定閾值。
k-means演算法本身不難,不過你截的圖片看著太不方便了。
你的程序沒什麼問題啊?
⑤ 八:聚類演算法K-means(20191223-29)
學習內容:無監督聚類演算法K-Means
k-means:模型原理、收斂過程、超參數的選擇
聚類分析是在數據中發現數據對象之間的關系,將數據進行分組,組內的相似性越大,組間的差別越大,則聚類效果越好。
不同的簇類型: 聚類旨在發現有用的對象簇,在現實中我們用到很多的簇的類型,使用不同的簇類型劃分數據的結果是不同的。
基於原型的: 簇是對象的集合,其中每個對象到定義該簇的 原型 的距離比其他簇的原型距離更近,如(b)所示的原型即為中心點,在一個簇中的數據到其中心點比到另一個簇的中心點更近。這是一種常見的 基於中心的簇 ,最常用的K-Means就是這樣的一種簇類型。 這樣的簇趨向於球形。
基於密度的 :簇是對象的密度區域,(d)所示的是基於密度的簇,當簇不規則或相互盤繞,並且有早上和離群點事,常常使用基於密度的簇定義。
關於更多的簇介紹參考《數據挖掘導論》。
基本的聚類分析演算法
1. K均值: 基於原型的、劃分的距離技術,它試圖發現用戶指定個數(K)的簇。
2. 凝聚的層次距離: 思想是開始時,每個點都作為一個單點簇,然後,重復的合並兩個最靠近的簇,直到嘗試單個、包含所有點的簇。
3. DBSCAN: 一種基於密度的劃分距離的演算法,簇的個數有演算法自動的確定,低密度中的點被視為雜訊而忽略,因此其不產生完全聚類。
不同的距離量度會對距離的結果產生影響,常見的距離量度如下所示:
優點:易於實現
缺點:可能收斂於局部最小值,在大規模數據收斂慢
演算法思想:
選擇K個點作為初始質心
repeat
將每個點指派到最近的質心,形成K個簇
重新計算每個簇的質心
until 簇不發生變化或達到最大迭代次數
這里的「重新計算每個簇的質心」,是根據目標函數來計算的,因此在開始時要考慮 距離度量和目標函數。
考慮歐幾里得距離的數據,使用 誤差平方和(Sum of the Squared Error,SSE) 作為聚類的目標函數,兩次運行K均值產生的兩個不同的簇集,使用SSE最小的那個。
k表示k個聚類中心,ci表示第幾個中心,dist表示的是歐幾里得距離。
這里有一個問題就是為什麼,我們更新質心是讓所有的點的平均值,這里就是SSE所決定的。
k均值演算法非常簡單且使用廣泛,但是其有主要的兩個缺陷:
1. K值需要預先給定 ,屬於預先知識,很多情況下K值的估計是非常困難的,對於像計算全部微信用戶的交往圈這樣的場景就完全的沒辦法用K-Means進行。對於可以確定K值不會太大但不明確精確的K值的場景,可以進行迭代運算,然後找出Cost Function最小時所對應的K值,這個值往往能較好的描述有多少個簇類。
2. K-Means演算法對初始選取的聚類中心點是敏感的 ,不同的隨機種子點得到的聚類結果完全不同
3. K均值演算法並不是很所有的數據類型。 它不能處理非球形簇、不同尺寸和不同密度的簇,銀冠指定足夠大的簇的個數是他通常可以發現純子簇。
4. 對離群點的數據進行聚類時,K均值也有問題 ,這種情況下,離群點檢測和刪除有很大的幫助。
下面對初始質心的選擇進行討論:
當初始質心是隨機的進行初始化的時候,K均值的每次運行將會產生不同的SSE,而且隨機的選擇初始質心結果可能很糟糕,可能只能得到局部的最優解,而無法得到全局的最優解。
多次運行,每次使用一組不同的隨機初始質心,然後選擇一個具有最小的SSE的簇集。該策略非常的簡單,但是效果可能不是很好,這取決於數據集合尋找的簇的個數。
關於更多,參考《數據挖掘導論》
為了克服K-Means演算法收斂於局部最小值的問題,提出了一種 二分K-均值(bisecting K-means)
將所有的點看成是一個簇
當簇小於數目k時
對於每一個簇
計算總誤差
在給定的簇上進行K-均值聚類,k值為2 計算將該簇劃分成兩個簇後總誤差
選擇是的誤差最小的那個簇進行劃分
在原始的K-means演算法中,每一次的劃分所有的樣本都要參與運算,如果數據量非常大的話,這個時間是非常高的,因此有了一種分批處理的改進演算法。
使用Mini Batch(分批處理)的方法對數據點之間的距離進行計算。
Mini Batch的好處:不必使用所有的數據樣本,而是從不同類別的樣本中抽取一部分樣本來代表各自類型進行計算。n 由於計算樣本量少,所以會相應的減少運行時間n 但另一方面抽樣也必然會帶來准確度的下降。
聚類試圖將數據集中的樣本劃分為若干個通常是不相交的子集,每個子集成為一個「簇」。通過這樣的劃分,每個簇可能對應於一些潛在的概念(也就是類別);需說明的是,這些概念對聚類演算法而言事先是未知的,聚類過程僅能自動形成簇結構,簇對應的概念語義由使用者來把握和命名。
聚類是無監督的學習演算法,分類是有監督的學習演算法。所謂有監督就是有已知標簽的訓練集(也就是說提前知道訓練集里的數據屬於哪個類別),機器學習演算法在訓練集上學習到相應的參數,構建模型,然後應用到測試集上。而聚類演算法是沒有標簽的,聚類的時候,需要實現的目標只是把相似的東西聚到一起。
聚類的目的是把相似的樣本聚到一起,而將不相似的樣本分開,類似於「物以類聚」,很直觀的想法是同一個簇中的相似度要盡可能高,而簇與簇之間的相似度要盡可能的低。
性能度量大概可分為兩類: 一是外部指標, 二是內部指標 。
外部指標:將聚類結果和某個「參考模型」進行比較。
內部指標:不利用任何參考模型,直接考察聚類結果。
對於給定的樣本集,按照樣本之間的距離大小,將樣本集劃分為K個簇。讓簇內的點盡量緊密的連在一起,而讓簇間的距離盡量的大
初學者會很容易就把K-Means和KNN搞混,其實兩者的差別還是很大的。
K-Means是無監督學習的聚類演算法,沒有樣本輸出;而KNN是監督學習的分類演算法,有對應的類別輸出。KNN基本不需要訓練,對測試集裡面的點,只需要找到在訓練集中最近的k個點,用這最近的k個點的類別來決定測試點的類別。而K-Means則有明顯的訓練過程,找到k個類別的最佳質心,從而決定樣本的簇類別。
當然,兩者也有一些相似點,兩個演算法都包含一個過程,即找出和某一個點最近的點。兩者都利用了最近鄰(nearest neighbors)的思想。
優點:
簡單, 易於理解和實現 ;收斂快,一般僅需5-10次迭代即可,高效
缺點:
1,對K值得選取把握不同對結果有很大的不同
2,對於初始點的選取敏感,不同的隨機初始點得到的聚類結果可能完全不同
3,對於不是凸的數據集比較難收斂
4,對噪點過於敏感,因為演算法是根據基於均值的
5,結果不一定是全局最優,只能保證局部最優
6,對球形簇的分組效果較好,對非球型簇、不同尺寸、不同密度的簇分組效果不好。
K-means演算法簡單理解,易於實現(局部最優),卻會有對初始點、雜訊點敏感等問題;還容易和監督學習的分類演算法KNN混淆。
參考閱讀:
1.《 深入理解K-Means聚類演算法 》
2.《 K-Means 》
⑥ 大數據分析之聚類演算法
大數據分析之聚類演算法
1. 什麼是聚類演算法
所謂聚類,就是比如給定一些元素或者對象,分散存儲在資料庫中,然後根據我們感興趣的對象屬性,對其進行聚集,同類的對象之間相似度高,不同類之間差異較大。最大特點就是事先不確定類別。
這其中最經典的演算法就是KMeans演算法,這是最常用的聚類演算法,主要思想是:在給定K值和K個初始類簇中心點的情況下,把每個點(亦即數據記錄)分到離其最近的類簇中心點所代表的類簇中,所有點分配完畢之後,根據一個類簇內的所有點重新計算該類簇的中心點(取平均值),然後再迭代的進行分配點和更新類簇中心點的步驟,直至類簇中心點的變化很小,或者達到指定的迭代次數。
KMeans演算法本身思想比較簡單,但是合理的確定K值和K個初始類簇中心點對於聚類效果的好壞有很大的影響。
聚類演算法實現
假設對象集合為D,准備劃分為k個簇。
基本演算法步驟如下:
1、從D中隨機取k個元素,作為k個簇的各自的中心。
2、分別計算剩下的元素到k個簇中心的相異度,將這些元素分別劃歸到相異度最低的簇。
3、根據聚類結果,重新計算k個簇各自的中心,計算方法是取簇中所有元素各自維度的算術平均數。
4、將D中全部元素按照新的中心重新聚類。
5、重復第4步,直到聚類結果不再變化。
6、將結果輸出。
核心Java代碼如下:
/**
* 迭代計算每個點到各個中心點的距離,選擇最小距離將該點劃入到合適的分組聚類中,反復進行,直到
* 分組不再變化或者各個中心點不再變化為止。
* @return
*/
public List[] comput() {
List[] results = new ArrayList[k];//為k個分組,分別定義一個聚簇集合,未來放入元素。
boolean centerchange = true;//該變數存儲中心點是否發生變化
while (centerchange) {
iterCount++;//存儲迭代次數
centerchange = false;
for (int i = 0; i < k; i++) {
results[i] = new ArrayList<T>();
}
for (int i = 0; i < players.size(); i++) {
T p = players.get(i);
double[] dists = new double[k];
for (int j = 0; j < initPlayers.size(); j++) {
T initP = initPlayers.get(j);
/* 計算距離 這里採用的公式是兩個對象相關屬性的平方和,最後求開方*/
double dist = distance(initP, p);
dists[j] = dist;
}
int dist_index = computOrder(dists);//計算該點到各個質心的距離的最小值,獲得下標
results[dist_index].add(p);//劃分到對應的分組。
}
/*
* 將點聚類之後,重新尋找每個簇的新的中心點,根據每個點的關注屬性的平均值確立新的質心。
*/
for (int i = 0; i < k; i++) {
T player_new = findNewCenter(results[i]);
System.out.println("第"+iterCount+"次迭代,中心點是:"+player_new.toString());
T player_old = initPlayers.get(i);
if (!IsPlayerEqual(player_new, player_old)) {
centerchange = true;
initPlayers.set(i, player_new);
}
}
}
return results;
}
上面代碼是其中核心代碼,我們根據對象集合List和提前設定的k個聚集,最終完成聚類。我們測試一下,假設要測試根據NBA球員的場均得分情況,進行得分高中低的聚集,很簡單,高得分在一組,中等一組,低得分一組。
我們定義一個Player類,裡面有屬性goal,並錄入數據。並設定分組數目為k=3。
測試代碼如下:
List listPlayers = new ArrayList();
Player p1 = new Player();
p1.setName(「mrchi1」);
p1.setGoal(1);
p1.setAssists(8);
listPlayers.add(p1);
Player p2 = new Player();
p2.setName("mrchi2");
p2.setGoal(2);
listPlayers.add(p2);
Player p3 = new Player();
p3.setName("mrchi3");
p3.setGoal(3);
listPlayers.add(p3);
//其他對象定義此處略。製造幾個球員的對象即可。
Kmeans<Player> kmeans = new Kmeans<Player>(listPlayers, 3);
List<Player>[] results = kmeans.comput();
for (int i = 0; i < results.length; i++) {
System.out.println("類別" + (i + 1) + "聚集了以下球員:");
List<Player> list = results[i];
for (Player p : list) {
System.out.println(p.getName() + "--->" + p.getGoal()
}
}
演算法運行結果:
可以看出中心點經歷了四次迭代變化,最終分類結果也確實是相近得分的分到了一組。當然這種演算法有缺點,首先就是初始的k個中心點的確定非常重要,結果也有差異。可以選擇彼此距離盡可能遠的K個點,也可以先對數據用層次聚類演算法進行聚類,得到K個簇之後,從每個類簇中選擇一個點,該點可以是該類簇的中心點,或者是距離類簇中心點最近的那個點。
⑦ 用C語言實現聚類分析演算法或者是FCM演算法源程序
為什麼總有人在這里問這么麻煩的問題呢,會有人有耐心給你寫程序嗎
⑧ 聚類演算法
1. 概述
K-means聚類演算法也稱k均值聚類演算法,是集簡單和經典於一身的基於距離的聚類演算法。它採用距離作為相似性的評價指標,即認為兩個對象的距離越近,其相似度就越大。該演算法認為類簇是由距離靠近的對象組成的,因此把得到 緊湊且獨立的簇作為最終目標。
2. 演算法核心思想
K-means聚類演算法是一種迭代求解的聚類分析演算法,其步驟是隨機選取K個對象作為初始的聚類中心,然後計算每個對象與各個種子聚類中心之間的距離,把每個對象分配給距離它最近的聚類中心。聚類中心以及分配給它們的對象就代表一個聚類。每分配一個樣本,聚類的聚類中心會根據聚類中現有的對象被重新計算。這個過程將不斷重復直到滿足某個終止條件。終止條件可以是沒有(或最小數目)對象被重新分配給不同的聚類,沒有(或最小數目)聚類中心再發生變化,誤差平方和局部最小。
3. 演算法實現步驟
1、首先確定一個k值,即我們希望將數據集經過聚類得到k個集合。
2、從數據集中隨機選擇k個數據點作為質心。
3、對數據集中每一個點,計算其與每一個質心的距離(如歐式距離),離哪個質心近,就劃分到那個質心所屬的集合。
4、把所有數據歸好集合後,一共有k個集合。然後重新計算每個集合的質心。
5、如果新計算出來的質心和原來的質心之間的距離小於某一個設置的閾值(表示重新計算的質心的位置變化不大,趨於穩定,或者說收斂),我們可以認為聚類已經達到期望的結果,演算法終止。
6、如果新質心和原質心距離變化很大,需要迭代3~5步驟。
4. 演算法步驟圖解
上圖a表達了初始的數據集,假設k=2。在圖b中,我們隨機選擇了兩個k類所對應的類別質心,即圖中的紅色質心和藍色質心,然後分別求樣本中所有點到這兩個質心的距離,並標記每個樣本的類別為和該樣本距離最小的質心的類別,如圖c所示,經過計算樣本和紅色質心和藍色質心的距離,我們得到了所有樣本點的第一輪迭代後的類別。此時我們對我們當前標記為紅色和藍色的點分別求其新的質心,如圖d所示,新的紅色質心和藍色質心的位置已經發生了變動。圖e和圖f重復了我們在圖c和圖d的過程,即將所有點的類別標記為距離最近的質心的類別並求新的質心。最終我們得到的兩個類別如圖f。
K-means術語:
簇:所有數據的點集合,簇中的對象是相似的。
質心:簇中所有點的中心(計算所有點的中心而來)
5. K-means演算法優缺點
優點:
1、原理比較簡單,實現也是很容易,收斂速度快。
2、當結果簇是密集的,而簇與簇之間區別明顯時, 它的效果較好。
3、主要需要調參的參數僅僅是簇數k。
缺點:
1、K值需要預先給定,很多情況下K值的估計是非常困難的。
2、K-Means演算法對初始選取的質心點是敏感的,不同的隨機種子點得到的聚類結果完全不同 ,對結果影響很大。
3、對噪音和異常點比較的敏感。用來檢測異常值。
4、採用迭代方法,可能只能得到局部的最優解,而無法得到全局的最優解。