我的编程空间,编程开发者的网络收藏夹
学习永远不晚

(python实现)一篇文章教会你k-means聚类算法(包括最优聚类数目k的确定)

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

(python实现)一篇文章教会你k-means聚类算法(包括最优聚类数目k的确定)

目录

摘要

Kmeans算法中,K值所决定的是在该聚类算法中,所要分配聚类的簇的多少。Kmeans算法对初始值是⽐较敏感的,对于同样的k值,选取的点不同,会影响算法的聚类效果和迭代的次数。本文通过计算原始数据中的:手肘法、轮廓系数、CH值和DB值,四种指标来衡量K-means的最佳聚类数目,并使用K-means进行聚类,最后可视化聚类的结果。
一篇文章教会你如何使用matlab进行K-means聚类,以及如何确定最优k值,不要再去看那些付费文章了。

1. K-means算法

1.1 聚类算法简介

对于"监督学习"(supervised learning),其训练样本是带有标记信息的,并且监督学习的目的是:对带有标记的数据集进行模型学习,从而便于对新的样本进行分类。而在“无监督学习”(unsupervised learning)中,训练样本的标记信息是未知的,目标是通过对无标记训练样本的学习来揭示数据的内在性质及规律,为进一步的数据分析提供基础。对于无监督学习,应用最广的便是"聚类"(clustering)。

"聚类算法"试图将数据集中的样本划分为若干个通常是不相交的子集,每个子集称为一个“簇”(cluster),通过这样的划分,每个簇可能对应于一些潜在的概念或类别。

1.2 K-means聚类算法

kmeans算法又名k均值算法,K-means算法中的k表示的是聚类为k个簇,means代表取每一个聚类中数据值的均值作为该簇的中心,或者称为质心,即用每一个的类的质心对该簇进行描述。

其算法思想大致为:先从样本集中随机选取 k个样本作为簇中心,并计算所有样本与这 k个“簇中心”的距离,对于每一个样本,将其划分到与其距离最近的“簇中心”所在的簇中,对于新的簇计算各个簇的新的“簇中心”。

根据以上描述,我们大致可以猜测到实现kmeans算法的主要四点:
   (1)簇个数 k 的选择
   (2)各个样本点到“簇中心”的距离
   (3)根据新划分的簇,更新“簇中心”
   (4)重复上述2、3过程,直至"簇中心"没有移动。

1.3 代码实现

注意:需要先通过下文2部分确定k值

import randomimport pandas as pdimport numpy as npimport matplotlib.pyplot as plt# 计算欧式距离def calcDis(dataSet, centroids, k):    clalist=[]    for data in dataSet:        diff = np.tile(data, (k, 1)) - centroids  #相减   (np.tile(a,(2,1))就是把a先沿x轴复制1倍,即没有复制,仍然是 [0,1,2]。 再把结果沿y方向复制2倍得到array([[0,1,2],[0,1,2]]))        squaredDiff = diff ** 2     #平方        squaredDist = np.sum(squaredDiff, axis=1)   #和  (axis=1表示行)        distance = squaredDist ** 0.5  #开根号        clalist.append(distance)     clalist = np.array(clalist)  #返回一个每个点到质点的距离len(dateSet)*k的数组    return clalist# 计算质心def classify(dataSet, centroids, k):    # 计算样本到质心的距离    clalist = calcDis(dataSet, centroids, k)    # 分组并计算新的质心    minDistIndices = np.argmin(clalist, axis=1)    #axis=1 表示求出每行的最小值的下标    newCentroids = pd.DataFrame(dataSet).groupby(minDistIndices).mean() #DataFramte(dataSet)对DataSet分组,groupby(min)按照min进行统计分类,mean()对分类结果求均值    newCentroids = newCentroids.values     # 计算变化量    changed = newCentroids - centroids     return changed, newCentroids# 使用k-means分类def kmeans(dataSet, k):    # 随机取质心    centroids = random.sample(dataSet, k)        # 更新质心 直到变化量全为0    changed, newCentroids = classify(dataSet, centroids, k)    while np.any(changed != 0):        changed, newCentroids = classify(dataSet, newCentroids, k)     centroids = sorted(newCentroids.tolist())   #tolist()将矩阵转换成列表 sorted()排序     # 根据质心计算每个集群    cluster = []    clalist = calcDis(dataSet, centroids, k) #调用欧拉距离    minDistIndices = np.argmin(clalist, axis=1)      for i in range(k):        cluster.append([])    for i, j in enumerate(minDistIndices):   #enymerate()可同时遍历索引和遍历元素        cluster[j].append(dataSet[i])            return centroids, cluster # 创建数据集def createDataSet():    return [[1, 1], [1, 2], [2, 1], [6, 4], [6, 3], [5, 4]]if __name__=='__main__':     dataset = createDataSet()    centroids, cluster = kmeans(dataset, 2)    print('质心为:%s' % centroids)    print('集群为:%s' % cluster)    for i in range(len(dataset)):      plt.scatter(dataset[i][0],dataset[i][1], marker = 'o',color = 'green', s = 40 ,label = '原始点')                        #  记号形状       颜色      点的大小      设置标签      for j in range(len(centroids)):        plt.scatter(centroids[j][0],centroids[j][1],marker='x',color='red',s=50,label='质心')        plt.show()

2. 最优聚类数目K的确定

2.1 手肘法–Elbow(经验方法)

我们知道k-means是以最小化样本与质点平方误差作为目标函数,将每个簇的质点与簇内样本点的平方距离误差和称为畸变程度(distortions),那么,对于一个簇,它的畸变程度越低,代表簇内成员越紧密,畸变程度越高,代表簇内结构越松散。 畸变程度会随着类别的增加而降低,但对于有一定区分度的数据,在达到某个临界点时畸变程度会得到极大改善,之后缓慢下降,这个临界点就可以考虑为聚类性能较好的点。

# 导包import numpy as npimport pandas as pdimport matplotlib.pyplot as pltfrom scipy.spatial.distance import cdistfrom sklearn.cluster import KMeans# 1.利用pandas读入数据data = pd.read_csv(data_path, header=None) # data_path换成你的需要聚类的数据所在路径,我的数据没有表头,所以设置header=Nonex = data[0: 150] # 设置需要聚类的数据列数,我的是150维# 2.绘制手肘图dispersions = []for k in range(1, 20): # k:需要聚几类,按需修改,推荐至少10类    kmeans = KMeans(n_clusters=k, random_state=9)    y_pred = kmeans.fit_predict(x)    dispersions.append(sum(np.min(cdist(x, kmeans.cluster_centers_, 'euclidean'), axis=1))/x.shape[0])print(dispersions)plt.plot(range(1, 20), dispersions, 'bx-')plt.xlabel('Number of Clusters (k)')plt.ylabel('Average Dispersion')plt.title('the Elbow Method')plt.show()

在这里插入图片描述

我的数据比较差,暂且认为在聚5类之前走势变换程度较大,聚5类以后走势变得平缓,所以如果按照手肘法,我的k值确定为5。
注意:手肘法通过人眼观察肘部图的走向来确定肘部位置进而来确定k值,主观因素很大,不推荐在写论文时使用,解释不清,以免审稿人刁难。

2.2 Silhouette Coefficient(轮廓系数,理论方法)

对于一个聚类任务,我们希望得到的类别簇中,簇内尽量紧密,簇间尽量远离,轮廓系数便是类的密集与分散程度的评价指标,公式表达为s=(b−a)/max(a,b),其中a簇样本到彼此间距离的均值,b代表样本到除自身所在簇外的最近簇的样本的均值,s取值在[-1, 1]之间,越接近1表示聚类效果越好

import pandas as pdimport matplotlib.pyplot as pltfrom sklearn.cluster import KMeansfrom sklearn.metrics import silhouette_scoredata = pd.read_csv(data_path, header=None)x = data[0: 150]silhouette_scores = []for k in range(2, 10):    y_pred = KMeans(n_clusters=k, random_state=9).fit_predict(x)    silhouette_scores.append(silhouette_score(x, y_pred))print(silhouette_scores)plt.plot(range(2, 10), silhouette_scores, 'bx-')plt.xlabel('Number of Clusters (k)')plt.ylabel('silhouette')plt.title('the Silhouette Method')plt.show()

在这里插入图片描述

2.3 Calinski-Harabasz Criterion(卡林斯基-哈拉巴斯指标,CH值,理论方法)

定义就不多说了,直接上代码

import pandas as pdimport matplotlib.pyplot as pltfrom sklearn import metricsfrom sklearn.cluster import KMeansdata = pd.read_csv(data_path, header=None)x = data[0: 520]scores = []for k in range(2, 20):    y_pred = KMeans(n_clusters=k, random_state=9).fit_predict(x)    score = metrics.calinski_harabasz_score(x, y_pred)    scores.append(score)print(scores)plt.plot(range(2, 20), scores, 'bx-')plt.xlabel('k')plt.ylabel('the Calinski Carabasz Score')plt.title('the CH Method')plt.show()

2.4 Davies-Bouldin Criterion(戴维斯-博尔丁指标,DB值,理论方法)

import pandas as pdimport matplotlib.pyplot as pltfrom sklearn import metricsfrom sklearn.cluster import KMeansdata = pd.read_csv(data_path, header=None)x = data[0: 520]scores = []for k in range(2, 20):    y_pred = KMeans(n_clusters=k, random_state=9).fit_predict(x)    score = metrics.davies_bouldin_score(x, y_pred)    scores.append(score)print(scores)plt.plot(range(2, 20), scores, 'bx-')plt.xlabel('k')plt.ylabel('the Davies Bouldin Score')plt.title('the DB Method')plt.show()

来源地址:https://blog.csdn.net/LBW_CSDN/article/details/128475848

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

(python实现)一篇文章教会你k-means聚类算法(包括最优聚类数目k的确定)

下载Word文档到电脑,方便收藏和打印~

下载Word文档

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录