分级聚类是通过连续不断地将最为相似的群组两两合并,来构造出一个群组的层级结构。其中的每个群组都是从单一元素开始的。如图所示:

元素的相似程序是通过它们的相对位置来体现的,距离越近越相似。两两合并,直到合并最后两个群组。

聚类是无监督学习的一个例子。与神经网络或决策树不同,无监督学习算法不是利用带有正确答案的样本数据进行“训练”。它们的目的是要在一组数据中找寻某种结构,而这些数据本身不是我们要找的答案。聚类算法的目标是采集数据,然后从中找出不同的群组。

下面我就利用分级聚类算法对iteye和csdn的博客进行分类。

1.准备数据。利用feedparser解析博客rss订阅源,利用jieba中文拆词获取关键词及其出现次数。

2.合并数据。利用皮尔逊相关度算法计算数据的相似度,两两合并相似度最小的数组,直到只剩下一个数级为止。

3.绘制树状图。利用PIL将合并后的数据做成图片,以此清晰地展现数据结构。

下面开始第一步:

安装feedparser.

feedparser是一个python库,可以用以分析RSS和Atom的订阅源。下载地址https://code.google.com/p/feedparser/downloads/list。解压后在feedparser目录下命令行输入python setup.py install。

下面去寻找一些iteye和csdn博客的订阅源。下面是我随便找的10个,写入到feedlist.txt中。

Python代码  
  1. <span>http://blog.csdn.net/xxg2810/rss/list
  2. http://lobert.iteye.com/rss
  3. http://blog.csdn.net/lfsf802/rss/list
  4. http://blog.csdn.net/david_lv/rss/list
  5. http://blog.csdn.net/m13666368773/rss/list
  6. http://blog.csdn.net/shulianghan/rss/list
  7. http://blog.csdn.net/withiter/rss/list
  8. http://blog.csdn.net/lfsf802/rss/list
  9. http://blog.csdn.net/pan_tian/rss/list
  10. http://blog.csdn.net/beijiguangyong/rss/list</span>

因为我们在天朝,所以用的当然是中文,因此需要一个分词库,这里我使用jieba(开始使用的是mmseg-cpp,但在实际运行中会出现卡死的现象)。

下载地址:https://github.com/fxsjy/jieba,解压后将文件夹直接放到python默认库地址即可。

准备工作完毕,开始mark了。

Python代码  
  1. #encoding=utf-8           #注意编码
  2. import sys
  3. from imp import reload
  4. reload(sys)
  5. import feedparser
  6. import re
  7. import jieba
  8. # Returns title and dictionary of word counts for an RSS feed
  9. def getwordcounts(url):
  10. # Parse the feed
  11. d=feedparser.parse(url)
  12. wc={}
  13. # Loop over all the entries
  14. for e in d.entries:
  15. if 'summary' in e: summary=e.summary
  16. else: summary=e.description
  17. # Extract a list of words
  18. words=getwords(e.title+' '+summary)
  19. for word in words:
  20. wc.setdefault(word,0)
  21. wc[word]+=1
  22. return d.feed.title,wc
  23. def getwords(html):
  24. # Remove all the HTML tags
  25. txt=re.compile(r'<[^>]+>').sub('',html)
  26. algor = jieba.cut(txt,cut_all=True)
  27. # Split words by all non-alpha characters
  28. # words=re.compile(r'[^A-Z^a-z]+').split(txt)
  29. # Convert to lowercase
  30. return [tok.lower() for tok in algor if tok!='']
  31. # return [word.lower() for word in words if word!='']
  32. apcount={}
  33. wordcounts={}
  34. feedlist=[line for line in open('feedlist.txt')]
  35. for feedurl in feedlist:
  36. try:
  37. title,wc=getwordcounts(feedurl)
  38. wordcounts[title]=wc
  39. for word,count in wc.items():
  40. apcount.setdefault(word,0)
  41. if count>1:
  42. apcount[word]+=1
  43. except:
  44. print 'Failed to parse feed %s' % feedurl
  45. wordlist=[]
  46. for w,bc in apcount.items():
  47. frac=float(bc)/len(feedlist)
  48. if frac>0.1 and frac<0.5:       //因为像“我”这样的单词几乎到处都是,而像“PYTHON”这样的单词则有可能只出现在个别博客中,所以通过只选择介于某个百分比范围内的单词,我们可以减少需要考查的单词总量。我们这里将1/10为下界,5/10为上界。
  49. wordlist.append(w)
  50. out=open('blogdata1.txt','w')
  51. out.write('Blog')
  52. for word in wordlist: out.write('\t%s' % word.strip())
  53. out.write('\n')
  54. for blog,wc in wordcounts.items():
  55. out.write(blog)
  56. for word in wordlist:
  57. if word in wc: out.write('\t%d' % wc[word])
  58. else: out.write('\t0')
  59. out.write('\n')

程序运行后数据保存到文件中,我这里跑了40s,如无意外,出现的是一个表格。其中的每一列对应一个单词,每一行对应一个博客。表格的数字就是单词出现在博客中的次数。


由于宽度原因,因此只截取部分数据。

到此,数据准备完毕。

第二步:mark

Python代码  
  1. def readfile(filename):
  2. lines=[line for line in file(filename)]
  3. # First line is the column titles
  4. colnames=lines[0].strip().split('\t')[1:]
  5. rownames=[]
  6. data=[]
  7. for line in lines[1:]:
  8. p=line.strip().split('\t')
  9. # First column in each row is the rowname
  10. rownames.append(p[0])
  11. # The data for this row is the remainder of the row
  12. data.append([float(x) for x in p[1:]])
  13. return rownames,colnames,data
  14. from math import sqrt
  15. def pearson(v1,v2):
  16. # Simple sums
  17. sum1=sum(v1)
  18. sum2=sum(v2)
  19. # Sums of the squares
  20. sum1Sq=sum([pow(v,2) for v in v1])
  21. sum2Sq=sum([pow(v,2) for v in v2])
  22. # Sum of the products
  23. pSum=sum([v1[i]*v2[i] for i in range(len(v1))])
  24. # Calculate r (Pearson score)
  25. num=pSum-(sum1*sum2/len(v1))
  26. den=sqrt((sum1Sq-pow(sum1,2)/len(v1))*(sum2Sq-pow(sum2,2)/len(v1)))
  27. if den==0: return 0
  28. return 1.0-num/den
  29. class bicluster:
  30. def __init__(self,vec,left=None,right=None,distance=0.0,id=None):
  31. self.left=left
  32. self.right=right
  33. self.vec=vec
  34. self.id=id
  35. self.distance=distance
  36. def hcluster(rows,distance=pearson):
  37. distances={}
  38. currentclustid=-1
  39. # Clusters are initially just the rows
  40. clust=[bicluster(rows[i],id=i) for i in range(len(rows))]
  41. while len(clust)>1:
  42. lowestpair=(0,1)
  43. closest=distance(clust[0].vec,clust[1].vec)
  44. # loop through every pair looking for the smallest distance
  45. for i in range(len(clust)):
  46. for j in range(i+1,len(clust)):
  47. # distances is the cache of distance calculations
  48. if (clust[i].id,clust[j].id) not in distances:
  49. distances[(clust[i].id,clust[j].id)]=distance(clust[i].vec,clust[j].vec)
  50. d=distances[(clust[i].id,clust[j].id)]
  51. if d<closest:
  52. closest=d
  53. lowestpair=(i,j)
  54. # 计算两个聚类的平均值
  55. mergevec=[
  56. (clust[lowestpair[0]].vec[i]+clust[lowestpair[1]].vec[i])/2.0
  57. for i in range(len(clust[0].vec))]
  58. # create the new cluster
  59. newcluster=bicluster(mergevec,left=clust[lowestpair[0]],
  60. right=clust[lowestpair[1]],
  61. distance=closest,id=currentclustid)
  62. # 不在原始集合中的聚类,其id为负数
  63. currentclustid-=1
  64. del clust[lowestpair[1]]
  65. del clust[lowestpair[0]]
  66. clust.append(newcluster)
  67. return clust[0]

第三步;借助树状图,我们可以更加理解聚类

安装PIL,由于我安装了python(x,y),里面已经包含了PIL,因此无需安装。

Python代码  
  1. from PIL import Image,ImageDraw,ImageFont
  2. #计算聚类总体的高度
  3. def getheight(clust):
  4. # Is this an endpoint? Then the height is just 1
  5. if clust.left==None and clust.right==None: return 1
  6. # Otherwise the height is the same of the heights of
  7. # each branch
  8. return getheight(clust.left)+getheight(clust.right)
  9. #计算误差
  10. def getdepth(clust):
  11. # The distance of an endpoint is 0.0
  12. if clust.left==None and clust.right==None: return 0
  13. #一个枝节点的距离等于左右两侧分支中距离较大者加上该枝节点自身的距离
  14. return max(getdepth(clust.left),getdepth(clust.right))+clust.distance
  15. #画图
  16. def drawdendrogram(clust,labels,jpeg='clusters.jpg'):
  17. # height and width
  18. h=getheight(clust)*30
  19. w=1200
  20. depth=getdepth(clust)
  21. # width is fixed, so scale distances accordingly
  22. scaling=float(w-350)/depth
  23. # Create a new image with a white background
  24. img=Image.new('RGB',(w,h),(255,255,255))
  25. draw=ImageDraw.Draw(img)
  26. draw.line((0,h/2,10,h/2),fill=(255,0,0))
  27. # Draw the first node
  28. drawnode(draw,clust,10,(h/2),scaling,labels)
  29. img.save(jpeg,'JPEG')
  30. def drawnode(draw,clust,x,y,scaling,labels):
  31. if clust.id<0:
  32. h1=getheight(clust.left)*20
  33. h2=getheight(clust.right)*20
  34. top=y-(h1+h2)/2
  35. bottom=y+(h1+h2)/2
  36. # Line length
  37. ll=clust.distance*scaling
  38. # Vertical line from this cluster to children
  39. draw.line((x,top+h1/2,x,bottom-h2/2),fill=(255,0,0))
  40. # Horizontal line to left item
  41. draw.line((x,top+h1/2,x+ll,top+h1/2),fill=(255,0,0))
  42. # Horizontal line to right item
  43. draw.line((x,bottom-h2/2,x+ll,bottom-h2/2),fill=(255,0,0))
  44. # Call the function to draw the left and right nodes
  45. drawnode(draw,clust.left,x+ll,top+h1/2,scaling,labels)
  46. drawnode(draw,clust.right,x+ll,bottom-h2/2,scaling,labels)
  47. else:
  48. font = ImageFont.truetype('simsun.ttc',24)
  49. # If this is an endpoint, draw the item label
  50. draw.text((x+5,y-7),unicode(labels[clust.id],'utf-8'),(0,0,0),font=font)

最后我们写个test跑下

Python代码  
  1. #encoding=utf-8
  2. import clusters #里面包含了第二,三步的代码
  3. blognames,words,data = clusters.readfile('blogdata1.txt')
  4. clust = clusters.hcluster(data)
  5. clusters.printclust(clust,labels=blognames)
  6. clusters.drawdendrogram(clust,blognames,jpeg='blogclust.jpg')

生成图片:

分级聚类算法(集体智慧编程)相关推荐

  1. 《集体智慧编程》读书笔记2

    最近重读<集体智慧编程>,这本当年出版的介绍推荐系统的书,在当时看来很引领潮流,放眼现在已经成了各互联网公司必备的技术. 这次边阅读边尝试将书中的一些Python语言例子用C#来实现,利于 ...

  2. 《集体智慧编程》——第一章导读

    为什么80%的码农都做不了架构师?>>>    什么是集体智慧 其含义是指:为了长早新的想法,而将一群人的行为.偏好或思想组合在一起. 完成这项工作的一种最为基础的方法,便是使用调查 ...

  3. 《集体智慧编程》读书笔记10

    最近重读<集体智慧编程>,这本当年出版的介绍推荐系统的书,在当时看来很引领潮流,放眼现在已经成了各互联网公司必备的技术. 这次边阅读边尝试将书中的一些Python语言例子用C#来实现,利于 ...

  4. 《集体智慧编程》读书笔记4

    最近重读<集体智慧编程>,这本当年出版的介绍推荐系统的书,在当时看来很引领潮流,放眼现在已经成了各互联网公司必备的技术. 这次边阅读边尝试将书中的一些Python语言例子用C#来实现,利于 ...

  5. 《集体智慧编程》数学公式

    这篇博客的目的主要是为了记录这些公式,取自原书附录B. 1.欧几里得距离(Euclidean Distance) 用途:计算距离,衡量相似度 公式: 代码实现: def euclidean(p, q) ...

  6. 《集体智慧编程》笔记(1 / 12):集体智慧导言

    文章目录 什么是集体智慧 什么是机器学习 机器学习的局限性 真实生活中的例子 学习型算法的其他用途 小结 Netflix, Google都适用了先进算法,将来自不同人群的数据加以组合,进而得出新的结论 ...

  7. 集体智慧编程——优化搜索算法:爬山法,模拟退火算法,遗传算法-Python实现

    在优化问题中,有两个关键点 代价函数:确定问题的形式和规模之后,根据不同的问题,选择要优化的目标.如本文涉及的两个问题中,一个优化目标是使得航班选择最优,共计12个航班,要使得总的票价最少且每个人的等 ...

  8. 集体智慧编程学习笔记——第一讲

    1. 用户相似度评价 (1)欧几里德距离 (2)皮尔逊相关度评价 (3)jaccard 系数 (4)曼哈顿距离算法 转载于:https://www.cnblogs.com/gylhaut/p/9377 ...

  9. 集体智慧编程 - 构建价格模型

    主要介绍了kNN算法,和相关的权重分配,按比例缩放和绘制分布图等,框图如下, 转载于:https://www.cnblogs.com/zhouweihit/p/4117533.html

最新文章

  1. js隐藏或显示某区域
  2. 基于 Jenkins 快速搭建持续集成环境--转
  3. 今天的我也不太清楚的即时通讯
  4. deap软件结果分析_绿港科技之窗:基于InDel标记的黄瓜种质资源遗传多样性分析...
  5. kubernetes权威指南学习遇见的问题以及意见之二:Permission denied
  6. 蓝屏:微软撤回 Windows 8.1 八月更新等4个补丁
  7. matlab 常用函数或符号用法总结
  8. CMD命令查看IP地址
  9. idea创建svn分支
  10. 怎么在计算机中添加电脑桌面,如何在电脑正在使用的主题中添加桌面背景图片...
  11. Python使用阿里API进行身份证识别
  12. HTML中属性问题以及通信问题总结
  13. vue-i18n 用法
  14. 【CSS 形状 (Shapes)】
  15. Socialbook告诉你网红营销和ROI的关系~
  16. 小米笔记本windows插入电源无法充满电问题处理
  17. 建设银行检测到设备已被Root的判断
  18. Vue 点击复制粘贴文本
  19. 简单的病毒编程代码Python,利用python编写勒索病毒
  20. AutoCAD Civil 3D-部件编辑器制作参数化多级边坡

热门文章

  1. ubuntu下rsync两个服务器同步文件
  2. 【CSS 遮挡和剪切属性 Masking】
  3. excel对不同岗位进行名次排序
  4. windows7台式计算机网线连接,win7台式机连接wifi的方法步骤详解(2)
  5. 【求职】作业帮 Java 方向面经
  6. iphone8 android传文件,如何从iPhone或Android将数据传输到新的iPhone 8
  7. 创建微服务架构的步骤_如何快速搭建一个微服务架构?
  8. Vue2响应式实现原理和解析
  9. Python pyautogui支持的按键的字符
  10. linux安装系统如何查看硬盘,如何检查Linux系统服务器的硬盘是SSD还是HDD?