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

这篇具有很好参考价值的文章主要介绍了(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 random
import pandas as pd
import numpy as np
import 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 np
import pandas as pd
import matplotlib.pyplot as plt
from scipy.spatial.distance import cdist
from sklearn.cluster import KMeans

# 1.利用pandas读入数据
data = pd.read_csv(data_path, header=None) # data_path换成你的需要聚类的数据所在路径,我的数据没有表头,所以设置header=None
x = 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()

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

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

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

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

import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score


data = 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()

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

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

定义就不多说了,直接上代码文章来源地址https://www.toymoban.com/news/detail-446186.html

import pandas as pd
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.cluster import KMeans


data = 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 pd
import matplotlib.pyplot as plt
from sklearn import metrics
from sklearn.cluster import KMeans


data = 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()

到了这里,关于(python实现)一篇文章教会你k-means聚类算法(包括最优聚类数目k的确定)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数学建模--K-means聚类的Python实现

    目录 1.算法流程简介 2.1.K-mean算法核心代码 2.2.K-mean算法效果展示 3.1.肘部法算法核心代码  3.2.肘部法算法效果展示   

    2024年02月09日
    浏览(25)
  • Python | 实现 K-means 聚类——多维数据聚类散点图绘制

    客观吐槽:CSDN的富文本编辑器真是超级无敌难用 。首先要吐槽一下CSDN的富文本编辑器,好难用,好难用,好难用,好难用好难用,好难用,好难用,好难用!!!!!!!!!!!!!!!!!!前边的开头文字编辑了三四次,每次都是不小心按了ctrl+z,就完全消失了。

    2024年02月03日
    浏览(28)
  • ai写作怎么用?这篇文章教会你

    在数字化时代,写作已经成为了一种不可或缺的技能。无论是学术论文、商业文案、社交媒体帖子,还是个人日记、博客文章,我们都需要用到写作。然而,随着人工智能技术的发展,我们开始使用ai写作来完成这些任务。ai写作可以帮助人们快速、准确地完成写作任务,提高

    2024年02月16日
    浏览(31)
  • k-means聚类算法 心得分享(含python实现代码)

    目录 1.K-means聚类算法 1.1 引言: 1.2 K-Means 算法的基本思想 1.3 K-Means 算法的优缺点: 1.4 K-Means 算法的应用: 2.K-means聚类算法的实现具体步骤 2.1初始化聚类中心 2.2计算每个数据点到聚类中心的距离 2.3确定每个数据点所属聚类簇 2.4更新聚类中心 2.5循环执行步骤2-4,直到达到最

    2024年02月02日
    浏览(35)
  • 一篇文章教会你什么是Linux进程控制

    在Linux上一篇文章进程概念详解我们提到了在linux中fork函数是非常重要的函数,它从已存在进程中创建一个新进程。新进程为子进程,而原进程为父进程。 返回值 自进程中返回0,父进程返回子进程id,出错返回-1 1.1那么fork创建子进程时,操作系统都做了什么呢? 当在操作系

    2024年02月13日
    浏览(26)
  • docker从安装到部署项目,一篇文章教会你

    首先看下 Docker 图标: 一条小鲸鱼上面有些集装箱,比较形象的说明了 Docker 的特点,以后见到这个图标等同见到了 Docker 1. Docker 是一个开源的应用容器引擎,它基于 Go 语言开发,并遵从 Apache2.0 开源协议 2. 使用 Docker 可以让开发者封装他们的应用以及依赖包到一个可移植的

    2024年02月08日
    浏览(40)
  • 一篇文章教会你如何编写一个简单的Shell脚本

    Shell脚本概念 Shell 脚本是一种用于自动化执行一系列命令和操作的脚本文件。它使用的是 Shell 解释器(如 Bash、Korn Shell、Zsh 等)来解释和执行其中的命令。Shell 脚本通常用于编写简单的任务和工作流程,可以帮助我们进行系统管理、批量处理、自动化部署等任务。 以.sh后缀

    2024年02月10日
    浏览(35)
  • C++初阶之一篇文章教会你list(理解和使用)

    在C++标准库中, std::list 是一个双向链表容器,用于存储一系列元素。与 std::vector 和 std::deque 等容器不同, std::list 使用链表的数据结构来组织元素,因此在某些操作上具有独特的优势和性能特点。以下是关于 std::list 的详细介绍: 双向链表结构: std::list 内部使用双向链表来

    2024年02月13日
    浏览(36)
  • K-Means聚类算法及其python实现(已附上代码至本博客)

    觉得有用的,一腚要先点赞后收藏!!!气死人了,40多个收藏0点赞!! 对于 n代表了x有n维,x上标j表示第j维的特征,下标i表示该向量是第i个样本 簇中心坐标为:(当然,这也是重新计算簇中心坐标的方法!!) 向量 u i = ( u i ( 1 ) , u i ( 2 ) , ⋅ ⋅ ⋅ , u i ( j ) , ⋅ ⋅ ⋅ , u i ( n )

    2024年02月08日
    浏览(27)
  • python 实现k-means聚类算法 银行客户分组画像实战(超详细,附源码)

    想要数据集请点赞关注收藏后评论区留言留下QQ邮箱 k-means具体是什么这里就不再赘述,详情可以参见我这篇博客 k-means 问题描述:银行对客户信息进行采集,获得了200位客户的数据,客户特征包括以下四个1:社保号码 2:姓名  3:年龄 4:存款数量 使用k-means算法对客户进行

    2024年02月11日
    浏览(42)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包