《集体智慧编程》——分级聚类的实现

                     **(博客-单词)**

一:feeflist.txt
http://blog.csdn.net/hlx371240/rss/list
http://blog.csdn.net/sunflower606/rss/list
http://blog.csdn.net/leshami/rss/list
http://blog.csdn.net/cuit/rss/list
http://blog.csdn.net/abcjennifer/rss/list
http://blog.csdn.net/augusdi/rss/list
http://blog.csdn.net/zouxy09/rss/list
http://blog.csdn.net/yeyang911/rss/listhttp://blog.csdn.net/kewing/rss/list
自己在csdn上找的8个博客的rss
二:generatefeedvector.py
生成blogdata.txt
行代表出现的单词
列代表的是博客名
这里写图片描述
源码:

# -*- coding: utf-8 -*-
#列聚类不行,不是算法上的原因,是因为节点和线太多,像素点不够

from math import sqrt
from PIL import Image,ImageDraw,ImageFont
# 加载数据文件
def readfile(filename):
    """load data"""
    with open(filename) as file:
        lines = [line for line in file]
    # 第一列是列标题
    colnames = lines[0].strip().split('\t')
    rownames = []
    data = []
    for line in lines[1:]:
        p = line.strip().split('\t')
        # 每行第一列是行名
        rownames.append(p[0])
        # 其余部分是数据
        data.append([float(x) for x in p[1:]])
    return rownames,colnames,data
#rows,cols,data = readfile(r"D:\subject\PycharmProjects\blogdata")
#上面的代码测试完毕,结果正确
# 皮尔逊算法--求相似度
def pearson(v1, v2):
    """pearson"""
    # 求和
    sum1 = sum(v1)
    sum2 = sum(v2)

    # 求平方和
    sum1sq = sum([pow(v,2) for v in v1])
    sum2sq = sum([pow(v,2) for v in v2])

    # 求乘积之和
    psum = sum([v1[i] * v2[i] for i in range(len(v1))])

    # 计算pearson score
    num = psum - (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

class bicluster:
    def __init__(self,vec,left=None,right=None,distance=0.0,id=None):
        self.vec = vec
        self.left = left
        self.right = right
        self.distance = distance
        self.id = id
# 聚类算法
def hcluster(rows, distancefunc = pearson):
    """cluster"""
    distances = {}
    currentclusterid = -1

    # 最开始的聚类就是数据集中的行
    clust = [bicluster(rows[i], id=i) for i in range(len(rows))]

    while len(clust) > 1:
        lowestpair = (0,1)
        closest = distancefunc(clust[0].vec, clust[1].vec)

        # 遍历每个配对,寻找最小值
        for i in range(len(clust)):
            for j in range(i + 1, len(clust)):
                # 用distances缓存距离的计算值
                if (clust[i].id, clust[j].id) not in distances:
                    distances[(clust[i].id, clust[j].id)] = distancefunc(clust[i].vec, clust[j].vec)

                d = distances[(clust[i].id, clust[j].id)]

                if d < closest:
                    closest = d
                    lowestpair = (i, j)

        # 计算两个聚类的平均值
        mergevec = [(clust[lowestpair[0]].vec[i] + clust[lowestpair[1]].vec[i]) / 2.0
                    for i in range(len(clust[0].vec))]

        # 建立新的聚类
        newcluster = bicluster(mergevec,left=clust[lowestpair[0]],right=clust[lowestpair[1]],distance=closest,id=currentclusterid)
        # 不在原始集合中的聚类,其id为负数
        currentclusterid -= 1
        del clust[lowestpair[1]]
        del clust[lowestpair[0]]
        clust.append(newcluster)
    return clust[0]

#----------------------------------------------------------------------
# 树状图
#----------------------------------------------------------------------
# 树状图 -- 树的总高度
def getheight(clust):
    """get the height of the tree"""
    if clust.left == None and clust.right == None:
        return 1
    else:
        return (getheight(clust.left) + getheight(clust.right))
#----------------------------------------------------------------------
# 树状图 -- 树的距离
def getdepth(clust):
    """the depth of the tree"""
    if clust.left == None and clust.right == None:
        return 0
    else:
        return (max(getdepth(clust.left), getdepth(clust.right)) + clust.distance)
#----------------------------------------------------------------------
# 生成图片
def drawdendrogram(clust, labels, jpeg = 'clusters.jpg'):
    """draw the picture"""
    # 获得高度和宽度
    h = getheight(clust)*30
    w = 1400
    depth = getdepth(clust)

    # 由于宽度固定,因此需要对距离进行调整
    scaling = float(w-150)/depth

    # 创建白色背景的图片
    img = Image.new('RGB', (w,h), (255,255,255))
    draw = ImageDraw.Draw(img)

    draw.line((0,h/2,10,h/2), fill=(255,0,0))

    # 画第一个节点
    drawnode(draw, clust, 10, (h/2), scaling, labels)
    img.save(jpeg, 'JPEG')
#----------------------------------------------------------------------
# 画节点和连线
def drawnode(draw, clust, x, y, scaling, labels):
    """draw node and lined node"""
    if clust.id < 0:
        h1 = getheight(clust.left)*20
        h2 = getheight(clust.right)*20

        top = y - (h1+h2)/2
        bottom = y + (h1+h2)/2

        # 线的长度
        l1 = clust.distance * scaling
        # 聚类到其子节点的垂直线
        draw.line((x, top + h1/2, x, bottom - h2/2), fill=(255,0,0))

        # 连接左侧节点的水平线
        draw.line((x, top+h1/2, x+l1, top+h1/2), fill=(255,0,0))

        # 连接右侧节点的水平线
        draw.line((x, bottom-h2/2, x+l1, bottom-h2/2), fill=(255,0,0))

        # 绘制左右节点
        drawnode(draw, clust.left, x+l1, top+h1/2, scaling, labels)
        drawnode(draw, clust.right, x+l1, bottom-h2/2, scaling, labels)
    else:
        # 是叶节点则绘制其标签
        font = ImageFont.truetype('simsun.ttc',24)
        draw.text((x + 5,y - 7), unicode(labels[clust.id],'utf-8'), (0,0,0),font=font)
        print labels[clust.id]

#列聚类
#矩阵的转置
def rotatematrix(data):
    newdata=[]
    for i in range(len(data[0])):
        newrow=[data[j][i] for j in range(len(data))]
        newdata.append(newrow)
    return newdata

if __name__ == '__main__':
    blognames,words,data = readfile(r"D:\subject\PycharmProjects\blogdata")
    clust=hcluster(data)
    print clust.id
    drawdendrogram(clust,blognames,jpeg='blogclust.jpg')
    rotatematrix(data)
    '''
    #列聚类
    newdata=rotatematrix(data)
    clustcol=hcluster(newdata)
    print clustcol.id
    print "........"
    '''

行聚类
blogcluster.jpg
列聚类(运行时间很长,因为节点太多,此文中3471个)
报错:
不是算法上的原因,是因为节点和线太多,像素点不够

结果:这里写图片描述

画图中出现中文问题的解决方案:
这里写链接内容

                **(物品-用户    偏好聚类的实现)**
# --coding:utf-8--
import clusters

def tanimoto(v1,v2):
    c1,c2,shr = 0,0,0
    for i in range(len(v1)):
         if v1[i]!=0:
             c1+=1
         if v2[i]!=0:
             c2+=1
         if v1[i]!=0 and v2[i]!=0:
             shr+=1
    return 1.0 - (float(shr) / (c1 + c2 - shr))

wants, people,data = clusters.readfile('zebo.txt')
print "用户想要物品的总数量: %d" % len(data)
print "用户数:%d" % len(data[0])
#实现物品的聚类
clust = clusters.hcluster(data,distancefunc=tanimoto)
clusters.drawdendrogram(clust,wants,jpeg='zebocluster.jpg')

结果:
这里写图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Kmeans聚类算法是一种无监督学习算法,用于将数据集划分为不同的簇。它是一个迭代算法,通过计算每个数据点与簇中心的距离,将数据点分配到最近的簇中心。然后,根据分配的数据点更新簇中心。重复这个过程,直到簇中心不再变化或达到预设的迭代次数。 下面是一个使用Python实现Kmeans聚类算法的示例: ``` python import numpy as np import matplotlib.pyplot as plt # 生成随机数据 np.random.seed(0) X = np.random.randn(100, 2) # 初始化K个簇中心 K = 3 centers = X[np.random.choice(len(X), K, replace=False)] # 迭代聚类 for i in range(10): # 计算每个数据点最近的簇中心 distances = np.linalg.norm(X[:, np.newaxis, :] - centers, axis=2) labels = np.argmin(distances, axis=1) # 更新簇中心 for k in range(K): centers[k] = np.mean(X[labels == k], axis=0) # 可视化聚类结果 colors = ['r', 'g', 'b'] for k in range(K): plt.scatter(X[labels == k, 0], X[labels == k, 1], c=colors[k]) plt.scatter(centers[:, 0], centers[:, 1], marker='*', s=200, c='#050505') plt.show() ``` 在这个例子中,我们生成了一个随机数据集,然后初始化了3个簇中心。然后,我们执行10次迭代,计算每个数据点最近的簇中心,并根据分配的数据点更新簇中心。最后,我们可视化聚类结果,其中每个簇用不同的颜色表示,簇中心用星号表示。 Kmeans聚类算法是一种简单有效的聚类算法,但它有一些缺点。例如,它需要预先指定簇的数量K,这可能不是很容易确定。此外,它对初始簇中心的选择很敏感,可能会导致陷入局部最优解。因此,在实际应用中,需要对它进行改进,例如Kmeans++算法和层次聚类算法等。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值