郑捷《机器学习算法原理与编程实践》学习笔记(第四章 推荐系统原理)(二)kmeans

时间:2024-01-05 18:11:02

(上接第二章)

  4.3.1 KMeans 算法流程

  算法的过程如下:

  (1)从N个数据文档随机选取K个文档作为质心

  (2)对剩余的每个文档测量其到每个质心的距离,并把它归到最近的质心的类

  (3)重新计算已经得到的各个类的质心

  (4)迭代(2)~(3)步直至新的质心与原质心相等或者小于指定阀值,算法结束。

  4.3.2 辅助函数

  (1)文件数据转为矩阵:file2matrix

def file2matrix(path,delimiter):
recordlist = []
fp = open(path,"rb")#读取文件内容
content = fp.read()
fp.close()
rowlist = content.splitlines()#按行转化为一维表
#逐行遍历,结果按分割符分割为行向量
recordlist = [map(eval,row.split(delimiter)) for row in rowlist if row.strip()]#eval:字符串转为、矩阵形式
return mat(recordlist)#返回转换后的矩阵形式

  (2)根据聚类中心绘制散点图,以及绘制聚类中心:默认4个聚类中心

def color_cluster(dataindx,dataSet,plt,k = 4):
index = 0
datalen = len(dataindx)
for indx in xrange(datalen):
if int(dataindx[indx]) == 0:
plt.scatter(dataSet[indx,0],dataSet[indx,1],c='blue',marker='o')
elif int(dataindx[indx]) == 1:
plt.scatter(dataSet[indx,0],dataSet[indx,1],c='green',marker='o')
elif int(dataindx[indx]) == 2:
plt.scatter(dataSet[indx,0],dataSet[indx,1],c='red',marker='o')
elif int(dataindx[indx]) == 3:
plt.scatter(dataSet[indx,0],dataSet[indx,1],c='cyan',marker='o')
index += 1
#绘制散点图
def drawScatter(plt,mydata,size = 20,color = 'blue',mrkr = 'o'):
plt.scatter(mydata.T[0],mydata.T[1],s = size,c = color,marker = mrkr)

  (3)欧式距离公式

#欧式距离
def distEclud(vecA,vecB):
return linalg.norm(vecA-vecB)

  (4)随机生成聚类的中心

def randCenters(dataSet,k):
n = shape(dataSet)[1] #初始化聚类中心矩阵:k*n
clustercents = mat(zeros(k,n))
for col in xrange(n):
mincol = min(dataSet[:,col])
maxcol = max(dataSet[:,col])
#random.rand(k,1):产生一个0~1之间的随机数向量:k,1表示k行1列的随机数
clustercents[:,col] = mat(mincol+float(maxcol-mincol)*random.rand(k,1))
return clustercents

  4.3.3 聚类主函数

  第一阶段:导入所需要的库,导入数据集,指定聚类中心k:

  

dataMat = file2matrix("./iris.txt"," ") #从文件构建的数据集
dataSet = mat(dataMat[:,1:]) #转换为矩阵的形式
m = dataSet.shape[0]
k = 4 #外部指定的聚类中心 #与数据等长,共两列。 #:列1:数据集对应的聚类中心k: #列2:数据集行向量到聚类中心的距离 ClusDist = mat(zeros((m,2))) clutercents = randCenters(dataSet,k) #随机生成聚类中心  flag = True #初始化迭代所需的标志位 counter = []

  第二阶段:算法停止迭代,即dataSet的所有向量都能找到某个聚类中心,到此中心的距离均小于其他k-1个中心的距离。

  

while flag:                               #主循环
flag = False #默认设置退出标志(False)

  第三阶段:内循环1遍历dataSet数据集,计算dataSet每行与聚类的最小欧氏距离,并以此更新聚类中心。

  算法停止条件:ClustDist[i,0] == minIndex

for i in xrange(m):
#遍历k个聚类中心,获取最短距离
distlist = [distEclud(clustercents[j,:],dataSet[i,:]) for j in range(k)]
minDist = min(distlist)
minIndex = distlist.index(minDist) if ClusDist[i,0] != minIndex: #找到一个新聚类中心
flag = True #重置标志位True,继续迭代 #更新聚类中心
ClusDist[i,:] = minIndex,minDist

  第四阶段:内循环2遍历每个聚类中心,计算DataSet已聚类的子列均值,并以此更新聚类中心。

  

for cent in xrange(k):
#从ClustDist的第一列筛选出等于cent的行下标
pstInClust = dataSet[nonzero(ClusDist[:,0].A == cent)[0]]
#计算pstInClust各列的均值:mean(ptsInClust,axis = 0):axis=0 #按列计算
clustercents[cent,:] = mean(ptsInClust,axis = 0)

  4.3.4  评估分类结果:
  第五阶段:分类结果可视化。

  

#返回计算完成的聚类中心
print "clustercents:\n",clustercents #根据ClustDist分类和描绘数据点
color_cluster(ClusDist[:,0:1],dataSet,plt)
#绘制聚类中心
drawScatter(plt,clustercents,size=60,color='red',mrkr='D')
plt.show()