首页 > 代码库 > 集体智慧编程-discovering groups
集体智慧编程-discovering groups
这一章讲的是利用聚集算法对blog进行分类。
首先是构造数据,找到一组blog,每个blog包含一组单词。这样就形成了(blog-name, word*)*的数据结构。
在构造该数据结构的过程中,还需要删除那些出现得太广泛的单词,删除的办法是计算每个词出现的总次数以及blog的总数,两者的比例超出某个特定的数值则表明该单词太泛滥了。
然后是计算blog之间的距离,和前一章一样,存在两种计算的方式。欧氏距离和pearson相关系数。
然后是聚集算法,存在两种聚集的方法,一种是基于row的,另一种是基于column的。
初始化:每个blog都是一个cluster,共计n个cluster,形成clusters的向量;
一次聚集算法:
for 每个cluster
for 每个其它的cluster
计算出它们之间的距离
找出上述距离的最小值,以及形成最小值的pair。
将clusters中的pair对应的元素删除,同时将pair作为一个新的cluster加入clusters中,新的cluster包含pair的两个元素的内容。
通过这个算法,我们就能获得blog之间的相关性,如下图所示:
上图中ab比较接近,而de的距离比dc的距离更近。
这种表示聚集结果的方法叫做dendragram,就是按照层次化的方法展示聚集结果。怎么把一个cluster展示成一个dendragram图呢?一个很重要的结论是,所有的节点都在叶子上,所以叶子节点多少决定了图形的宽度和高度,因此可以得出如下的递归表达式:
如果parent的位置是x,y,up和bot表示上下两个儿子的节点数,并且每个节点的高度为const,并且up-d,bot-d表示儿子离parent的距离;
up的x为parent.x + up-d * 常数
up的y为parent.y + up * 常数 /2
同理算出bot的。这样就能算出整个节点树的形状。
-----------------------------------
上面讲的根据单词找出blog之间的相关关系,但是有时候找出单词之间的关系也是有意思的。如果一个单词出现在blog1,blog2中,另一个单词也出现在blog1,blog2中,那么我们认为这两个单词存在某种联系。
找出这种集群的算法很简单,和上面的算法类似,只是对向量做一个transform。
----------------------------------
然后再来看看kmeans算法。
初始化:随机选出k个点作为中心点,建立best-match:{中心:【中心点附近的点】}
迭代:
遍历所有的向量,
遍历所有中心点,找到该向量最近的中心点x
把向量加入大best-match【x】的集合中
遍历best-match所有的value,每个value是一个集合
找出这个集合的中心点,用它替换旧的中心点
计算对新的best-match的,每个点到其对应中心点的距离的总和;
如果这个总和呈现下降趋势则继续,如果出现上升,则停止;目的是使得这个总和最小。
----------------------------------
分析下,基于row的算法,每次归并1个点,共计n轮,每次计算任意两点的距离n*n,共计n^3复杂度。
kmeans算法,经历的轮数不确定,每次复杂度n*k,k代表集群个数。因此当n很大的时候,kmeans复杂度更低。
----------------------------------
然后怎样把kmeans的计算结果展现到图上呢?假设有n个point,相互之间的真实距离是real(i,j),如何呈现在一个平面图上?
可以使用梯度下降的方法。
首先为每个点随机分配一个位置(xi,yi)for i;
进入迭代:
for每个i
for 每个j
计算平面图上的各个点的距离dist(i,j),将其与real(i,j)进行比较,计算出总体的误差绝对值之和 totalerror;
计算出grad(i,j)表示i到j的向量
调整每个点的位置,如果它和其它某个点的距离太大,则根据grad(i,j)靠近点儿,否则离远点儿。
(可能出现abc一条直线,a离b太远了,但离c太近了,a靠近b了,就使得到c的误差更大了,从而进入死循环吗?如果这样,应该移动b和c距离)
不过梯度下降本来就可能得不到全局最优解。
------------------------------------
就这样,我们可以实现2中聚集算法,并把聚集结果正确显示出来。
集体智慧编程-discovering groups