实现文档聚类的总体思想:

  1. 将每个文档的关键词提取,形成一个关键词集合N;
  2. 将每个文档向量化,可以参看计算余弦相似度那一章;
  3. 给定K个聚类中心,使用Kmeans算法处理向量;
  4. 分析每个聚类中心的相关文档,可以得出最大的类或者最小的类等;

将已经分好词的文档提取关键词,统计词频:

# 计算每个文档的关键词和词频
# 关键词统计和词频统计,以列表形式返回
def Count(resfile):
t = {}
infile = open(resfile, 'r', encoding='utf-8')
i = 0
f = infile.readlines()
count = len(f)
# print(count)
infile.close()
s = open(resfile, 'r', encoding='utf-8')
while i < count:
line = s.readline()
line = line.rstrip('\n')
# print(line)
words = line.split(" ")
# print(words)
for word in words:
if word != "" and t.__contains__(word):
num = t[word]
t[word] = num + 1
elif word != "":
t[word] = 1
i = i + 1
# 按键值降序
dic = sorted(t.items(), key=lambda t: t[1], reverse=True)
s.close()
# 返回的是一篇文档的词项统计表,形式为[(word:出现次数)]
return dic

  上面的count函数统计的一篇文档的词频,如果每篇文档都需要统计则需要调用这个count函数,每调用一次就返回一个dict,给一个文档集统计词频的参考代码如下(假设有500篇文档):

def readfile():
f = open("res.txt", "w", encoding="utf-8")
# mergeword 用来记录所有文档的词项集合,不重复,其长度是用来作为文档向量维度
mergeword = []
everyDocumentDict = []
for i in range(500):
      
filedir = "D:/PythonCodingLover/PythonPro/DailyStudy/互联网项目二/CNS/"+ "CNS" +str(i)+"_C.txt"
# 将每个文档的字典写入res.txt中
dict = Count(filedir)
# everyDocumentDict记录的是每篇文档的词项统计
everyDocumentDict.append(dict)
# print(type(dict))
for j in range(len(dict)):
if dict[j][0] not in mergeword:
mergeword.append(dict[j][0]) f.close()
# 返回文档集的词项集
return mergeword,everyDocumentDict

  上面两部分可以实现将文档集里的关键词,担心是否正确可以使用简单的测试代码,如下:

# 测试文档集关键词是否正确
mergeword ,eveKeywordOfCount= readfile()
print(type(eveKeywordOfCount))
print(len(eveKeywordOfCount))
print(len(mergeword))

将每篇文档向量化,便于后面的文档聚类:

  下面这个函数将所有的文档向量一起返回,而不是一篇文档向量;

# 现在有了500个文档的总关键词和每篇文档的词项统计,所以我们现在要做的是将每篇文档向量化,维度是len(mergeword)
# 注意EveDocCount的结构是[[(),()],[(),()]],里面记录的列表是每个文档的词项统计,而括号里面的是keyword:词频 print("-------------------文档向量化开始操作-----------------")
def VectorEveryDoc(EveDocCount,mergeword):
# vecOfDoc列表记录的是每篇文档向量化后的向量列表,共有500个元素
vecOfDoc = []
# vecDoc列表记录的是一篇文档的向量模型,向量化后添加到vecOfDoc
vectorLenth = len(mergeword)
# 下面开始将500文档向量化
i = 0 while i < 500:
# EveDocCount[i]记录的是第几篇文档的词项统计
vecDoc = [0] * vectorLenth
# 测试是正确的
# print(EveDocCount[i])
for ch in range(len(EveDocCount[i])):
# termFrequence 是词项对应的频数
termFrequence = EveDocCount[i][ch][1]
# keyword是词项
keyword = EveDocCount[i][ch][0]
# 下面开始具体的向量化
j = 0
while j < vectorLenth:
if keyword == mergeword[j]:
# 这里是J 而不是 I ,写错了就很容易出错了
vecDoc[j] = termFrequence
break
else:
j = j + 1
vecOfDoc.append(vecDoc)
i = i+ 1
# 返回500个文档的文档向量
return vecOfDoc print("-------------------文档向量化操作结束-----------------")

向量化结束之后,便需要计算余弦距离(也可以使用其他距离,例如欧几里得距离):

  说明:一个文档集的关键词可能有很多,为了方便后面的计算,引入科学计算包numpy,示例代码如下:

  

# 导入科学计算包
import numpy as np

  而后将500个文档向量传给numpy的数组,构造矩阵,示例代码如下:

resultVec = VectorEveryDoc(eveKeywordOfCount,mergeword)
vecDate = np.array(resultVec)

  之后便计算余弦相似度,这里和前面写的余弦距离相似度计算类似,不同的是使用了nmupy数组,注意其中的矩阵乘法,示例代码如下:

# 计算余弦距离
def CalConDis(v1,v2):
lengthVector = len(v1)
# 计算出两个向量的乘积
# 将v2变换,转置矩阵v2
v2s =v2.T
B = np.dot(v1,v2s)
# 计算两个向量的模的乘积
v1s = v1.T
A1 = np.dot(v1,v1s)
A2 = np.dot(v2,v2s)
A = math.sqrt(A1) * math.sqrt(A2)
# print('相似度 = ' + str(float(B) / A))
resdis = format(float(B) / A,".3f")
return float(resdis)

Kmeans聚类算法实现文档聚类:

随机产生K个聚类中心点:

# 随机选取中心点,dateSet是m * n矩阵,K是要指定的聚类的个数
def createRandomCent(dateSet,k):
# 返回整个矩阵的列的列数
n = np.shape(dateSet)[1]
# 创建一个k * n 的零矩阵
centroids = np.mat(np.zeros((k, n)))
# 随机产生k个中心点
for j in range(n):
minJ = min(dateSet[:, j])
rangeJ = float(max(dateSet[:, j]) - minJ)
centroids[:, j] = np.mat(minJ + rangeJ * np.random.rand(k, 1))
# 返回随机产生的k个中心点
return centroids

Kmeans算法按照随机产生的聚类中心开始聚类,返回的一个矩阵:

countclu = 1
# 具体的Kmeans算法实现
# dateset是指500个文档的向量集合(500 * length),dis用的是余弦距离,k是给定的k个聚类中心,createCent是随机生成的K个初始中心
def dfdocKmeansCluster(dateset,k,discos = CalConDis,createCent = createRandomCent):
# docCount 记录的总共有多少个样本,既矩阵的行数
docCount = np.shape(dateset)[0]
# 在构建一个500 * 2的0矩阵,用来存放聚类信息
docCluster = np.mat(np.zeros((docCount,2))) # 初始化K个聚类中心
centerOfCluster = createCent(dateset,k)
# clusterFlag用来判定聚类是否结束
clusterFlag = True
while clusterFlag:
clusterFlag = False
for each in range(docCount):
# 将最大余弦距离初始化成一个负数
maxCosDis = -100
# 文档索引
minIndex = -1
# 找到每篇文档距离最近的中心
for i in range(k):
# 计算每个文档到中心点的余弦相似度,
global countclu
countclu = countclu+ 1
print("已经聚类第" + str(countclu) + "次")
distcosOfDocToDoccenter = discos(centerOfCluster[i, :], dateset[each, :])
# 选择余弦距离最大的一个中心
if distcosOfDocToDoccenter > maxCosDis: maxCosDis = distcosOfDocToDoccenter
minIndex = i
if docCluster[each, 0] != minIndex:
# 如果没到最优方案则继续聚类
clusterFlag = True
# 第1列为所属中心,第2列为余弦距离
docCluster[each, :] = minIndex, maxCosDis
# 打印随机产生的中心点
print(centerOfCluster) # 更改聚类中心点
for cent in range(k):
ptsInClust = dateset[np.nonzero(docCluster[:, 0].A == cent)[0]]
centerOfCluster[cent, :] = np.mean(ptsInClust, axis=0)
# 返回K个中心点,
return centerOfCluster,docCluster

  这里返回的一个500*2的矩阵,第一列是聚类中心,第二列是和中心的余弦距离,索引就是文档编号;

  如果需要得出具体的类有几篇文档等问题,则需要对返回的矩阵进行分析(注意是numpy矩阵);

  程序到了这里。就基本上结束了;

Kmeans文档聚类算法实现之python的更多相关文章

  1. 相似文档查找算法之 simHash 简介及其 java 实现 - leejun_2005的个人页面 - 开源中国社区

    相似文档查找算法之 simHash 简介及其 java 实现 - leejun_2005的个人页面 - 开源中国社区 相似文档查找算法之 simHash 简介及其 java 实现

  2. AutoPy首页、文档和下载 - 跨平台的Python GUI工具包 - 开源中国社区

    AutoPy首页.文档和下载 - 跨平台的Python GUI工具包 - 开源中国社区 AutoPy是一个简单跨平台的 Python GUI工具包,可以控制鼠标,键盘,匹配颜色和屏幕上的位图.使用纯A ...

  3. k-means和iosdata聚类算法在生活案例中的运用

    引言:聚类是将数据分成类或者簇的过程,从而使同簇的对象之间具有很高的相似度,而不同的簇的对象相似度则存在差异.聚类技术是一种迭代重定位技术,在我们的生活中也得到了广泛的运用,比如:零件分组.数据评价. ...

  4. 【机器学习】:Kmeans均值聚类算法原理(附带Python代码实现)

    这个算法中文名为k均值聚类算法,首先我们在二维的特殊条件下讨论其实现的过程,方便大家理解. 第一步.随机生成质心 由于这是一个无监督学习的算法,因此我们首先在一个二维的坐标轴下随机给定一堆点,并随即给 ...

  5. 用Python做SVD文档聚类---奇异值分解----文档相似性----LSI(潜在语义分析)

    转载请注明出处:电子科技大学EClab——落叶花开http://www.cnblogs.com/nlp-yekai/p/3848528.html SVD,即奇异值分解,在自然语言处理中,用来做潜在语义 ...

  6. (数据科学学习手札13)K-medoids聚类算法原理简介&Python与R的实现

    前几篇我们较为详细地介绍了K-means聚类法的实现方法和具体实战,这种方法虽然快速高效,是大规模数据聚类分析中首选的方法,但是它也有一些短板,比如在数据集中有脏数据时,由于其对每一个类的准则函数为平 ...

  7. 聚类算法总结以及python代码实现

    一.聚类(无监督)的目标 使同一类对象的相似度尽可能地大:不同类对象之间的相似度尽可能地小. 二.层次聚类 层次聚类算法实际上分为两类:自上而下或自下而上.自下而上的算法在一开始就将每个数据点视为一个 ...

  8. 相似文档查找算法之 simHash及其 java 实现

    传统的 hash 算法只负责将原始内容尽量均匀随机地映射为一个签名值,原理上相当于伪随机数产生算法.产生的两个签名,如果相等,说明原始内容在一定概 率 下是相等的:如果不相等,除了说明原始内容不相等外 ...

  9. TF-IDF词频逆文档频率算法

    一.简介 1.RF-IDF[term frequency-inverse document frequency]是一种用于检索与探究的常用加权技术. 2.TF-IDF是一种统计方法,用于评估一个词对于 ...

随机推荐

  1. 高性能MYSQL(查询优化)

    1.对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2.应尽量避免在 where 子句中对字段进行 null 值判断,否则将导致引擎放弃使用索 ...

  2. React 父/子窗体参数传递

    1.父窗体 import Modal from './Modal' onModalRef = ref => { this.modal = ref } onCallback = msg => ...

  3. Shadowmap简易实现

    之前一直没有自己实现过阴影,只是概念上有所了解,这次通过Demo进行实际编写操作. 总的来说没有什么可以优化的,倒是对于窗户这种可用面片代替的物体似乎能优化到贴图上,之前arm有个象棋屋的demo做过 ...

  4. vue/react/angular开发的css架构思考

    前端开发现在已经从传统的后端web多页面开发模式转向前端单页SPA开发模式,而vuejs/react/angular则是开发SPA非常优秀的前端框架.组件化开发由react最早提出,vuejs后发优势 ...

  5. 虚拟化x86的三种途径

    虚拟化x86的三种途径 作者:缪天翔链接:https://www.zhihu.com/question/20145026/answer/34527331 x86上的全系统虚拟化有三种主要的途径: 二进 ...

  6. uni-app悬浮框模板

    1. uni-app悬浮框模板 1.1. 目标 模仿饿了吗app的悬浮框效果,即上移过程中,中间的某个组件框到顶部后不再上移,呈类似置顶的效果 1.2. 问题 中间遇到fixed固定组件导致flex失 ...

  7. js学习之堆栈内存

    **栈内存** >基本数据类型值是直接存放在栈内存中的 栈内存中的变量一般都是已知大小或者有范围上限的,算作一种简单存储.而堆内存存储的对象类型数据对于大小这方面,一般都是未知的.个人认为,这也 ...

  8. HTML 注释 和 实体字符

    一.注释 在HTML中还有一种特殊的标签——注释标签.如果需要在HTML文档中添加一些便于阅读和理解但又不需要显示在页面中的注释文字,就需要使用注释标签. 注释内容不会显示在浏览器窗口中,但是作为HT ...

  9. python 之 sys.stdout输出不换行

    在处理程序打进度条时,希望不换行显示进度,可以使用sys.stdout相关函数来进行处理. 1.print 输出不换行 首先可以使用print函数来整体输入,利用,结尾就可以在同一行内显示: # py ...

  10. GoLang 中用 MongoDB Watch 监听指定字段的变化

    需要 MongoDB 3.6 及以上, 需要 ReplicaSet 模式. 监听一个字段的变化: func watch(coll *mongo.Collection) { match := bson. ...