[python] Kmeans文本聚类算法+PAC降维+Matplotlib显示聚类图像

前言


本文主要讲述以下几点:
        1.通过scikit-learn计算文本内容的tfidf并构造N*M矩阵(N个文档 M个特征词);
        2.调用scikit-learn中的K-means进行文本聚类;
        3.使用PAC进行降维处理,每行文本表示成两维数据;
        4.最后调用Matplotlib显示聚类效果图。

输入


文本输入是读取本地的01_All_BHSpider_Content_Result.txt文件,里面包括1000行数据,其中001~400行为景区、401~600为动物、601~800为人物明星、801~1000为国家地理文本内容(百度百科摘要信息)。
该内容可以自定义爬虫进行爬取,同时分词采用Jieba进行。

 免费下载包括代码py文件和01_All_BHSpider_Content_Result.txt。
下载地址:http://download.csdn.net/detail/eastmount/9410810
 



源代码

代码如下,详见注释和后面的学习笔记推荐:

[python] view plain copy

  1. # coding=utf-8  
  2. """ 
  3. Created on 2016-01-16 @author: Eastmount
  4. 输入:打开txt 对应1000个文本
  5. 001~400 5A景区 401~600 动物 601~800 人物 801~1000 国家 
  6. 输出:txt tfidf值聚类图形 1000个类标 
  7. 参数:weight权重这是一个重要参数 
  8. """
  9. importtime            
  10. importre            
  11. importos    
  12. importsys  
  13. importcodecs  
  14. importshutil  
  15. importnumpy as np  
  16. importmatplotlib  
  17. importscipy  
  18. importpyplot as plt  
  19. fromsklearn importfeature_extraction    
  20. fromfeature_extraction.text importTfidfTransformer    
  21. fromfeature_extraction.text importCountVectorizer  
  22. fromfeature_extraction.text importHashingVectorizer   
  23. if__name__ == "__main__":  
  24. #########################################################################
  25. #                           第一步计算TFIDF  
  26. #文档预料空格连接  
  27. corpus = []  
  28. #读取预料一行预料为一个文档  
  29. forline in open('01_All_BHSpider_Content_Result.txt', 'r').readlines():  
  30. #print line
  31. append(line.strip())  
  32. #print corpus
  33. #参考: http://blog.csdn.net/abcjennifer/article/details/23615947
  34. #vectorizer = HashingVectorizer(n_features = 4000)
  35. #将文本中的词语转换为词频矩阵矩阵元素a[i][j] 表示j词在i类文本下的词频  
  36. vectorizer = CountVectorizer()  
  37. #该类会统计每个词语的tf-idf权值
  38. transformer = TfidfTransformer()  
  39. #第一个fit_transform是计算tf-idf 第二个fit_transform是将文本转为词频矩阵
  40. tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))  
  41. #获取词袋模型中的所有词语  
  42. word = vectorizer.get_feature_names()  
  43. #将tf-idf矩阵抽取出来,元素w[i][j]表示j词在i类文本中的tf-idf权重
  44. weight = tfidf.toarray()  
  45. #打印特征向量文本内容
  46. print'Features length: ' + str(len(word))  
  47. resName = "BHTfidf_Result.txt"
  48. result = codecs.open(resName, 'w', 'utf-8')  
  49. forin range(len(word)):  
  50. write(word[j] + ' ')  
  51. write('\r\n\r\n')  
  52. #打印每类文本的tf-idf词语权重,第一个for遍历所有文本,第二个for便利某一类文本下的词语权重  
  53. forin range(len(weight)):  
  54. #print u"-------这里输出第", i, u"类文本的词语tf-idf权重------"  
  55. forin range(len(word)):  
  56. #print weight[i][j],
  57. write(str(weight[i][j]) + ' ')  
  58. write('\r\n\r\n')  
  59. close()  
  60. ########################################################################
  61. #                               第二步聚类Kmeans  
  62. print'Start Kmeans:'  
  63. fromcluster importKMeans  
  64. clf = KMeans(n_clusters=4)   #景区动物 人物 国家  
  65. s = clf.fit(weight)  
  66. prints  
  67. '''''
  68. print 'Start MiniBatchKmeans:'
  69. from sklearn.cluster import MiniBatchKMeans
  70. clf = MiniBatchKMeans(n_clusters=20)
  71. s = clf.fit(weight)
  72. print s
  73. '''
  74. #中心点
  75. print(clf.cluster_centers_)  
  76. #每个样本所属的簇
  77. label = []               #存储1000个类标4个类  
  78. print(clf.labels_)  
  79. i = 1  
  80. whilei <= len(clf.labels_):  
  81. printi, clf.labels_[i-1]  
  82. append(clf.labels_[i-1])  
  83. i = i + 1  
  84. #用来评估簇的个数是否合适,距离越小说明簇分的越好,选取临界点的簇个数137281791
  85. print(clf.inertia_)  
  86. ########################################################################
  87. #                               第三步图形输出 降维  
  88. fromdecomposition importPCA  
  89. pca = PCA(n_components=2)             #输出两维
  90. newData = pca.fit_transform(weight)   #载入N维
  91. printnewData  
  92. #5A景区
  93. x1 = []  
  94. y1 = []  
  95. i=0  
  96. whilei<400:  
  97. append(newData[i][0])  
  98. append(newData[i][1])  
  99. i += 1  
  100. #动物
  101. x2 = []  
  102. y2 = []  
  103. i = 400  
  104. whilei<600:  
  105. append(newData[i][0])  
  106. append(newData[i][1])  
  107. i += 1  
  108. #人物
  109. x3 = []  
  110. y3 = []  
  111. i = 600  
  112. whilei<800:  
  113. append(newData[i][0])  
  114. append(newData[i][1])  
  115. i += 1  
  116. #国家
  117. x4 = []  
  118. y4 = []  
  119. i = 800  
  120. whilei<1000:  
  121. append(newData[i][0])  
  122. append(newData[i][1])  
  123. i += 1  
  124. #四种颜色红 绿 蓝 黑  
  125. plot(x1, y1, 'or')  
  126. plot(x2, y2, 'og')  
  127. plot(x3, y3, 'ob')  
  128. plot(x4, y4, 'ok')  
  129. show()  




输出结果


采用Kmeans中设置类簇数为4,分别表示景区、动物、明星和国家。
其中运行结果如下图所示,包括17900维tfidf特征向量: 


聚类输出结果如下图所示:其中"红-景区 绿-动物 蓝-人物 黑-国家"。由于数据集比较小,文本聚类效果还是很明显的,而LDA算法是计算每个主题分布的算法,推荐你也去学习下。

[python] Kmeans文本聚类算法+PAC降维+Matplotlib显示聚类图像_第1张图片


性能评估


这里我想结合文本聚类简单叙述下最常用的评估方法:
        正确率 Precision = 正确识别的个体总数 /  识别出的个体总数
        召回率 Recall = 正确识别的个体总数 /  测试集中存在的个体总数
        F值 F-measure = 正确率 * 召回率 * 2 / (正确率 + 召回率)

由于"clf.labels_"会返回聚类每个样本所属的簇,比如1000行数据,就会返回1000个label值。同时,clf = KMeans(n_clusters=4)设置了类簇为4,故每个值对应在0、1、2、3中的一个,统计结果如下:

[python] Kmeans文本聚类算法+PAC降维+Matplotlib显示聚类图像_第2张图片

其中以世界国家为例,label1数目为198,同时识别出的个体数=198(世界国家)+2(动物)=200,故:
        准确率=198/200=0.990
其中动物里面有两个聚类到了世界国家中。而召回率我以人物明星为例,因为知道测试集中601~800这200个数据对应人物明星,故测试集中存在个体数为200,而正确识别数目为185个,故:
        召回率=185/200=0.925
最后计算F值即可。同时可以计算宏平均聚类准确率(Macro-Prec)和宏平均召回率(Macro-Rec)。




总结及推荐学习资料

代码中有几个问题我没有实现,包括:
        (1) 使用HashingVectorizer(n_features = n)设置维数,如何选择更合理的特征;
        (2) 调用plt.legend([plot1, plot2, plot3, plot4], (u'景区', u'动物', u'明星', u'国家') )
报错"AttributeError: 'NoneType' object has no attribute 'tk'";
        (3) sklearn其它聚类算法以及设置聚类中心点。

但是对那些刚接触Python聚类算法的同学 ,这篇文章还是有一定帮助的!

你可能感兴趣的:(python,kmeans)