#coding=utf-8
2 from numpy import *
3
4 def loadDataSet(fileName):
5 dataMat = []
6 fr = open(fileName)
7 for line in fr.readlines():
8 curLine = line.strip().split('\t')
9 fltLine = map(float, curLine)
10 dataMat.append(fltLine)
11 return dataMat
12
13 #计算两个向量的距离,用的是欧几里得距离
14 def distEclud(vecA, vecB):
15 return sqrt(sum(power(vecA - vecB, 2)))
16
17 #随机生成初始的质心(ng的课说的初始方式是随机选K个点)
18 def randCent(dataSet, k):
19 n = shape(dataSet)[1] #shape(dataSet)获得数据集的形状, 即数据集是几行几列的,然后取下标为1的元素
20 centroids = mat(zeros((k,n))) #初始化一个k行n列的二维数组,数组初始值全部为0,然后用mat函数将其转化为矩阵
21 for j in range(n):
22 minJ = min(dataSet[:,j]) #[:,j]:逗号前部分表示取dataSet数据集所有行,j表示取第j列。本句含义:依次取dataSet数据集第j列最小值,j从0到n。参考文献:https://blog.csdn.net/github_36669230/article/details/78038756
23 rangeJ = float(max(array(dataSet)[:,j]) - minJ) #max(array(dataSet)[:,j]):取数据集中第j列的最大值。本句含义:用第j列最大值减去最小值,获得第j列元素的取值范围
24 centroids[:,j] = minJ + rangeJ * random.rand(k,1) #numpy.random.rand()
官方文档中给出的用法是:numpy.random.rand(d0,d1,…dn)
以给定的形状创建一个数组,并在数组中加入在[0,1]之间均匀分布的随机样本。例:a=np.random.rand(2,3),表示创建一个形状为二维三列的数组,数组元素在0到1之间均匀分布。
25 return centroids
26
27 def kMeans(dataSet, k, distMeas=distEclud, createCent=randCent):
#将函数distEclud和randCent作为参数传进来,可以更好的封装kMeans函数
28 m = shape(dataSet)[0] #获得数据集的形状后,取第0列数据,即获得数据集的行数
29 clusterAssment = mat(zeros((m,2))) # clusterAssment是一个m行2列的矩阵,第一列存放每个样本所属聚类中心的下标,第二列存放该样本与该聚类中心的距离
30
31 centroids = createCent(dataSet, k)
32 clusterChanged = True
33 while clusterChanged:
34 clusterChanged = False
#下面两个for循环计算每一个样本到每一个聚类中心的距离
35 for i in range(m): #取每一个样本
36 minDist = inf #inf表示无穷大,-inf表示负无穷
37 minIndex = -1
38 for j in range(k):
39 distJI = distMeas(centroids[j,:],dataSet[i,:])
40 if distJI < minDist:
41 minDist = distJI; minIndex = j
42 if clusterAssment[i,0] != minIndex:
43 clusterChanged = True
44 clusterAssment[i,:] = minIndex,minDist**2
45 print centroids
46 for cent in range(k): #重新计算聚类中心,cent从0遍历到k
47 ptsInClust = dataSet[nonzero(clusterAssment[:,0].A==cent)[0]]
#clusterAssment[:,0]:取得clusterAssment中第0列元
素。
#clusterAssment[:,0].A:转置成一个1行m列的行矩阵
#clusterAssment[:,0].A==cent :将行矩阵中每一个元素与
cent进行比较,得到一个1行m列、元素取值为True和false
的矩阵,元素为true表示该样本是第cent个聚类中心的点
#nonzero(clusterAssment[:,0].A==cent)[0]:获得元素值为
True的元素下标,这些下标集合即为所有属于cent类的样
本下标
#整句含义:取得数据集中属于第cent个簇的样本集
48 centroids[cent,:] = mean(ptsInClust, axis=0)
#对ptsInClust的每一列计算平均值,生成新的聚类中心
#axis=0:进行列运算
#centroids[cent,:]:第cent行
49 return centroids, clusterAssment
50
51 def show(dataSet, k, centroids, clusterAssment):
52 from matplotlib import pyplot as plt
53 numSamples, dim = dataSet.shape #dataSet.shape返回两个
#值,分别赋给numSamples和dim
54 mark = ['or', 'ob', 'og', 'ok', '^r', '+r', 'sr', 'dr', '<r', 'pr'] #样本集的显
#示样式
55 for i in xrange(numSamples): #xrange一次加载一个数,range
#一次加载完所有数。当数据范围较大时,range
#一次性加载完所有数据,效率较慢。
56 markIndex = int(clusterAssment[i, 0])
57 plt.plot(dataSet[i, 0], dataSet[i, 1], mark[markIndex])
58 mark = ['Dr', 'Db', 'Dg', 'Dk', '^b', '+b', 'sb', 'db', '<b', 'pb'] #聚类中
#心的显示样式
59 for i in range(k):
60 plt.plot(centroids[i, 0], centroids[i, 1], mark[i], markersize = 12)
61 plt.show()
62
63 def main():
64 dataMat = mat(loadDataSet('testSet.txt'))
65 myCentroids, clustAssing= kMeans(dataMat,4)
66 print myCentroids
67 show(dataMat, 4, myCentroids, clustAssing)
68
69
70 if __name__ == '__main__':
71 main() #python代码按照顺序从头到尾执行,不执行def开头的函数,def函数只有被调用时才执行。本句意思是:判断正在执行的程序是否有主函数,若有,则不执行第71行语句;若没有,则调用main函数
参考文献:http://www.cnblogs.com/MrLJC/p/4127553.html
Python实现K-means代码详解(新手上路)
猜你喜欢
转载自blog.csdn.net/u011208984/article/details/85376671
今日推荐
周排行