赞
踩
聚类常规方法,分一下几步:
第一部分内容,本人暂不祥说,核心的内容,大概如下把
- for line in file.readlines():
- words = jieba.cut(line)
- for word in words:
- # print(word)
- if word not in stopword:
- output.write(word + " ")
接下来是将上述处理过的文档,进行向量化,此处,我选择的是doc2vec,即是document to vector,文档到向量,这个内容涉及内容也比较多,原理也可以不用了解的那么深,会用就可以了,也没有什么关系,
- # doc2vec
- #训练并保存模型
- def open_file():
- corpus = []
- token_path = "res_title_news.txt"
- try:
-
- with open(token_path, 'r', encoding="utf-8") as t:
- for line in t.readlines():
- corpus.append(line.strip())
- import gensim
-
- sentences = gensim.models.doc2vec.TaggedLineDocument(token_path)
- model = gensim.models.Doc2Vec(sentences, dm=1, size=200, window=10)
- model.train(sentences, total_examples=model.corpus_count, epochs=100)
- model.save('res_title_news_w2c.txt')
- out = open('res_title_news_vector.txt', 'w')
- for idx, docvec in enumerate(model.docvecs):
- for value in docvec:
- out.write(str(value) + ' ')
- out.write('\n')
- except Exception as e:
- print(e)
-
- open_file()
-
'运行
上面包含模型的训练与保存,会把当中文档向量的部分,放入到res_title_news_vector.txt中,打开这个文本文件之后,你会看到每一篇文档被训练成了200维度的向量。
那么模型训练好之后,接下来的是就是使用模型训练的向量,来完成Kmeans聚类,那么这个聚类是怎么做的尼?
- import gensim
- from gensim.models.doc2vec import Doc2Vec, LabeledSentence
-
- def test_km():
- model = gensim.models.Doc2Vec.load("res_title_news_vector.txt")#加载模型
- from sklearn.cluster import KMeans
- for k in range(5,20):
- clf = KMeans(n_clusters=k, n_init=20, init='k-means++', n_jobs=4)#n_init选择质心的次数,返回最好的结果
- s = clf.fit(model.docvecs)
-
- # 20个中心点位置
- # print(clf.cluster_centers_)
-
- # 每个样本所属的簇,
- print(clf.labels_)
- i = 1
- while i <= len(clf.labels_):
- # print(i, clf.labels_[i - 1])
- i = i + 1
- # 每个点,到簇类中心的距离之和,用来评估簇的个数是否合适,距离越小说明簇分的越好,选取临界点的簇个数
- print(clf.inertia_)
- test_km()

这里我进行了多次K值的设定,想重上述的结果中,找到最好的结果。
结果表明当K=12时,效果较好。这个值是根据clf.inertia_(即簇内平方和SSE,每一个样本点到簇中心的距离之和)来确定,即手肘法(此部分,来自实验室成员所写:手肘法的核心思想是:随着聚类数k的增大,样本划分会更加精细,每个簇的聚合程度会逐渐提高,那么误差平方和SSE自然会逐渐变小。并且,当k小于真实聚类数时,由于k的增大会大幅增加每个簇的聚合程度,故SSE的下降幅度会很大,而当k到达真实聚类数时,再增加k所得到的聚合程度回报会迅速变小,所以SSE的下降幅度会骤减,然后随着k值的继续增大而趋于平缓,也就是说SSE和k的关系图是一个手肘的形状,而这个肘部对应的k值就是数据的真实聚类数。当然,这也是该方法被称为手肘法的原因。)
- [ 3 8 13 13 11 6 13 0 0 5 3 1 5 13 6 0 0 12 4 15 12 6 1 9 7
- 8 8 6 7 12 4 11 11 4 3 15 0 0 5 3 5 4 12 1 4 12 11 10 12 13
- 12 4 15 4 4 8 11 0 0 5 3 6 11 11 4 4 13 11 13 0 4 10 4 2 2
- 3 3 13 4 4 2 15 12 12 15 9 13 8 3 0 12 6 3 2 0 15 11 2 12 15
- 2 8 15 15 15 13 4 10 4 3 3 2 14 12 13 12 4 13 5 5 4 14 3 1 12
- 4 1 4 2 3 11 13 2 4 12 6 6 1 1 2 6 11 12 13 13 2 15 11 9 11
- 11 15 5 1 15 15 12 15 12 13 15 11 15 11 11 3 15 11 12 15 11 15 5 15 15
- 15 15 15 15 11 15 15 5 15 15 15 15 1 15 14 14 14 14 14 14 14 14 14 14 14
- 14 14 14 13 14 0 14 6 14 14 6 8 7 6 6 0 14 7 8 6 7 0 14 4 6
- 7 0 7 7 6 8 6 3 3 0 2 2 8 8 3 3 6 0 6 0]
得到上述聚类结果后,依然看不出到底聚类效果怎么样,是否把同一主题的文本聚成一类,那么为了方便分析聚类结果,我们将文本所属簇与文本内容,一起展示出来,一探究竟,看看具体属于哪一类?
我们将此拼接成一个【K, text】形式,K即是文本所属的簇,text即是文本;
我们借用以下方法,此处是我测试的一个文本量很小的例子:输出结果是从小到大进行排序的,根据K值进行排序;
- import numpy as np
- x=np.array([1,0,0,2,2,0])
- file = open('cute.txt','r', encoding='utf-8')
- data = file.readlines()#同样是一个列表
- # print(data[3])
- index = x.argsort()#根据指针对x排序,[1,2,5,0,3,4]
- print(index)
- for i in range(len(index)):
- print(x[index[i]], data[index[i]])
前面的整数是聚类的结果,后面是对应的文本,这样便于获取当前聚类的主题。
当我们获取到每一个簇中的文本,我们可以根据NLP技术,分析每一个簇的主题,或者是根据TFIDF方法,获取每个簇的关键词,根据关键词,进行主题的呈现。
下一章,我将继续写初始化质心的内容,如何设定Kmeans的初始化质心,以提升聚类效果和聚类性能!
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。