Kmeans原理和实现

K均值聚类算法是一种简单、快速、对大样本集高效的、经典的无监督学习多类分类算法。

K均值聚类算法是最简单的一种基于距离的聚类算法。算法采用样本的特征向量的距离作为相似性的评价标准,两个样本的特征向量的距离越接近,两者的相似度越高。K均值聚类算法训练完成的标准,是使各个样本的特征向量与所在类特征向量均值的误差平方和达到最小,此时所有样本与各自所在类特征向量均值距离最小,相似度最高。距离的计算公式有欧氏距离、曼哈顿距离等等,常用的为欧氏距离公式。

如图 2‑13所示,图中有三类样本点,经过聚类之后,产生了三个聚类中心,各类样本点距离相应的聚类中心最近。各个聚类中心准确的代表了所在类的典型值。


K均值聚类算法的总体上可分为四步,具体如下:

(1)初始化。输入所有样本数据,存入适当的容器中,输入指定要聚类的类别数N,并在容器中随机选取N个对象作为初始聚类中心。设定迭代终止条件,常用的迭代终止条件有最大循环次数聚类中心收敛误差容限等;

(2)进行迭代。根据算法相似度评价标准将所有数据对象分配到各自最接近的聚类中心所在的类,从而形成N类数据,每一个类用一个容器存储;

(3)更新聚类中心。以每一类数据的几何平均值作为新的聚类中心,然后根据相似性评价标准重新分配数据对象;

(4)循环执行第二步和第三步直至满足迭代终止条件,保存训练得到的聚类中心。

1.      Matlab代码


%初始化m_pattern
for i=1:num
   m_pattern(i).distance=inf;
   m_pattern(i).category=-1;
   m_pattern(i).feature=m_pattern1(i).feature;
end
%初始化聚类中心
randPattern=randperm(num);
for i=1:center_num
  m_pattern(randPattern(i)).category=i;
  m_pattern(randPattern(i)).distance=0;
  m_center(i).feature=m_pattern(randPattern(i)).feature;
  m_center(i).index=i;
  m_center(i).num=1;
  m_center(i).distance=0;
end
counter=0;%记录迭代次数
change=1;
while(counter<iter_num&&change~=0)
   counter=counter+1;
    change=0;
    %对每个pattern重归类,并计算重归类后的原类和新类的中心
    for i=1:num
       index=-1;
       distance=inf;
        %归类
        forj=1:center_num
           tempDis=GetDistance(m_pattern(i),m_center(j))-m_center(j).distance;
            if(tempDis<distance)
               distance=tempDis;
               index=j;
            end
        end
       
       if(m_pattern(i).category==index)
           m_pattern(i).distance=distance;
        else %计算重归类后的原类和新类的中心
           oldIndex=m_pattern(i).category;
           m_pattern(i).category=index;
           m_pattern(i).distance=distance;
           if(oldIndex~=-1)
               m_center(oldIndex)=CalCenter(m_center(oldIndex),m_pattern,num);
            end
           m_center(index)=CalCenter(m_center(index),m_pattern,num);
           change=1;
        end
       
    end
end


2.      C实现

void  KMeansCalculate(List l, XInfo* pMeans)
{
    List * pl;
        double oldVar = -1;
        double newVar = 0;
        int i;
        int count = ListGetCount(l);  //样本数量
        float threshold = THRESHOLD;
        int idx;
        int label;
        Node * p;    //样本数据的链表结构
        XInfo x;     //样本数据
        int time = 0;
 
        //初始化,随即生成聚类中心
    pl = (List *)malloc(NK * sizeof(List));  //NK为类别数
    for (i = 0; i < NK; i++)
        {
        idx = rand()%count;
               printf("%d \n",idx);
        pMeans[i] = ListAt(l, idx)->x;
               ListInit(&pl[i]);
        }
 
        //根据聚类中心对每个特征向量进行归类
    p = l->next;
        while (p != NULL)
        {
               x = p->x;
               label = GetLabel(pMeans, x);
        ListAdd(&pl[label], x);
               p = p->next;
        }
        
        //迭代,求出稳定的聚类中心
        newVar = GetVar(pl, pMeans);
        while (fabs(newVar - oldVar) >= threshold)
        {
          printf("第%d次迭代开始\n",++time);
 
                 for (i = 0; i < NK; i++)
                 {
                        pMeans[i] = GetMean(pl[i]);
                 }
 
                 oldVar = newVar;
                 newVar = GetVar(pl, pMeans);
                 printf("oldVar = %f  newVar = %f\n", oldVar, newVar);
                 for (i = 0; i < NK; i++)
                 {
                        ListClear(&pl[i]);
                 }
          p = l->next;
                 while (p != NULL)
                 {
                       x = p->x;
                       label = GetLabel(pMeans, x);
                       ListAdd(&pl[label], x);
                       p = p->next;
                 }
        }


3.      初值问题改进

Kmens算法由于聚类中心更新的局限性和初始化中心的随机性容易陷入局部最优。如下图所示,当聚类中心到达A位置时

 

 

Kmeans 用于图像分割



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
K-means算法是一种基于聚类的机器学习算法,用于将一组数据点分成K个不同的簇。K-means算法的原理是将所有数据点分成K个簇,每个簇的中心点是所有该簇数据点的平均值,然后通过最小化所有数据点到其所在簇中心点的距离的平方和来优化簇的分配。 下面是K-means算法的代码实现(Python): ```python import numpy as np class KMeans: def __init__(self, n_clusters=8, max_iter=300): self.n_clusters = n_clusters self.max_iter = max_iter def fit(self, X): self.centroids = X[np.random.choice(X.shape[0], self.n_clusters)] for i in range(self.max_iter): clusters = [[] for _ in range(self.n_clusters)] for x in X: distances = np.linalg.norm(self.centroids - x, axis=1) cluster_idx = np.argmin(distances) clusters[cluster_idx].append(x) new_centroids = np.zeros_like(self.centroids) for i, cluster in enumerate(clusters): if len(cluster) == 0: new_centroids[i] = self.centroids[i] else: new_centroids[i] = np.mean(cluster, axis=0) if np.allclose(new_centroids, self.centroids): break self.centroids = new_centroids def predict(self, X): distances = np.linalg.norm(self.centroids - X[:, np.newaxis], axis=2) return np.argmin(distances, axis=1) ``` 这里的`fit()`方法用于训练模型,`predict()`方法用于预测数据点所属的簇。在`fit()`方法中,首先随机初始化K个簇中心点,然后使用循环迭代来优化簇的分配和簇中心点的位置。在每次循环迭代中,将所有数据点分配到最近的簇中心点,然后重新计算每个簇的中心点位置。如果新的中心点位置与旧的中心点位置相同,则停止迭代。在`predict()`方法中,使用已经训练好的模型来预测新的数据点所属的簇。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值