您的位置:首页 > 编程语言

集体智慧编程 读书笔记 三

2014-02-14 14:27 232 查看
第三章

先是讲述聚类算法,第一步工作是构建数据集,书中给了现成数据集的下载地址, 还有feed list的下载地址, 给出了利用feed list 调用feedparser 处理成博客以及相应的单词的表格, 自己实现的时候没有必要这么来做, 一个是list里好多地址连不上, 都是国外的, 看懂代码即可, 我们可以直接把数据集下载下来, 书中给的地址已经改变所以新地址应该是:

数据集: http://segaran.com/clusters/blogdata.txt
feedlist http://segaran.com/clusters/feedlist.txt
数据集的格式为:

Blog	china	kids	music	yahoo
Wonkette	0	2	1	0	6	2


第一列是博客名字, 第一行是列名, 然后剩下的是博客中出现单词的次数,分隔符是‘\t’

分级聚类

类似归并排序,一级一级来, 最后构成的结果从上往下看就是一棵树, 两两归并的原则是相似度或者紧密度, 这里书中用的是pearson算法, 比欧几里得要好一些,他能纠正类似 某一博客单词次数比另一博客都多但是趋势一直, 也就是对于某一直线的拟合度很小,其实相似度很高的情形。
第一步:先处理数据,
def readfile(filename='your data file'):
lines = [line for line in open(filename)]

colnames = lines[0].strip().split('\t')[1:]
blognames = []
blogwordcount=[]

for line in lines[1:]:
datalist = line.strip().split('\t')
blognames.append(datalist[0])
blogwordcount.append([data for data in datalist[1:]])
return colnames, blognames, blogwordcount


pearson求两个单词向量的紧密度前面已经写过, 如下:
def pearson(v1, v2):
sum1 = sum(v1)
sum2 = sum(v2)

sum1sq = sum([pow(v, 2) for v in v1])
sum2sq = sum([pow(v, 2) for v in v2])

sumMul = sum([v1[i] * v2[i] for i in range(len(v1))] )

num = sumMul - sum1 * sum2 /len(v1)
den = sqrt((sum1sq-pow(sum1, 2)/len(v1)) * (sum2sq-pow(sum2, 2)/len(v1)))
if den == 0: return 0
return 1.0 - num/den


跟之前不一样的是最后一行, 以前是返回值越大相似度越高, 这里是返回值越小, 紧密度越高, 距离越近
为了树形表示, 构建一个类, 跟数据结构里讲二叉树节点一样, 只不过是python版本, 这里就不贴了, 之后就开始类似归并排序的工作, 不过跟归并排序不同的是 他是先从所有的向量里寻找最接近的两个, 然后生成新的 加入到剩余的里面, 然后再进行计算 知道剩下一个, 这个复杂度相当的高。。
下面来看代码:
def hcluster(rows, disfunc = pearson):
distance = {}
curclusterid = -1

cluster = [treenode(rows[i], id=i) for i in range(len(rows))]
while len(cluster) > 1:
lowestpair = (0,1)
closest = disfunc(cluster[0].vec, cluster[1].vec)

for i in range(len(cluster)):
for j in range(i+1, len(cluster)):
if (cluster[i].id, cluster[j].id) not in distance:
distance[(cluster[i].id, cluster[j].id)] = disfunc(cluster[i].vec, cluster[j].vec)
d = distance[(cluster[i].id, cluster[j].id)]
if d < closest:
closest = d
lowestpair = (i,j)
mergevec = [(int(cluster[lowestpair[0]].vec[i]) + int(cluster[lowestpair[1]].vec[i])) / 2.0 for i in range(len(cluster[0].vec))]

newitem = treenode(mergevec, left=cluster[lowestpair[0]], right=cluster[lowestpair[1]], distance=closest,id=curclusterid)
curclusterid -= 1
del cluster[lowestpair[1]]
del cluster[lowestpair[0]]
cluster.append(newitem)
return cluster[0]


让我想起了冒泡排序。。。。
下面是递归显示树:
def displaytree(trees, labels=None, n=0):
for i in range(n): print(' ', end="")
if trees.id < 0: print('-')
else:
if labels==None: print(trees.id)
else: print(labels[trees.id])
if trees.left != None: displaytree(trees.left, labels=labels, n=n+1)
if trees.right!=None: displaytree(trees.right, labels=labels, n=n+1)


注意print有个 end="" 在python3里print是默认一行以显示, 这里我们要自己控制换行要不显示就乱套了
部分输出如下所示
-
-
-
Wired News: Top Stories
-
Signum sine tinnitu--by Guy Kawasaki
-
Mashable!
-
GigaOM
TechCrunch


由此第一个分级聚类就完事了, 下面是用图形工具显示 待续。。。。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: