当前位置:首页 » 编程语言 » 聚类算法的实现c语言
扩展阅读
webinf下怎么引入js 2023-08-31 21:54:13
堡垒机怎么打开web 2023-08-31 21:54:11

聚类算法的实现c语言

发布时间: 2023-01-11 18:31:25

① 使用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、采用迭代方法,可能只能得到局部的最优解,而无法得到全局的最优解。