其他
【强基固本】Kmeans 聚类算法
“强基固本,行稳致远”,科学研究离不开理论基础,人工智能学科更是需要数学、物理、神经科学等基础学科提供有力支撑,为了紧扣时代脉搏,我们推出“强基固本”专栏,讲解AI领域的基础知识,为你的科研学习提供助力,夯实理论基础,提升原始创新能力,敬请关注。
地址:https://zhuanlan.zhihu.com/p/150515679
01
聚类算法中,最经典的就是Kmeans 聚类了,也叫作 K 均值聚类,是最常用的聚类算法。
Kmeans 算法中的 K 表示的是,将样本聚为 K 个簇;Means 代表取每一个聚类中数据值的均值作为该簇的中心,或者称为质心。Kmeans 聚类算法,可以将输入数据聚合成 K 个簇并输出。
02
Kmeans 算法的停止条件通常有以下 4 个,一般任意满足一点即可停止算法的主流程:
4)某次循环,均方误差 SSE 递减的增量,小于预先设置的某个阈值,也就是这一次的迭代对聚类结果影响非常小,算法已经趋近于收敛,则算法结束迭代。SSE 的计算公式如下:
其中,K 表示 K 个簇,Cj 为簇 j 内数据样本的集合,mj 表示 Cj 簇的质心。这个公式的意思是,对每个簇计算每个数据点与其所归属的质心的距离平方和,再将所有簇的结果求和。随着 Kmeans 不断迭代,SSE 的值在不断的缩小,直到某次迭代,这个减小的幅度可被忽略。
03
04
手肘法的核心指标是SSE(sum of the squared errors,误差平方和)
05
import jieba
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.feature_extraction.text import TfidfTransformer
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt
from sklearn.decomposition import PCA
class KmeansClustering():
def __init__(self, stopwords_path=None):
self.stopwords = self.load_stopwords(stopwords_path)
self.vectorizer = CountVectorizer()
self.transformer = TfidfTransformer()
def load_stopwords(self, stopwords=None):
"""
加载停用词
:param stopwords:
:return:
"""
if stopwords:
with open(stopwords, 'r', encoding='utf-8') as f:
return [line.strip() for line in f]
else:
return []
def preprocess_data(self, corpus_path):
"""
文本预处理,每行一个文本
:param corpus_path:
:return:
"""
corpus = []
with open(corpus_path, 'r', encoding='utf-8') as f:
for line in f:
corpus.append(' '.join([word for word in jieba.lcut(line.strip()) if word not in self.stopwords]))
return corpus
def get_text_tfidf_matrix(self, corpus):
"""
获取tfidf矩阵
:param corpus:
:return:
"""
tfidf = self.transformer.fit_transform(self.vectorizer.fit_transform(corpus))
# 获取词袋中所有词语
# words = self.vectorizer.get_feature_names()
# 获取tfidf矩阵中权重
weights = tfidf.toarray()
return weights
def pca(self, weights, n_components=2):
"""
PCA对数据进行降维
:param weights:
:param n_components:
:return:
"""
pca = PCA(n_components=n_components)
return pca.fit_transform(weights)
def kmeans(self, corpus_path, n_clusters=5, fig=True):
"""
KMeans文本聚类
:param corpus_path: 语料路径(每行一篇),文章id从0开始
:param n_clusters: :聚类类别数目
:return: {cluster_id1:[text_id1, text_id2]}
"""
corpus = self.preprocess_data(corpus_path)
weights = self.get_text_tfidf_matrix(corpus)
pca_weights = self.pca(weights)
clf = KMeans(n_clusters=n_clusters)
# clf.fit(weights)
y = clf.fit_predict(weights)
if fig:
plt.scatter(pca_weights[:, 0], pca_weights[:, 1], c=y)
plt.show()
# 中心点
centers = clf.cluster_centers_
print('中心点', centers)
# 用来评估簇的个数是否合适,距离约小说明簇分得越好,选取临界点的簇的个数
score = clf.inertia_
print("评估簇的个数是否合适", score)
# 每个样本所属的簇
result = {}
for text_idx, label_idx in enumerate(y):
if label_idx not in result:
result[label_idx] = [text_idx]
else:
result[label_idx].append(text_idx)
return result
def elbow_algorithm(self, corpus_path, n_clusters_iterations=12):
"""
肘部算法 确定最优聚类类别数目
:param n_clusters_iterations: 聚类类别数目
:param corpus_path: 语料路径(每行一篇),文章id从0开始
:return:
"""
corpus = self.preprocess_data(corpus_path)
weights = self.get_text_tfidf_matrix(corpus)
SSE = [] # 存放每次结果的误差平方和
for k in range(1, n_clusters_iterations):
clf = KMeans(n_clusters=k) # 构造聚类器
clf.fit(weights)
SSE.append(clf.inertia_) # clf.inertia_获取聚类准则的总和(用来评估簇的个数是否合适,距离约小说明簇分得越好,选取临界点的簇的个数)
X = range(1, n_clusters_iterations)
plt.xlabel('k')
plt.ylabel('SSE')
plt.plot(X, SSE, 'o-')
plt.show()
if __name__ == '__main__':
Kmeans = KmeansClustering(stopwords_path='./data/stop_words.txt')
# 肘部算法 确定 簇的最优
Kmeans.elbow_algorithm('./data/test_data.txt',24)
result = Kmeans.kmeans('./data/test_data.txt', n_clusters=18)
本文目的在于学术交流,并不代表本公众号赞同其观点或对其内容真实性负责,版权归原作者所有,如有侵权请告知删除。
“强基固本”历史文章
聚类性能评估-V-Measure
完全图解RNN、RNN变体、Seq2Seq、Attention机制
脉冲神经网络(Spiking Neural Network)介绍
流形学习概述
神经网络15分钟入门!——反向传播到底是怎么传播的?
图神经网络的理论基础
深度学习入门与Pytorch|4.2 变分自编码器(VAE)介绍、推导及代码
深度学习入门与Pytorch4.1 深度学习中的几种自编码器的介绍与Pytorch代码实现
白化变换:PCA白化、ZCA白化
常用卷积神经网络巡礼(论文详解+代码实现)
强化学习入门简述
深度学习分类任务常用评估指标
漫谈什么是AI框架?
深度学习检测小目标常用方法
更多强基固本专栏文章,
请点击文章底部“阅读原文”查看
分享、点赞、在看,给个三连击呗!