k-means算法解决了什么问题

2024-05-09 22:46

1. k-means算法解决了什么问题

k-means
算法属于聚类分析方法中一种基本的且应用最广泛的划分算法,它是一种已知聚类类别数的聚类算法。指定类别数为k,对样本集合进行聚类,聚类的结果由k
个聚类中心来表达,基于给定的聚类目标函数(或者说是聚类效果判别准则),算法采用迭代更新的方法,每一次迭代过程都是向目标函数值减小的方向进行,最终的聚类结果使目标函数值取得极小值,达到较优的聚类效果。使用平均误差准则函数e作为聚类结果好坏的衡量标准之一,保证了算法运行结果的可靠性和有效性。

k-means算法解决了什么问题

2. K-means的介绍

K-means算法是硬聚类算法,是典型的基于原型的目标函数聚类方法的代表,它是数据点到原型的某种距离作为优化的目标函数,利用函数求极值的方法得到迭代运算的调整规则。K-means算法以欧式距离作为相似度测度,它是求对应某一初始聚类中心向量V最优分类,使得评价指标J最小。算法采用误差平方和准则函数作为聚类准则函数。

3. K-Means原理总结

    K-means是聚类中的一个经典方法。其中的原理和思想实在是巧妙到爆炸💥。接下来让我来给大家展示来自1967年的算法的智慧。
  
 问题引出:如下图所示,我们想要自动的聚类,肉眼一看是5类。那么我们随机生成5个点,它们最终将会成为聚类后每个类的中心点。由于是随机初始化的5个点,所以它们的位置刚开始大概率不在每个类的中心点上,不过没关系,我们可以慢慢调整。
                                          
 过程描述:如上图所示生成的5个点,它们最终会成为每个类的中心点,此时此刻,每个点有着自己的领域范围。比如最上面的那个点1,它想要成为一个类的中心点,这个类此时此刻都包含哪些点呢,答案当然是到它的距离比到其他中心点距离更近的所有样本点。那么接下来,哪些点符合条件呢?由于每个中心点它都想要控制尽可能多的点,并且得合理。那最上面那个中心点1想要控制位于它自己下面的一些样本点,会有哪些中心点在跟它竞争呢? 答案是中间左右两个点2和3,注意最下面两个中心点4和5参与不到竞争了。所以我们做出两条垂直平分线a,b。a是连线点1,2的垂直平分线,b是连线点1,3的垂直平分线。垂直平分线有什么性质啊? 位于线上的点到两端的距离相等,位于线一侧的点到该侧端点距离更小。所以!位于垂直平分线a,b上面的所有样本点暂时归中心点的领域,注意此时点1并未是该领域样本点的中心,我们应该更新点1的位置,把它挪到领域的中心。因为三角形三条边的垂直平分线会交于一点(先画出两条交于一点,再从该点向另一个边做垂线,证明该垂线与边的交点为中点即可)所以5个中心点互相竞争划分领域会呈现出如上并不杂乱的界限。我们更新5个中心点的位置,再次重新竞争领域,再更新位置。。。直到中心点的位置不动了,聚类完毕。
  
 
  
                                          
         原理中一直贯穿着中心的概念,这就是means的含义。接下来我们来分析一下K-means的优缺点。
  
             1.对分布类似球型的数据效果很好。为什么?试想长条带状的末端有一小簇。
  
 .............................................           。
  
 .............................................           。
  
 如果刚开始随机的中心点一左一右刚刚好,开始竞争,显然...这些右侧的..离。。。的中心点更近,按规则应该归它领域,然后再更新。这样就不符合人的直觉了。
  
             2.收敛的很快,中心点更新个几次后就不咋动了。
  
             3.相对高效并且易估计复杂度O(k·t·n),t是迭代次数一般几次就可以完成,k是中心点个数,簇的个数,不会很大。n是数据点的个数,可能会很大。
  
         1.K值不好估计,不能预先去判断。
  
         2.可能会因为初始点随机的不好,会收敛到一个奇怪的结果。如下图。

K-Means原理总结

4. K-means原理、优化、应用

 K-Means算法是无监督的聚类算法,它实现起来比较简单,聚类效果也不错,因此应用很广泛。K-Means算法有大量的变体,本文就从最传统的K-Means算法讲起,在其基础上讲述K-Means的优化变体方法。包括初始化优化K-Means++, 距离计算优化elkan K-Means算法和大数据情况下的优化Mini Batch K-Means算法。
  
     K-Means算法的思想很简单,对于给定的样本集,按照样本之间的距离大小,将样本集划分为K个簇。让簇内的点尽量紧密的连在一起,而让簇间的距离尽量的大。
  
 1、随机选择K个聚类的初始中心。
  
 2、对任意一个样本点,求其到K个聚类中心的距离,将样本点归类到距离最小的中心的聚类。
  
 3、每次迭代过程中,利用均值等方法更新各个聚类的中心点(质心)。
  
 4、对K个聚类中心,利用2、3步迭代更新后,如果位置点变化很小(可以设置阈值),则认为达到稳定状态,迭代结束。(画图时,可以对不同的聚类块和聚类中心可选择不同的颜色标注)
  
 1、原理比较简单,实现也是很容易,收敛速度快。 
  
 2、聚类效果较优。 
  
 3、算法的可解释度比较强。 
  
 4、主要需要调参的参数仅仅是簇数k。
  
 1、K值的选取不好把握 
  
 2、对于不是凸的数据集比较难收敛 
  
 3、如果各隐含类别的数据不平衡,比如各隐含类别的数据量严重失衡,或者各隐含类别的方差不同,则聚类效果不佳。 
  
 4、 最终结果和初始点的选择有关,容易陷入局部最优。
  
 5、对噪音和异常点比较的敏感。
  
     解决K-Means算法对 初始簇心 比较敏感的问题,二分K-Means算法是一种弱化初始质心的一种算法。
  
 1、将所有样本数据作为一个簇放到一个队列中。
  
 2、从队列中选择一个簇进行K-Means算法划分,划分为两个子簇,并将子簇添加到队列中。
  
 3、循环迭代步骤2操作,直到中止条件达到(聚簇数量、最小平方误差、迭代次数等)。
  
 4、队列中的簇就是最终的分类簇集合。
  
  从队列中选择划分聚簇的规则一般有两种方式;分别如下: 
  
 1、对所有簇计算误差和SSE(SSE也可以认为是距离函数的一种变种),选择SSE最大的聚簇进行划分操作(优选这种策略)。
  
 2、选择样本数据量最多的簇进行划分操作:
                                          
     由于 K-means 算法的分类结果会受到初始点的选取而有所区别,因此有提出这种算法的改进: K-means++ 。
  
     其实这个算法也只是对初始点的选择有改进而已,其他步骤都一样。初始质心选取的基本思路就是, 初始的聚类中心之间的相互距离要尽可能的远 。
  
 1、随机选取一个样本作为第一个聚类中心 c1;
  
 2、计算每个样本与当前已有类聚中心最短距离(即与最近一个聚类中心的距离),用 D(x)表示;这个值越大,表示被选取作为聚类中心的概率较大;最后,用轮盘法选出下一个聚类中心。
  
 3、重复步骤2,知道选出 k 个聚类中心。
  
 4、选出初始点(聚类中心),就继续使用标准的 k-means 算法了。
  
 尽管K-Means++在聚类中心的计算上浪费了很多时间,但是在迭代过程中,k-mean 本身能快速收敛,因此算法实际上降低了计算时间。
  
       解决K-Means++算法缺点而产生的一种算法;主要思路是改变每次遍历时候的取样规则,并非按照K-Means++算法每次遍历只获取一个样本,而是每次获取K个样本,重复该取样操作O(logn)次 (n是样本的个数) ,然后再将这些抽样出来的样本聚类出K个点,最后使用这K个点作为K-Means算法的初始聚簇中心点。实践证明:一般5次重复采用就可以保证一个比较好的聚簇中心点。
  
 1、在N个样本中抽K个样本,一共抽logn次,形成一个新的样本集,一共有Klogn个数据。
  
 2、在新数据集中使用K-Means算法,找到K个聚簇中心。
  
 3、把这K个聚簇中心放到最初的样本集中,作为初始聚簇中心。
  
 4、原数据集根据上述初始聚簇中心,再用K-Means算法计算出最终的聚簇。
  
         Canopy属于一种‘粗’聚类算法,即使用一种简单、快捷的距离计算方法将数据集分为若干可重叠的子集canopy,这种算法不需要指定k值、但精度较低,可以结合K-means算法一起使用:先由Canopy算法进行粗聚类得到k个质心,再使用K-means算法进行聚类。
  
  1、将原始样本集随机排列成样本列表L=[x1,x2,...,xm](排列好后不再更改),根据先验知识或交叉验证调参设定初始距离阈值T1、T2,且T1>T2 。
  
 2、从列表L中随机选取一个样本P作为第一个canopy的质心,并将P从列表中删除。
  
 3、从列表L中随机选取一个样本Q,计算Q到所有质心的距离,考察其中最小的距离D:
  
 如果D≤T1,则给Q一个弱标记,表示Q属于该canopy,并将Q加入其中;
  
 如果D≤T2,则给Q一个强标记,表示Q属于该canopy,且和质心非常接近,所以将该canopy的质心设为所有强标记样本的中心位置,并将Q从列表L中删除;
  
  如果D>T1,则Q形成一个新的聚簇,并将Q从列表L中删除。
  
 4、重复第三步直到列表L中元素个数为零。
  
 1、‘粗’距离计算的选择对canopy的分布非常重要,如选择其中某个属性、其他外部属性、欧式距离等。
  
 2、当T2<D≤T1时,样本不会从列表中被删除,而是继续参与下一轮迭代,直到成为新的质心或者某个canopy的强标记成员。
  
 3、T1、T2的取值影响canopy的重叠率及粒度:当T1过大时,会使样本属于多个canopy,各个canopy间区别不明显;当T2过大时,会减少canopy个数,而当T2过小时,会增加canopy个数,同时增加计算时间。
  
 4、canopy之间可能存在重叠的情况,但是不会存在某个样本不属于任何canopy的情况。
  
 5、Canopy算法可以消除孤立点,即删除包含样本数目较少的canopy,往往这些canopy包含的是孤立点或噪音点。
  
 
  
                                          
     由于K-Means算法存在初始聚簇中心点敏感的问题,常用使用Canopy+K-Means算法混合形式进行模型构建。
  
 1、先使用canopy算法进行“粗”聚类得到K个聚类中心点。
  
 2、K-Means算法使用Canopy算法得到的K个聚类中心点作为初始中心点,进行“细”聚类。
  
 1、执行速度快(先进行了一次聚簇中心点选择的预处理);
  
 2、不需要给定K值,应用场景多。
  
 3、能够缓解K-Means算法对于初始聚类中心点敏感的问题。
  
     Mini Batch K-Means算法是K-Means算法的一种优化变种,采用 小规模的数据子集 (每次训练使用的数据集是在训练算法的时候随机抽取的数据子集) 减少计算时间 ,同时试图优化目标函数;Mini Batch K-Means算法可以减少K-Means算法的收敛时间,而且产生的结果效果只是略差于标准K-Means算法。
  
 
  
 1、首先抽取部分数据集,使用K-Means算法构建出K个聚簇点的模型。
  
 2、继续抽取训练数据集中的部分数据集样本数据,并将其添加到模型中,分配给距离最近的聚簇中心点。
  
 3、更新聚簇的中心点值。
  
 4、循环迭代第二步和第三步操作,直到中心点稳定或者达到迭代次数,停止计算操作。
  
 
  
  
 https://www.jianshu.com/p/f0727880c9c0

5. 大数据十大经典算法之k-means

大数据十大经典算法之k-means
k均值算法基本思想:
K均值算法是基于质心的技术。它以K为输入参数,把n个对象集合分为k个簇,使得簇内的相似度高,簇间的相似度低。
处理流程:
1、为每个聚类确定一个初始聚类中心,这样就有k个初始聚类中心;
2、将样本按照最小距离原则分配到最邻近聚类
3、使用每个聚类中的样本均值作为新的聚类中心
4、重复步骤2直到聚类中心不再变化
5、结束,得到K个聚类
划分聚类方法对数据集进行聚类时的要点:
1、选定某种距离作为数据样本间的相似性度量,通常选择欧氏距离。
2、选择平价聚类性能的准则函数
用误差平方和准则函数来评价聚类性能。
3、相似度的计算分局一个簇中对象的平均值来进行
K均值算法的优点:
如果变量很大,K均值比层次聚类的计算速度较快(如果K很小);
与层次聚类相比,K均值可以得到更紧密的簇,尤其是对于球状簇;
对于大数据集,是可伸缩和高效率的;
算法尝试找出使平方误差函数值最小的k个划分。当结果簇是密集的,而簇与簇之间区别明显的时候,效果较好。
K均值算法缺点:
最后结果受初始值的影响。解决办法是多次尝试取不同的初始值。
可能发生距离簇中心m最近的样本集为空的情况,因此m得不到更新。这是一个必须处理的问题,但我们忽略该问题。
不适合发现非凸面形状的簇,并对噪声和离群点数据较敏感,因为少量的这类数据能够对均值产生较大的影响。
K均值算法的改进:
样本预处理。计算样本对象量量之间的距离,筛掉与其他所有样本那的距离和最大的m个对象。
初始聚类中心的选择。选用簇中位置最靠近中心的对象,这样可以避免孤立点的影响。
K均值算法的变种:
K众数(k-modes)算法,针对分类属性的度量和更新质心的问题而改进。
EM(期望最大化)算法
k-prototype算法
这种算法不适合处理离散型属性,但是对于连续型具有较好的聚类效果。
k均值算法用途:
图像分割;
衡量足球队的水平;
下面给出代码:
 #include   
    #include   
    //auther archersc  
    //JLU  
    namespace CS_LIB  
    {  
    using namespace std;  
    class Kmean  
    {  
    public:  
       //输入格式  
       //数据数量N 维度D  
       //以下N行,每行D个数据  
       istream& loadData(istream& in);  
       //输出格式  
       //聚类的数量CN  
       //中心维度CD  
       //CN行,每行CD个数据  
       //数据数量DN  
       //数据维度DD  
       //以下DN组,每组的第一行两个数值DB, DDis  
       //第二行DD个数值  
       //DB表示改数据属于一类,DDis表示距离改类的中心的距离  
       ostream& saveData(ostream& out);  
       //设置中心的数量  
       void setCenterCount(const size_t count);  
       size_t getCenterCount() const;  
       //times最大迭代次数, maxE ,E(t)表示第t次迭代后的平方误差和,当|E(t+1) - E(t)| < maxE时终止  
       void clustering(size_t times, double maxE);  
      
    private:  
       double calDistance(vector& v1, vector& v2);  
      
    private:  
       vector > m_Data;  
       vector > m_Center;  
       vector m_Distance;  
       vector m_DataBelong;  
       vector m_DataBelongCount;  
    };  
    }  
    #include "kmean.h"  
      
    #include   
    #include   
    #include   
    //auther archersc  
    //JLU  
      
    namespace CS_LIB  
    {  
    template  
    void swap(T& a, T& b)  
    {  
       T c = a;  
       a = b;  
       b = c;  
    }  
      
    istream& Kmean::loadData(istream& in)  
    {  
       if (!in){  
        cout << "input error" << endl;  
        return in;  
       }  
       size_t dCount, dDim;  
       in >> dCount >> dDim;  
       m_Data.resize(dCount);  
       m_DataBelong.resize(dCount);  
       m_Distance.resize(dCount);  
       for (size_t i = 0; i < dCount; ++i){  
        m_Data[i].resize(dDim);  
        for (size_t j = 0; j < dDim; ++j){  
         in >> m_Data[i][j];  
        }  
       }  
       return in;  
    }  
    ostream& Kmean::saveData(ostream& out)  
    {  
       if (!out){  
        cout << "output error" << endl;  
        return out;  
       }  
       out << m_Center.size();  
       if (m_Center.size() > 0)  
        out <<  << m_Center[0].size();  
       else  
        out <<  << 0;  
       out << endl << endl;  
       for (size_t i = 0; i < m_Center.size(); ++i){  
        for (size_t j = 0; j < m_Center[i].size(); ++j){  
         out << m_Center[i][j] << ;  
        }  
        out << endl;  
       }  
       out << endl;  
       out << m_Data.size();  
       if (m_Data.size() > 0)  
        out <<  << m_Data[0].size();  
       else  
        out <<  << 0;  
       out << endl << endl;  
       for (size_t i = 0; i < m_Data.size(); ++i){  
        out << m_DataBelong[i] <<  << m_Distance[i] << endl;  
        for (size_t j = 0; j < m_Data[i].size(); ++j){  
         out << m_Data[i][j] << ;  
        }  
        out << endl << endl;  
       }  
       return out;  
    }  
    void Kmean::setCenterCount(const size_t count)  
    {  
       m_Center.resize(count);  
       m_DataBelongCount.resize(count);  
    }  
    size_t Kmean::getCenterCount() const  
    {  
       return m_Center.size();  
    }  
    void Kmean::clustering(size_t times, double maxE)  
    {  
       srand((unsigned int)time(NULL));  
       //随机从m_Data中选取m_Center.size()个不同的样本点作为初始中心。  
       size_t *pos = new size_t[m_Data.size()];  
       size_t i, j, t;  
       for (i = 0; i < m_Data.size(); ++i){  
        pos[i] = i;  
       }  
       for (i = 0; i < (m_Data.size() << 1); ++i){  
        size_t s1 = rand() % m_Data.size();  
        size_t s2 = rand() % m_Data.size();  
        swap(pos[s1], pos[s2]);  
       }  
       for (i = 0; i < m_Center.size(); ++i){  
        m_Center[i].resize(m_Data[pos[i]].size());  
        for (j = 0; j < m_Data[pos[i]].size(); ++j){  
         m_Center[i][j] = m_Data[pos[i]][j];  
        }  
       }  
       delete []pos;  
       double currE, lastE;  
       for (t = 0; t < times; ++t){  
        for (i = 0; i < m_Distance.size(); ++i)  
         m_Distance[i] = LONG_MAX;  
        for (i = 0; i < m_DataBelongCount.size(); ++i)  
         m_DataBelongCount[i] = 0;  
        currE = 0.0;  
        for (i = 0; i < m_Data.size(); ++i){  
         for (j = 0; j < m_Center.size(); ++j){  
          double dis = calDistance(m_Data[i], m_Center[j]);  
          if (dis < m_Distance[i]){  
           m_Distance[i] = dis;  
           m_DataBelong[i] = j;  
          }  
         }  
         currE += m_Distance[i];  
         m_DataBelongCount[m_DataBelong[i]]++;  
        }  
        cout << currE << endl;  
        if (t == 0 || fabs(currE - lastE) > maxE)  
         lastE = currE;  
        else  
         break;  
        for (i = 0; i < m_Center.size(); ++i){  
         for (j = 0; j < m_Center[i].size(); ++j)  
          m_Center[i][j] = 0.0;  
          
        }  
        for (i = 0; i < m_DataBelong.size(); ++i){  
         for (j = 0; j < m_Data[i].size(); ++j){  
          m_Center[m_DataBelong[i]][j] += m_Data[i][j] / m_DataBelongCount[m_DataBelong[i]];  
         }  
        }   
       }  
    }  
    double Kmean::calDistance(vector& v1, vector& v2)  
    {  
       double result = 0.0;  
       for (size_t i = 0; i < v1.size(); ++i){  
        result += (v1[i] - v2[i]) * (v1[i] - v2[i]);  
       }  
       return pow(result, 1.0 / v1.size());  
    //return sqrt(result);  
    }  
    }  
    #include   
    #include   
    #include "kmean.h"  
    using namespace std;  
    using namespace CS_LIB;  
      
    int main()  
    {  
    ifstream in("in.txt");  
    ofstream out("out.txt");  
    Kmean kmean;  
    kmean.loadData(in);  
    kmean.setCenterCount(4);  
    kmean.clustering(1000, 0.000001);  
    kmean.saveData(out);  
      
    return 0;  
    }

大数据十大经典算法之k-means

6. k-means算法是聚类算法还是分类算法

一,k-means聚类算法原理
k-means
算法接受参数
k
;然后将事先输入的n个数据对象划分为
k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小.聚类相似度是利用各聚类中对象的均值所获得一个“中心对
象”(引力中心)来进行计算的.
  k-means算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一.k-means算法的基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类.通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果.
  假设要把样本集分为c个类别,算法描述如下:
  (1)适当选择c个类的初始中心;
  (2)在第k次迭代中,对任意一个样本,求其到c个中心的距离,将该样本归到距离最短的中心所在的类;
  (3)利用均值等方法更新该类的中心值;
  (4)对于所有的c个聚类中心,如果利用(2)(3)的迭代法更新后,值保持不变,则迭代结束,否则继续迭代.
  该算法的最大优势在于简洁和快速.算法的关键在于初始中心的选择和距离公式.

7. K-means的基本信息

 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算法输入:聚类个数k,以及包含 n个数据对象的数据库。输出:满足方差最小标准的k个聚类。 (1) 从 n个数据对象任意选择 k 个对象作为初始聚类中心;(2) 根据每个聚类对象的均值(中心对象),计算每个对象与这些中心对象的距离;并根据最小距离重新对相应对象进行划分;(3) 重新计算每个(有变化)聚类的均值(中心对象)(4) 循环(2)到(3)直到每个聚类不再发生变化为止k-means 算法接受输入量 k ;然后将n个数据对象划分为 k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对象”(引力中心)来进行计算的。工作过程k-means 算法的工作过程说明如下:首先从n个数据对象任意选择 k 个对象作为初始聚类中心;而对于所剩下其它对象,则根据它们与这些聚类中心的相似度(距离),分别将它们分配给与其最相似的(聚类中心所代表的)聚类;然 后再计算每个所获新聚类的聚类中心(该聚类中所有对象的均值);不断重复这一过程直到标准测度函数开始收敛为止。一般都采用均方差作为标准测度函数。k个聚类具有以下特点:各聚类本身尽可能的紧凑,而各聚类之间尽可能的分开。

K-means的基本信息

8. K-Means聚类算法原理是怎么样的?

一,K-Means聚类算法原理
        k-means 算法接受参数 k 
;然后将事先输入的n个数据对象划分为 
k个聚类以便使得所获得的聚类满足:同一聚类中的对象相似度较高;而不同聚类中的对象相似度较小。聚类相似度是利用各聚类中对象的均值所获得一个“中心对
象”(引力中心)来进行计算的。
  K-means算法是最为经典的基于划分的聚类方法,是十大经典数据挖掘算法之一。K-means算法的基本思想是:以空间中k个点为中心进行聚类,对最靠近他们的对象归类。通过迭代的方法,逐次更新各聚类中心的值,直至得到最好的聚类结果。
  假设要把样本集分为c个类别,算法描述如下:
  (1)适当选择c个类的初始中心;
  (2)在第k次迭代中,对任意一个样本,求其到c个中心的距离,将该样本归到距离最短的中心所在的类;
  (3)利用均值等方法更新该类的中心值;
  (4)对于所有的c个聚类中心,如果利用(2)(3)的迭代法更新后,值保持不变,则迭代结束,否则继续迭代。
  该算法的最大优势在于简洁和快速。算法的关键在于初始中心的选择和距离公式。