花了好几天时间学习了文本聚类,以下记录一下这次的学习,也整理了一些这方面的资料,和大家分享一下,一起交流学习,进步在于不断总结和分享以及相互交流。

文本聚类就是把相似的文档聚集成一簇,通过把文本转换成数值进行聚类,主要分为两个部分,第一个是构建词袋,也就是TF-IDF矩阵,也叫作文档词频矩阵,这个矩阵的每行是一篇文档,每列是一个词,矩阵的某个值代表该词在某篇文档的TF-IDF权重,就是把文档中的每个词转成它在这篇文档的重要性,用TF-IDF来表达这个词的重要程度,从而用数值来替换文本。这一步非常重要,可以说它占整个文本聚类过程的五分之四。关于TF-IDF的介绍。我认为解释的比较易懂的是这篇文档:http://mp.weixin.qq.com/s?__biz=MzA3MDg0MjgxNQ==&mid=2652390921&idx=1&sn=c89606ab9a3d55387305f54a05d26fd5&chksm=84da46d9b3adcfcff0c500c82ea01d1ba3a3d4beb50354cad084863c24b3ab5978bb0d015354&mpshare=1&scene=1&srcid=03255LjRoyvBkfIFoMPxmsBt#rd,这里解释得非常简单易懂了,大家可以阅读参考,(附:这篇文章是我在一个叫 数据挖掘入门与实战的微信公众号看到的,这个公众号经常推送一些数据挖掘的文章,非常实用,感兴趣的伙伴可以关注学习。)我总结一下构建词袋的几个关键步骤,首先是分词,分词是否准确影响聚类效果,关于jieba分词可以参考这篇文章http://www.oschina.net/p/jieba/,然后是计算TF值和IDF值,最后计算TF-IDF值,构建矩阵,这就是构建词袋的过程。

我们已经知道TF-IDF的含义了,下面具体说说代码实现。一开始我不了解已经有现成的库可以直接调用函数就可以计算TF-IDF值,直接可以得到词袋,所以我一开始是自己参考一些资料,根据TF-IDF的含义,一步步编代码计算出来。当我花了很多时间不断地调代码,终于运行正确的时候,突然找到关于scikit-learn库有相应的模块直接调用函数就可以计算。所以我两种方法都试了,以下我把两个方法都介绍一下。

1、直接计算法  import jieba  import os  import pandas as pd  import numpy as np  stopw = [line.strip().decode(‘utf-8’) for line in open(u’F:/自然语言处理/stops.txt’).readlines()]#读取停用词  def del_stop_words(words,stop_words):#定义一个将分词结果过滤掉停用词的函数  result=jieba.cut(words)#分词  new_words = []  for i in result:#对分词结果进行遍历  if i not in stop_words:#如果词语不在停用词表,是我们需要的词  new_words.append(i)#将保留下来的词追加到一个新的list中  return new_words  names = [ os.path.join(u’F:/自然语言处理/document’,h) for h in os.listdir(u’F:/自然语言处理/document’) ]#主要是读取document文件夹下所有的文本文件的路径,其中os.listdir是读取文本文件的名称如‘1.txt’、‘2.txt’  posts = [ open(name).read() for name in names ]#循环读取每个文本文件的内容  docs = []  word_set = set()  以下这个循环的主要作用是获取每个文档的词表,然后把 每个文档的词表取并集,形成word_set。词表就是指该篇文档由哪些词组成。用set函数可以得到每篇文档包含的词语。  for post in posts:  doc = del_stop_words(post,stopw)  docs.append(doc)  word_set |= set(doc)  word_set = list(word_set)#将word_set转为一个list数据类型  docs_vsm = []  以下这两个循环的主要作用是计算每一篇文档的词频,并把所有文档的词频全部放在doc_vsm中,doc_vsm转换成矩阵docs_matrix,这就是一个词频矩阵,每行是一篇文档,列是相应文档里的词,矩阵的某个数值表示该词在某篇文档的频数。  for i in range(13):#我的实验数据一共13篇文档,所以遍历13次,或许有同学会问为什么不是for doc in docs,我参考的博客资料确实这么写,但是我运行测试以后发现有问题,就是最后有一个函数是计算矩阵docs_matrix每一行的和,出现为0的情况,这显然不对,不可能一篇文档的词总数为0,当我写成for i in range(13):的时候,就没有这种问题,13这个数字可以根据您测试的文档数进行更换。  temp_vector = []  for word in word_set:#遍历词表,该词表包含组成文档的所有词  temp_vector.append(docs[i].count(word) * 1.0)#计算每篇文档每个词的词频, temp_vector临时保存一篇文档的词频  docs_vsm.append(temp_vector)#将每篇文档的词频依次追加到docs_vsm数据表中  docs_matrix = np.mat(docs_vsm)  column_sum = [ float(len(np.nonzero(docs_matrix[:,i])[0])) for i in range(docs_matrix.shape[1]) ]#计算包含该词的文档数  column_sum = np.array(column_sum)#转换为数组,因为数组可以方便后面的批量除法计算  column_sum = docs_matrix.shape[0] / column_sum#用文档总数除以包含某个词的文档总数(根据idf的概念)  idf = np.log(column_sum)#取对数  idf = np.diag(idf)#将数组转换为n*n的对角矩阵  以下这个循环主要是根据前面的词频矩阵docs_matrix计算tf值,tf值是词频除以该篇文档的总词数。  for doc_v in docs_matrix:  if doc_v.sum() == 0:  doc_v = doc_v / 1  else:  doc_v = doc_v / (doc_v.sum())  tfidf = np.dot(docs_matrix,idf)#tf*idf  tfidf就是一个词袋了  以上是直接计算的方法,为了说明详细,所以写的注释有点多,为了大家看得更清晰一些,我把代码重新复制一次。  import jieba  import os  import pandas as pd  import numpy as np  stopw = [line.strip().decode(‘utf-8’) for line in open(u’F:/自然语言处理/stops.txt’).readlines()]  def del_stop_words(words,stop_words):  result=jieba.cut(words)  new_words = []  for i in result:  if i not in stop_words:  new_words.append(i)  return new_words  names = [ os.path.join(u’F:/自然语言处理/document’,h) for h in os.listdir(u’F:/自然语言处理/document’) ]  posts = [ open(name).read() for name in names ]  docs = []  word_set = set()  for post in posts:  doc = del_stop_words(post,stopw)  docs.append(doc)  word_set |= set(doc)  word_set = list(word_set)  docs_vsm = []  #print word.encode(“utf-8”)  for i in range(13):  temp_vector = []  for word in word_set:  temp_vector.append(docs[i].count(word) * 1.0)  docs_vsm.append(temp_vector)  docs_matrix = np.mat(docs_vsm)  column_sum = [ float(len(np.nonzero(docs_matrix[:,i])[0])) for i in range(docs_matrix.shape[1]) ]  column_sum = np.array(column_sum)  column_sum = docs_matrix.shape[0] / column_sum  idf = np.log(column_sum)  idf = np.diag(idf)  for doc_v in docs_matrix:  if doc_v.sum() == 0:  doc_v = doc_v / 1  else:  doc_v = doc_v / (doc_v.sum())  tfidf = np.dot(docs_matrix,idf)  2、使用scikit-learn库的feature_extraction.textTrans文本特征抽取模块中的former 和CountVectorizer 相关函数进行计算,比上面的方法简单十倍都不止,但是数据类型要必须满足它的要求,所以在使用这个方法之前要做一些特别的处理,最后形成一个词列表list,list的每个元素是一篇文档的所有词,即每篇文档的所有词构成一个向量,所有的向量构成list。以下是相关代码:  2.1计算TFIDF值之前的前期处理  import re  import os  import sys  import codecs  import jieba  stopw = [line.strip().decode(‘utf-8’) for line in open(u’F:/自然语言处理/stops.txt’).readlines()]  path=u’F:/file/’  ph=u’F:/自然语言处理/document/’  n= 1  while n<=13: #遍历每篇文档  name = “%d” % n  filename = ph + str(name) + “.txt”  resname=path+str(name)+”.txt”  source = open(filename, ‘r’)  result = codecs.open(resname, ‘w’, ‘utf-8’)  line = source.readline() #按行读取  line = line.rstrip(‘\n’)  while line!=”“: #对读取的每行数据进行分词  seglist = jieba.cut(line,cut_all=False)  newword=[]  for i in seglist:  if i not in stopw:  newword.append(i)#去停后的分词结果是以逗号分隔  output = ’ ‘.join(list(newword)) #所以要用join替换成空格拼接  result.write(output + ‘\r\n’) #将该篇文档的某一行文本分词后的结果写入新文档  line = source.readline() #循环读取该篇文档的每行文本  source.close()  result.close()  n = n + 1

result = codecs.open(u’F:/自然语言处理/document/all.txt’, ‘w’, ‘utf-8’)  num = 1  while num <= 13:  name = “%d” % num  fileName = path + str(name) + “.txt”  source = open(fileName, ‘r’)  line = source.readline()  line = line.strip(‘\n’) #去除回车换行符,让所有的词形成一行  line = line.strip(‘\r’)  while line!=”“:  line = line.replace(‘\n’,’ ‘)  line = line.replace(‘\r’,’ ‘) #去除回车换行符,让所有的词形成一行  result.write(line+ ’ ‘) #将每一行写入一个文档并用空格分隔  line = source.readline()  source.close()  num = num + 1  result.close()

主要思路是读取每篇文档进行分词,分词以后将分词结果分别写到新的文本文件中去,我原始文档有13个,最后也会有相应的13个分词结果文件,接着再读取每个分词结果文件到python中,再依次写到一个文件中,这个文件就包含了所有文档的分词结果,这个文件每一行就是一篇文档的分词结果,我这里测试文档是13篇,那么这个文件就只有13行数据,必须这样,否则后面使用函数计算TFIDF会出错。  2.2正式进行计算TF-IDF值  from sklearn.feature_extraction.text import TfidfTransformer  from sklearn.feature_extraction.text import CountVectorizer  corpus = []  for line in open(u’F:/自然语言处理/document/all.txt’, ‘r’).readlines():  #print line  corpus.append(line.strip())#all文件就是存放所有文档分词结果的文件,一共13行,每行代表一篇文本,把它读取到corpus中  vectorizer = CountVectorizer()#将文本中的词语转换为词频矩阵 矩阵元素a[i][j] 表示j词在i类文本下的词频  transformer = TfidfTransformer() #该类会统计每个词语的tf-idf权值  tfidf = transformer.fit_transform(vectorizer.fit_transform(corpus))#第一个fit_transform是计算tf-idf 第二个fit_transform是将文本转为词频矩阵  word = vectorizer.get_feature_names() #获取词袋模型中的所有词语  weight = tfidf.toarray() #将tf-idf矩阵抽取出来,元素w[i][j]表示j词在i类文本中的tf-idf权重  weight就是tfidf矩阵  3、聚类  根据前面计算的tfidf值,我们已经把文本转换成了数值,可以直接进行聚类了。实际上为了测试效果,我使用的文本是已经分好类的,是搜狗实验室的文本数据,我分别从财经、IT、汽车三个类抽取出13篇文章,所以我可以很容易了解到聚类效果。我尝试了所有的聚类方法,聚类效果都不是很好,在其他一些作者写的关于文本聚类的文章里面,也有提到效果不是很好。根据我以前看过的文献资料,应该是最后的TFIDF矩阵是一个高维稀疏矩阵,导致聚类效果很差,解决方法就是降维,目前我还没有继续往下优化,希望对这方面有研究的朋友跟我交流,多多指导。  以下是聚类的有关代码:  from sklearn.cluster import KMeans  kmeans=KMeans(n_clusters=3)  kmeans.fit(weight)  kmeans.labels_#输出k-means聚类的结果  from sklearn import cluster  ms = cluster.MeanShift()  ms.fit_predict(weight)  two_means = cluster.MiniBatchKMeans(n_clusters=3)  two_means.fit_predict(weight)  ward = cluster.AgglomerativeClustering(n_clusters=3, linkage=’ward’)  ward.fit_predict(weight)  spectral = cluster.SpectralClustering(n_clusters=3,eigen_solver=’arpack’,affinity=”nearest_neighbors”)  spectral.fit_predict(weight)  dbscan = cluster.DBSCAN(eps=.2)  dbscan.fit_predict(weight)  affinity_propagation = cluster.AffinityPropagation()  affinity_propagation.fit_predict(weight)  从所有的运行结果看,虽然结果都不太好,总的来说k-means稍微好一些,但是我了解到谱聚类是比较适合高维数据的聚类的,实际运行效果也不好,可能我调参不对,感兴趣的同学都可以尝试一下。  以下给出我参考的几篇博客资料:  http://blog.csdn.net/eastmount/article/details/50473675  http://blog.csdn.net/yyxyyx10/article/details/63685382  这两篇博客写得很好,尤其是第一篇,里面还总结了很多文本挖掘的资料,大家可以参考。

python中文文本聚类_python进行中文文本聚类实例(TFIDF计算、词袋构建)相关推荐

  1. python中文文本分析_Python有趣|中文文本情感分析

    前言 前文给大家说了python机器学习的路径,这光说不练假把式,这次,罗罗攀就带大家完成一个中文文本情感分析的机器学习项目,今天的流程如下: 数据情况和处理 数据情况 这里的数据为大众点评上的评论数 ...

  2. python中文分词统计_python 实现中文分词统计

    总是看到别人用Python搞各种统计,前端菜鸟的我也来尝试了一把.有各种语义分析库在,一切好像并不是很复杂.不过Python刚开始看,估计代码有点丑. 一.两种中文分词开发包 thulac (http ...

  3. python分词统计词频_python 实现中文分词统计

    总是看到别人用Python搞各种统计,前端菜鸟的我也来尝试了一把.有各种语义分析库在,一切好像并不是很复杂.不过Python刚开始看,估计代码有点丑. 一.两种中文分词开发包 THULAC(THU L ...

  4. python输出文本框_python TKinter获取文本框内容的方法

    python TKinter获取文本框内容的方法 如下所示: #coding:utf-8 import urllib,urllib2 import Tkinter #导入TKinter模块 ytm=T ...

  5. python 拼音相似度_python 計算文本的相似度

    用Python計算文本的相似度 因為后期會需要用到這方面的知識,所以先提前准備准備:如何判斷網頁返回內容的相似度? 找到了幾個Python的方法和庫: 還有高大上的"TF-IDF方法&quo ...

  6. [转载] python 遍历字符串 字符_python 遍历字符串(含汉字)实例详解

    参考链接: Python字符串| rfind python 遍历字符串(含汉字)实例详解 python 遍历字符串(含汉字)实例详解 s = "中国china" for j in ...

  7. python 遍历字符串 字符_python 遍历字符串(含汉字)实例详解

    python 遍历字符串(含汉字)实例详解 python 遍历字符串(含汉字)实例详解 s = "中国china" for j in s: print j 首先一个,你这个'a'是 ...

  8. python 写入第二列_python读写Excel表格的实例代码(简单实用)

    这篇文章主要介绍了python读写Excel表格的方法,本文通过实例代码给大家介绍的非常详细,具有一定的参考借鉴价值,需要的朋友可以参考下.需要先安装两个库:pip install xlrd.pip ...

  9. python输出国际象棋棋盘_python输出国际象棋棋盘的实例分享

    国际象棋是当今国际上最流行的智力体育运动项目.青年人下棋可以锻炼思维.增强记忆力和培养坚强的意志:中年人下棋可以享受美学:老年下棋可以很好的休息娱乐.国际象棋游戏有自己的规则,需要两个人将棋子落在棋盘 ...

  10. python打印国际象棋棋盘_python输出国际象棋棋盘的实例分享

    国际象棋是当今国际上最流行的智力体育运动项目.青年人下棋可以锻炼思维.增强记忆力和培养坚强的意志:中年人下棋可以享受美学:老年下棋可以很好的休息娱乐.国际象棋游戏有自己的规则,需要两个人将棋子落在棋盘 ...

最新文章

  1. OracleDBConsoleorcl服务无法启动问题(1053错误、发生服务特定错误2)
  2. 2019研究生数学建模比赛题目
  3. zzUbuntu安装配置Qt环境
  4. 简单子串查找--strstr的使用(ZCMU1108)
  5. 介绍Android 与 GPhone的书籍
  6. 笔记本电脑清洁小记(附螺丝滑丝处理,常见意外情况)
  7. linux so_nosigpipe,TCP_NODELAY/SO_LINGER/SO_NOSIGPIPE/MSG_NOSIGNAL设置
  8. leetcode 721. 账户合并(并查集)
  9. 漫画追踪器Tracker
  10. Python学习(列表)
  11. 计算机维修高级技能,高级计算机维修工操作技能考核试卷
  12. Cesium 修改默认地球贴图的两种方式
  13. JNA释放Memory对象分配的内存
  14. 红米android10参数,红米10x5g手机参数红米10x5g手机参数有哪些
  15. [SCOI2009]粉刷匠 dp
  16. 用顺序表求集合的交集、并集和差集
  17. taskkill /im test.exe /f
  18. Oracle又裁员!工作10年,却被裁员!
  19. 团贷网爆雷启示录:事发前早有预兆 激进资本运作致败局
  20. 转 The C10K problem 中文版 - 如何处理高并发连接

热门文章

  1. Traceview命令
  2. maven依赖包快速下载
  3. ✿ iBm T60 水货入手了 满意 2005
  4. java uploadify 下载_java uploadify 实现文件上传
  5. DELL披露MacBook Pro杀手
  6. Serverless+SCF=打倒服务器,解放程序员
  7. Spring之Bean的作用域、使用外部属性文件、mchange-commons-java-0.2.11.jar下载
  8. 编译器之词法分析器(Lexical Analyzer)
  9. java做游戏前端_小游戏——金庸奇侠传(JAVA,对面向对象的进一步了解)
  10. M1 Mac YYKit 报错