聚类算法有很多种(几十种),K-Means是聚类算法中的最常用的一种,算法最大的特点是简单,好理解,运算速度快,但是一定要在聚类前需要手工指定要分成几类。 具体实现步骤如下: 给定n个训练样本{x1,x2,x3,…,xn}
kmeans算法过程描述如下所示:
1.创建k个点作为起始质心点,c1,c2,…,ck 2.重复以下过程直到收敛
遍历所有样本xi,根据距离确定每一个样本的类别。 确定类别后,计算每一个样本到各自质心的距离,然后求和。和用来和前一次计算出来的距离和比较,已确定是否收敛。 对每一个类,计算所有样本的均值并将其作为新的质心(对于点而言,就是所有x坐标的平均值作为质心的x坐标,所有y坐标的平均值作为y坐标的均值) 根据以上步骤,实现的具体效果如下:
完整代码如下:
from matplotlib import pyplot import numpy as np #随机生成K个质心 def randomCenter(pointers,k): indexs = np.random.random_integers(0,len(pointers)-1,k) centers = [] for index in indexs: centers.append(pointers[index]) return centers #绘制最终的结果 def drawPointersAndCenters(pointers,centers): i = 0 for classs in pointers: cs = np.zeros(4,dtype=np.int8) cs[i]=1 cs[3]=1 #将list转为numpy中的array,方便切片 xy = np.array(classs) if(len(xy)>0): pyplot.scatter(xy[:,0],xy[:,1],c=cs) i += 1 centers = np.array(centers) pyplot.scatter(centers[:, 0], centers[:, 1], c=[0,0,0],linewidths = 20) pyplot.show() #计算两个向量的距离,用的是欧几里得距离 def distEclud(vecA, vecB): return np.sqrt(np.sum(np.power(vecA - vecB, 2))) #求这一组数据坐标的平均值,也就是新的质心 def getMean(data): xMean = np.mean(data[:,0]) yMean = np.mean(data[:,1]) return [xMean,yMean] def KMeans(pointers,centers): diffAllNew = 100 diffAllOld = 0 afterClassfy = [] while(abs(diffAllNew - diffAllOld)>1): #更新diffAllOld为diffAllNEw diffAllOld = diffAllNew #先根据质心,对所有的数据进行分类 afterClassfy = [[] for a in range(len(centers))] for pointer in pointers: dis = [] for center in centers: dis.append(distEclud(pointer,center)) minDis = min(dis) i=0 for d in dis: if(minDis == d): break else: i += 1 afterClassfy[i].append(pointer) afterClassfy = np.array(afterClassfy) #计算所有点到其中心距离的总的和 diffAllNews = [[] for a in range(len(centers))] i=0 for classs in afterClassfy: for center in centers: if len(classs) >0: diffAllNews[i] += distEclud(classs,center) i+=1 diffAllNew = sum(diffAllNews) #更新质心的位置 i=0 for classs in afterClassfy: classs = np.array(classs) if len(classs) > 0 : centers[i] = getMean(classs) i += 1 drawPointersAndCenters(afterClassfy,centers) print(afterClassfy) def randonGenerate15Pointer(): ponters =[np.random.random_integers(0,10,2) for a in range(15)] np.save("data",ponters) print(ponters) def loadData(fileName): return np.load(fileName) def test(): pointers = loadData("data.npy") centers = randomCenter(pointers,3) print(pointers) print(centers) KMeans(pointers, centers) test()loadData装载的数据是通过randonGenerate15Pointer()方法随机生成的15个点。