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

Python实现聚类K-means算法

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

北京

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

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

看不清楚,换张图片

免费获取短信验证码

Python实现聚类K-means算法

本文内容、数据参考周志华《机器学习》,代码部分为个人实现,如有错误还请指出。
K-means(K均值)算法是最简单的一种聚类算法,它期望最小化平方误差
E = ∑ i = 1 k ∑ x ∈ C i ∣ ∣ x − μi ∣ ∣22 E=\sum\limits_{i=1}^k\sum\limits_{x\in C_i}||\pmb x-\pmb\mu_i||_2^2 E=i=1kxCixxxμμμi22
其中 μi = 1 ∣ C i ∣ ∑ x ∈ C i x \pmb\mu_i=\frac{1}{|C_i|}\sum_{x \in C_i}\pmb x μμμi=Ci1xCixxx是簇(cluster) Ci C_i Ci的均值向量, ∣ ∣ x − μi ∣ ∣2 ||\pmb x-\pmb\mu_i||_2 xxxμμμi2即一般意义下向量的模长。
K-means算法的一般步骤如下:

输入:样本集 D = { x1 , x2 , . . . , xm } ; D=\{\pmb x_1,\pmb x_2,...,\pmb x_m\}; D={xxx1,xxx2,...,xxxm};聚类簇数 k . k. k.
过程
   1 : 从 D 中 随 机 选 择 k 个 样 本 作 为 初 始 均 值 向 量 { μ1 , μ2 , . . . , μk } \ \ 1:从D中随机选择k个样本作为初始均值向量\{\pmb \mu_1, \pmb \mu_2,...,\pmb \mu_k\}   1:Dk{μμμ1,μμμ2,...,μμμk}
   2 : repeat \ \ 2:\texttt{repeat}   2:repeat
   3 : 令 Ci = ∅ ( 1 ≤ i ≤ k ) \ \ 3:\hspace{0.5cm}令C_i=\varnothing(1\le i \le k)   3:Ci=(1ik)
   4 : for j = 1 , 2 , . . . , m do \ \ 4:\hspace{0.5cm}\texttt{for}\hspace{0.2cm} j=1,2,...,m \hspace{0.2cm}\texttt{do}   4:forj=1,2,...,mdo
   5 : 计 算 样 本 xj 与 各 均 值 向 量 μi ( 1 ≤ i ≤ k ) 的 距 离 : d j i = ∣ ∣ x − μi ∣ ∣2 ; \ \ 5:\hspace{1.0cm}计算样本\pmb x_j与各均值向量\pmb \mu_i(1\le i \le k)的距离:d_{ji}=||\pmb x-\pmb\mu_i||_2;   5:xxxjμμμi(1ik)dji=xxxμμμi2;
   6 : 根 据 距 离 最 近 的 均 值 向 量 确 定 xj 的 簇 标 记 : λj = argmin i ∈ { 1 , 2 , . . . , k } d j i ; \ \ 6:\hspace{1.0cm}根据距离最近的均值向量确定x_j的簇标记:\lambda_j=\texttt{argmin}_{i\in \{1,2,...,k\}}d_{ji};   6:xj:λj=argmini{1,2,...,k}dji;
   7 : 将 样 本 xj 划 入 相 应 的 簇 : C λ j = C λ j ∪ { xj } ; \ \ 7:\hspace{1.0cm}将样本\pmb x_j划入相应的簇:C_{\lambda_j}=C_{\lambda_j}\cup\{\pmb x_j\};   7:xxxj:Cλj=Cλj{xxxj};
   8 : end for \ \ 8:\hspace{0.5cm}\texttt{end for}   8:end for
   9 : for i = 1 , 2 , . . . , k do \ \ 9:\hspace{0.5cm}\texttt{for}\hspace{0.2cm}i=1,2,...,k\hspace{0.2cm}\texttt{do}   9:fori=1,2,...,kdo
10 : 计 算 新 均 值 向 量 : μi ′ = 1 ∣ C i ∣ ∑ x ∈ C i x ; 10:\hspace{1.0cm}计算新均值向量:\pmb \mu_i^{'}=\frac{1}{|C_i|}\sum_{x \in C_i}\pmb x; 10::μμμi=Ci1xCixxx;
11 : if μi ′ ≠ μi then 11:\hspace{1.0cm}\texttt{if} \hspace{0.2cm}\pmb \mu_i^{'}\neq\pmb \mu_i\hspace{0.2cm}\texttt{then} 11:ifμμμi=μμμithen
12 : 将 当 前 均 值 向 量 μi 更 新 为 μi ′ 12:\hspace{1.5cm}将当前均值向量\pmb \mu_i更新为\pmb \mu_i^{'} 12:μμμiμμμi
13 : else 13:\hspace{1.0cm}\texttt{else} 13:else
14 : 保 持 当 前 均 值 向 量 不 变 14:\hspace{1.5cm}保持当前均值向量不变 14:
15 : end if 15:\hspace{1.0cm}\texttt{end if} 15:end if
16 : end for 16:\hspace{0.5cm}\texttt{end for} 16:end for
17 : until 当 前 均 值 向 量 均 未 更 新 17:\texttt{until}\hspace{0.2cm}当前均值向量均未更新 17:until
输出:簇划分 C = { C1 , C2 , . . . , Ck } \mathcal{C}=\{C_1,C_2,...,C_k\} C={C1,C2,...,Ck}

:为避免运行时间过长,通常设置一个最大运行轮数或最小调整幅度阈值,若到达最大轮数或调整幅度小于阈值,则停止运行。

下面我们用python来实现一下K-means算法:我们先尝试手动实现这个算法,再用sklearn库中的KMeans类来实现。数据我们采用《机器学习》的西瓜数据(P202表9.1):

# 下面的内容保存在 melons.txt 中# 第一列为西瓜的密度;第二列为西瓜的含糖率。我们要把这30个西瓜分为3类0.697 0.4600.774 0.3760.634 0.2640.608 0.3180.556 0.2150.403 0.2370.481 0.1490.437 0.2110.666 0.0910.243 0.2670.245 0.0570.343 0.0990.639 0.1610.657 0.1980.360 0.3700.593 0.0420.719 0.1030.359 0.1880.339 0.2410.282 0.2570.748 0.2320.714 0.3460.483 0.3120.478 0.4370.525 0.3690.751 0.4890.532 0.4720.473 0.3760.725 0.4450.446 0.459

手动实现

我们用到的库有matplotlibnumpy,如果没有需要先用pip安装一下。

import randomimport numpy as npimport matplotlib.pyplot as plt

下面定义一些数据:

k = 3 # 要分的簇数rnd = 0 # 轮次,用于控制迭代次数(见上文)ROUND_LIMIT = 100 # 轮次的上限THRESHOLD = 1e-10 # 单轮改变距离的阈值,若改变幅度小于该阈值,算法终止melons = [] # 西瓜的列表clusters = [] # 簇的列表,clusters[i]表示第i簇包含的西瓜

melons.txt读取数据,保存在列表中:

f = open('melons.txt', 'r')for line in f:# 把字符串转化为numpy中的float64类型    melons.append(np.array(line.split(' '), dtype = np.string_).astype(np.float64))

m m m个数据中随机挑选出 k k k个,对应上面算法的第 1 1 1行:

# random的sample函数从列表中随机挑选出k个样本(不重复)。我们在这里把这些样本作为均值向量mean_vectors = random.sample(melons, k)

下面是算法的主要部分。

# 这个while对应上面算法的2-17行while True:    rnd += 1 # 轮次增加    change = 0 # 把改变幅度重置为0    # 清空对簇的划分,对应上面算法的第3行    clusters = []    for i in range(k):        clusters.append([])    # 这个for对应上面算法的4-8行    for melon in melons:    '''    argmin 函数找出容器中最小的下标,在这里这个目标容器是    list(map(lambda vec: np.linalg.norm(melon - vec, ord = 2), mean_vectors)),    它表示melon与mean_vectors中所有向量的距离列表。    (numpy.linalg.norm计算向量的范数,ord = 2即欧几里得范数,或模长)    '''        c = np.argmin(            list(map( lambda vec: np.linalg.norm(melon - vec, ord = 2), mean_vectors))        )        clusters[c].append(melon)# 这个for对应上面算法的9-16行    for i in range(k):    # 求每个簇的新均值向量        new_vector = np.zeros((1,2))        for melon in clusters[i]:            new_vector += melon        new_vector /= len(clusters[i])                # 累加改变幅度并更新均值向量        change += np.linalg.norm(mean_vectors[i] - new_vector, ord = 2)        mean_vectors[i] = new_vector# 若超过设定的轮次或者变化幅度<预先设定的阈值,结束算法    if rnd > ROUND_LIMIT or change < THRESHOLD:        breakprint('最终迭代%d轮'%rnd)

最后我们绘图来观察一下划分的结果:

colors = ['red', 'green', 'blue']# 每个簇换一下颜色,同时迭代簇和颜色两个列表for i, col in zip(range(k), colors):    for melon in clusters[i]:    # 绘制散点图        plt.scatter(melon[0], melon[1], color = col)plt.show()

划分结果(由于最开始的 k k k个均值向量随机选取,每次划分的结果可能会不同):
在这里插入图片描述
完整代码:

import randomimport numpy as npimport matplotlib.pyplot as pltk = 3rnd = 0ROUND_LIMIT = 10THRESHOLD = 1e-10melons = []clusters = []f = open('melons.txt', 'r')for line in f:    melons.append(np.array(line.split(' '), dtype = np.string_).astype(np.float64))mean_vectors = random.sample(melons, k)while True:    rnd += 1    change = 0    clusters = []    for i in range(k):        clusters.append([])    for melon in melons:        c = np.argmin(            list(map( lambda vec: np.linalg.norm(melon - vec, ord = 2), mean_vectors))        )        clusters[c].append(melon)    for i in range(k):        new_vector = np.zeros((1,2))        for melon in clusters[i]:            new_vector += melon        new_vector /= len(clusters[i])        change += np.linalg.norm(mean_vectors[i] - new_vector, ord = 2)        mean_vectors[i] = new_vector    if rnd > ROUND_LIMIT or change < THRESHOLD:        breakprint('最终迭代%d轮'%rnd)colors = ['red', 'green', 'blue']for i, col in zip(range(k), colors):    for melon in clusters[i]:        plt.scatter(melon[0], melon[1], color = col)plt.show()

sklearn库中的KMeans

这种经典算法显然不需要我们反复地造轮子,被广泛使用的python机器学习库sklearn已经提供了该算法的实现。sklearn的官方文档中给了我们一个示例:

>>> from sklearn.cluster import KMeans>>> import numpy as np>>> X = np.array([[1, 2], [1, 4], [1, 0],...               [10, 2], [10, 4], [10, 0]])>>> kmeans = KMeans(n_clusters=2, random_state=0).fit(X)>>> kmeans.labels_array([1, 1, 1, 0, 0, 0], dtype=int32)>>> kmeans.predict([[0, 0], [12, 3]])array([1, 0], dtype=int32)>>> kmeans.cluster_centers_array([[10.,  2.],       [ 1.,  2.]])

可以看出,X即要聚类的数据(1,2),(1,4),(1,0)等。
KMeans类的初始化参数n_clusters即簇数 k k k;
random_state是用于初始化选取 k k k个向量的随机数种子;
kmeans.labels_即每个点所属的簇;
kmeans.predict方法预测新的数据属于哪个簇;
kmeans.cluster_centers_返回每个簇的中心。
我们就改造一下这个简单的示例,完成对上面西瓜的聚类。

import numpy as npimport matplotlib.pyplot as pltfrom sklearn.cluster import KMeansX = []f = open('melons.txt', 'r')for line in f:    X.append(np.array(line.split(' '), dtype = np.string_).astype(np.float64))kmeans = KMeans(n_clusters = 3, random_state = 0).fit(X)colors = ['red', 'green', 'blue']for i, cluster in enumerate(kmeans.labels_):    plt.scatter(X[i][0], X[i][1], color = colors[cluster])plt.show()

运行结果如下,可以看到和我们手写的聚类结果基本一致。
在这里插入图片描述

来源地址:https://blog.csdn.net/wyn1564464568/article/details/125782286

免责声明:

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

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

Python实现聚类K-means算法

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

下载Word文档

猜你喜欢

Python如何实现聚类K-means算法

今天小编给大家分享一下Python如何实现聚类K-means算法的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。K-means
2023-07-02

python中实现k-means聚类算法详解

算法优缺点:优点:容易实现 缺点:可能收敛到局部最小值,在大规模数据集上收敛较慢 使用数据类型:数值型数据 算法思想k-means算法实际上就是通过计算不同样本间的距离来判断他们的相近关系的,相近的就会放到同一个类别中去。 1.首先我们需要
2022-06-04

如何使用Python语言实现K-Means聚类算法

这篇文章给大家分享的是有关如何使用Python语言实现K-Means聚类算法的内容。小编觉得挺实用的,因此分享给大家做个参考,一起跟随小编过来看看吧。1 概述1.1 无监督学习 在一个典型的监督学习中,我们有一个有标签的训练集,我
2023-06-26

Python 中怎么实现一个k-means 均值聚类算法

Python 中怎么实现一个k-means 均值聚类算法,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。scikti-learn 将机器学习分为4个领域,分别是分
2023-06-02

python怎么实现K-means算法

本篇内容介绍了“python怎么实现K-means算法”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!  K-means 聚类算法  特点  
2023-06-01

K-means聚类算法介绍与利用python实现的代码示例

聚类 今天说K-means聚类算法,但是必须要先理解聚类和分类的区别,很多业务人员在日常分析时候不是很严谨,混为一谈,其实二者有本质的区别。 分类其实是从特定的数据中挖掘模式,作出判断的过程。比如Gmail邮箱里有垃圾邮件分类器,一开始的时
2022-06-04

python利用K-Means算法实现对数据的聚类案例详解

目的是为了检测出采集数据中的异常值。所以很明确,这种情况下的簇为2:正常数据和异常数据两大类 1、安装相应的库import matplotlib.pyplot as plt # 用于可视化 from sklearn.cluster imp
2022-06-02

Python实现K-means聚类算法并可视化生成动图步骤详解

K-means算法介绍 简单来说,K-means算法是一种无监督算法,不需要事先对数据集打上标签,即ground-truth,也可以对数据集进行分类,并且可以指定类别数目 牧师-村民模型 K-means 有一个著名的解释:牧师—村民模型:有
2022-06-02

编程热搜

  • 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动态编译

目录