python3 基于Kmeans 文本聚类

聚类常规方法,分一下几步:

  • 文本处理,切词、去停用词,文档向量
  • 聚类(K值,聚类中心,本节涉及的Kmeans方法中心暂时是随机生成,后面会有更新)

第一部分内容,本人暂不祥说,核心的内容,大概如下把

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]])

python3 基于Kmeans 文本聚类_第1张图片

前面的整数是聚类的结果,后面是对应的文本,这样便于获取当前聚类的主题。

当我们获取到每一个簇中的文本,我们可以根据NLP技术,分析每一个簇的主题,或者是根据TFIDF方法,获取每个簇的关键词,根据关键词,进行主题的呈现。

下一章,我将继续写初始化质心的内容,如何设定Kmeans的初始化质心,以提升聚类效果和聚类性能!

你可能感兴趣的:(python)