继上一篇博客使用分级聚类对博客进行聚类《集体智慧编程》,本次使用K-means方法来对博客聚类,部分代码和数据请看上一篇。
K-均值聚类应该算是比较容易理解的一种算法了,我在前面学习的时候有专门的说过K-means的原理原理和实现,如果不是很理解可以可以去看看。
作者使用方法和我之前的大同小异,我用的是多个组合函数对二维数据集的聚类,更容易理解和实现。本次的数据集为多维的数据集,方法也略有不同,所以这里记录一下,下面看代码:
(这里只写了K-means的代码,其余调用的函数代码和数据在上一篇中,可以直接拿来用)
import random
def kcluster(rows,distance=pearson,k=4):
#确定每个点的最小值和最大值 (这里竖着求出每个关键字出现次数的最小最大值)
ranges= [(min([row[i] for row in rows]),max([row[i] for row in rows]))
for i in range(len(rows[0]))]
#随机创建k个中心点 [[],[],[],[]]
clusters = [[random.random()*(ranges[i][1]-ranges[i][0]) + ranges[i][0]
for i in range(len(rows[0]))] for j in range(k)]
lastmatches = None #记录上一次聚类后的结果,用来和本次相比
cnt = 0
while(1):
cnt +=1
print('Iteration {}'.format(cnt))
bestmatches = [[] for i in range(k)] #生成k个嵌套的列表
#寻找每一行距离最近的中心点,然后添加到中心点列表中
for j in range(len(rows)):
row = rows[j]
bestmatch = 0 #每次用来记录该点目前所在最优簇号
for i in range(k): #与k个中心点比较,选出最近的
d = distance(clusters[i],row)
if(d<distance(clusters[bestmatch],row)):
bestmatch = i
bestmatches[bestmatch].append(j)
#如果结果与上一次相同,则整个过程结束
if(bestmatches == lastmatches):
break
lastmatches = bestmatches
#把中心点移到其所有成员的平均位置处
for i in range(k):
avgs = [0.0]*len(rows[0]) #初始化所有关键字那么长的列表
if(len(bestmatches[i]) > 0):
for rowid in bestmatches[i]: #这两个for循环求第i簇中所有列表点的和 每个列表对应相加
for m in range(len(rows[rowid])):
avgs[m] +=rows[rowid][m]
for j in range(len(avgs)): #该for循环将第i簇的和的列表除以i簇长度 求平均值
avgs[j] /=len(bestmatches[i])
clusters[i] = avgs
return bestmatches
kclust = kcluster(data,k=10)
print(kclust)
result1 = [blognames[r] for r in kclust[0]]
print(result1)
result2 = [blognames[r] for r in kclust[1]]
print(result2)
相对与我前面写的K-means,作者的方法代码更优化了,所以还是值得看的。
看一下结果:
这里只打印了0、1两个簇,我们的算法将它们聚在了一起,说明它们之间一定有着相似的关系,这里我们先不研究了。
这里其实可以发现,这几次的算法,大多用到了第一章学习的相似度距离的计算方法,这些算法得以实现,都通过了对距离的判断,所以对于相似度距离计算的方法应该有比较牢固的的掌握。