K-means聚类算法

   K-means聚类算法

1、算法思想

首先,我们可以随机选取K个对象作为初始的聚类中心,然后计算每个对象与每一个种子聚类中心的距离,然后分别把这些对象分配给距离对象最近的一个聚类中心,只要对象被分配以后,被分配的对象就和聚类中心组成一个新的聚类,分配后就不能改变了,然后在根据每个聚类的聚类中心和对象的距离进行重新计算,并且一直重复这样的计算,直到没有对象可以被重新分配给不同的聚类或聚类中心不再发生变化或误差平方和局部已经最小,这样循环计算就会停止。

2、优缺点

优点:a.算法容易实现

           b.当聚类个数小于真实值时,误差平方和会下降的很快;

缺点:a.当聚类个数超过真实值时,误差平方和虽然会继续下降,但是下降的速度会缓减,而这个转折点就是最佳的聚类个数了。

           b.非均质的数据、不同类别内部方差不相同 

3、伪代码

输入:类簇的个数K,迭代终止值Z。

输出:聚类结果

For(t=1;t<K;t++){

     给出数据对象Xi;

     计算聚类中心和对象的距离dist(Xi,Centerk);

     将Xi划到距离Xi最近的类簇中心所在的类簇中

For(直到Xi不能在分配){

将所有的类簇中心更新

}

输出聚类结果;

}

4.代码实现

 

import numpy as np

 

import pandas as pd

 

import random

 

import sys

 

import time

 

class KMeansClusterer:

 

    def __init__(self,ndarray,cluster_num):

 

        self.ndarray = ndarray

 

        self.cluster_num = cluster_num

 

        self.points=self.__pick_start_point(ndarray,cluster_num)

 

         

 

    def cluster(self):

 

        result = []

 

        for i in range(self.cluster_num):

 

            result.append([])

 

        for item in self.ndarray:

 

            distance_min = sys.maxsize

 

            index=-1

 

            for i in range(len(self.points)):                

 

                distance = self.__distance(item,self.points[i])

 

                if distance < distance_min:

 

                    distance_min = distance

 

                    index = i

 

            result[index] = result[index] + [item.tolist()]

 

        new_center=[]

 

        for item in result:

 

            new_center.append(self.__center(item).tolist())

 

        # 中心点未改变,说明达到稳态,结束递归

 

        if (self.points==new_center).all():

 

            return result

 

         

 

        self.points=np.array(new_center)

 

        return self.cluster()

 

             

 

    def __center(self,list):

 

        '''计算一组坐标的中心点

 

        '''

 

        # 计算每一列的平均值

 

        return np.array(list).mean(axis=0)

 

    def __distance(self,p1,p2):

 

        '''计算两点间距

 

        '''

 

        tmp=0

 

        for i in range(len(p1)):

 

            tmp += pow(p1[i]-p2[i],2)

 

        return pow(tmp,0.5)

 

    def __pick_start_point(self,ndarray,cluster_num):

 

        

 

        if cluster_num <0 or cluster_num > ndarray.shape[0]:

 

            raise Exception("簇数设置有误")

 

      

 

        # 随机点的下标

 

        indexes=random.sample(np.arange(0,ndarray.shape[0],step=1).tolist(),cluster_num)

 

        points=[]

 

        for index in indexes:

 

            points.append(ndarray[index].tolist())

 

        return np.array(points)

 

代码参考资料cf44fxnaALrxBy0alj1s9pDTHymWapRwW4pnYyFhdnzSIAK-aAFBsCADRaJbBaRXne6CwU5lM4ucx-Y2YTUKejAT7qcyU_OsvFfLJldKJPmfADilL3a6K3QzB3u--M2y.htm

 

原文地址:https://www.cnblogs.com/wyf-1999-1--6/p/11602519.html