作者 | 许文武

责编 | 郭芮

出品 | CSDN 博客

scikti-learn 将机器学习分为4个领域,分别是分类(classification)、聚类(clustering)、回归(regression)和降维(dimensionality reduction)。k-means均值算法虽然是聚类算法中比较简单的一种,却包含了丰富的思想内容,非常适合作为初学者的入门习题。
关于 k-means 均值聚类算法的原理介绍、实现代码,网上有很多,但运行效率似乎都有点问题。今天稍微有点空闲,写了一个不足20行的 k-means 均值聚类算法,1万个样本平均耗时20毫秒(10次均值)。同样的数据样本,网上流行的算法平均耗时3000毫秒(10次均值)。差距竟然达百倍以上,令我深感意外,不由得再次向 numpy 献上膝盖!
以下是我的代码,包含注释、空行总共26行,有效代码16行。
 1import numpy as np23def kmeans_xufive(ds, k):4    """k-means聚类算法56    k       - 指定分簇数量7    ds      - ndarray(m, n),m个样本的数据集,每个样本n个属性值8    """9
10    m, n = ds.shape # m:样本数量,n:每个样本的属性值个数
11    result = np.empty(m, dtype=np.int) # m个样本的聚类结果
12    cores = np.empty((k, n)) # k个质心
13    cores = ds[np.random.choice(np.arange(m), k, replace=False)] # 从m个数据样本中不重复地随机选择k个样本作为质心
14
15    while True: # 迭代计算
16        d = np.square(np.repeat(ds, k, axis=0).reshape(m, k, n) - cores)
17        distance = np.sqrt(np.sum(d, axis=2)) # ndarray(m, k),每个样本距离k个质心的距离,共有m行
18        index_min = np.argmin(distance, axis=1) # 每个样本距离最近的质心索引序号
19
20        if (index_min == result).all(): # 如果样本聚类没有改变
21            return result, cores # 则返回聚类结果和质心数据
22
23        result[:] = index_min # 重新分类
24        for i in range(k): # 遍历质心集
25            items = ds[result==i] # 找出对应当前质心的子样本集
26            cores[i] = np.mean(items, axis=0) # 以子样本集的均值作为当前质心的位置

这是网上比较流行的 k-means 均值聚类算法代码,包含注释、空行总共57行,有效代码37行。
 1import numpy as np23# 加载数据4def loadDataSet(fileName):5    data = np.loadtxt(fileName,delimiter='\t')6    return data78# 欧氏距离计算9def distEclud(x,y):
10    return np.sqrt(np.sum((x-y)**2))  # 计算欧氏距离
11
12# 为给定数据集构建一个包含K个随机质心的集合
13def randCent(dataSet,k):
14    m,n = dataSet.shape
15    centroids = np.zeros((k,n))
16    for i in range(k):
17        index = int(np.random.uniform(0,m)) #
18        centroids[i,:] = dataSet[index,:]
19    return centroids
20
21# k均值聚类
22def kmeans_open(dataSet,k):
23
24    m = np.shape(dataSet)[0]  #行的数目
25    # 第一列存样本属于哪一簇
26    # 第二列存样本的到簇的中心点的误差
27    clusterAssment = np.mat(np.zeros((m,2)))
28    clusterChange = True
29
30    # 第1步 初始化centroids
31    centroids = randCent(dataSet,k)
32    while clusterChange:
33        clusterChange = False
34
35        # 遍历所有的样本(行数)
36        for i in range(m):
37            minDist = 100000.0
38            minIndex = -1
39
40            # 遍历所有的质心
41            #第2步 找出最近的质心
42            for j in range(k):
43                # 计算该样本到质心的欧式距离
44                distance = distEclud(centroids[j,:],dataSet[i,:])
45                if distance < minDist:
46                    minDist = distance
47                    minIndex = j
48            # 第 3 步:更新每一行样本所属的簇
49            if clusterAssment[i,0] != minIndex:
50                clusterChange = True
51                clusterAssment[i,:] = minIndex,minDist**2
52        #第 4 步:更新质心
53        for j in range(k):
54            pointsInCluster = dataSet[np.nonzero(clusterAssment[:,0].A == j)[0]]  # 获取簇类所有的点
55            centroids[j,:] = np.mean(pointsInCluster,axis=0)   # 对矩阵的行求均值
56
57    return clusterAssment.A[:,0], centroids

函数create_data_set(),用于生成测试数据。可变参数 cores 是多个三元组,每一个三元组分别是质心的x坐标、y坐标和对应该质心的数据点的数量。
 1def create_data_set(*cores):2    """生成k-means聚类测试用数据集"""34    ds = list()5    for x0, y0, z0 in cores:6        x = np.random.normal(x0, 0.1+np.random.random()/3, z0)7        y = np.random.normal(y0, 0.1+np.random.random()/3, z0)8        ds.append(np.stack((x,y), axis=1))9
10    return np.vstack(ds)

测试代码如下:
 1import time2import matplotlib.pyplot as plt34k = 45ds = create_data_set((0,0,2500), (0,2,2500), (2,0,2500), (2,2,2500))67t0 = time.time()8result, cores = kmeans_xufive(ds, k)9t = time.time() - t0
10
11plt.scatter(ds[:,0], ds[:,1], s=1, c=result.astype(np.int))
12plt.scatter(cores[:,0], cores[:,1], marker='x', c=np.arange(k))
13plt.show()
14
15print(u'使用kmeans_xufive算法,1万个样本点,耗时%f0.3秒'%t)
16
17t0 = time.time()
18result, cores = kmeans_open(ds, k)
19t = time.time() - t0
20
21plt.scatter(ds[:,0], ds[:,1], s=1, c=result.astype(np.int))
22plt.scatter(cores[:,0], cores[:,1], marker='x', c=np.arange(k))
23plt.show()
24
25print(u'使用kmeans_open算法,1万个样本点,耗时%f0.3秒'%t)

测试结果如下:

1PS D:\XufiveGit\CSDN\code> py -3 .\k-means.py
2使用kmeans_xufive算法,1万个样本点,耗时0.0156550.3秒
3使用kmeans_open算法,1万个样本点,耗时3.9990890.3秒

效果如下:
作者:许文武,博客昵称「天元浪子」,本文首发于作者CSDN博客https://blog.csdn.net/xufive/article/details/101448969。
扫描下方二维码,下载 CSDN App,查看博主精彩分享
【END】

2019程序员转型学什么?

https://edu.csdn.net/topic/ai30?utm_source=csdn_bw

CSDN 博客诚邀入驻啦!

本着共享、协作、开源、技术之路我们共同进步的准则,

只要你技术够干货,内容够扎实,分享够积极,

欢迎加入 CSDN 大家庭!

扫描下方二维码,即刻加入吧!

 热 文 推 荐 

Python 分析热门旅游景点,告诉你哪些地方好玩、便宜、人又少!
点击阅读原文,即刻阅读《程序员大本营》最新期刊。
你点的每个“在看”,我都认真当成了喜欢

不足 20 行 Python 代码,高效实现 k-means 均值聚类算法!相关推荐

  1. 聚类 python 代码_不足 20 行 Python 代码,高效实现 k-means 均值聚类算法

    下载好向圈APP可以快速联系圈友 您需要 登录 才可以下载或查看,没有帐号?立即注册 x 不足 20 行 Python 代码,高效实现 k-means 均值聚类算法-1.jpg (143.81 KB, ...

  2. 20行 Python 代码爬取王者荣耀全英雄皮肤 | 原力计划

    作者 | wangweijun 责编 | Elle 出品 | CSDN 博客 引言 王者荣耀大家都玩过吧,没玩过的也应该听说过,作为时下最火的手机MOBA游戏,咳咳,好像跑题了.我们今天的重点是爬取王 ...

  3. python视频压缩算法_Python入门到精通视频,阿里巴巴大力推荐,20行Python代码,无损压缩千百张图片!...

    阿里巴巴推荐,Python基础入门,Python小白书籍,Python学习路线,Python进阶,Python高级,Python爬虫等等一系列关于Python的文档和视频(包括hadoop,fink, ...

  4. 如何运用python爬游戏皮肤_Python爬虫练习:20行Python代码爬取王者荣耀全英雄皮肤...

    引言王者荣耀大家都玩过吧,没玩过的也应该听说过,作为时下最火的手机MOBA游戏,咳咳,好像跑题了.我们今天的重点是爬取王者荣耀所有英雄的所有皮肤,而且仅仅使用20行Python代码即可完成. 准备工作 ...

  5. python爬虫脚本 初级入门爬虫英雄联盟所有皮肤_Python爬虫练习:20行Python代码爬取王者荣耀全英雄皮肤...

    引言王者荣耀大家都玩过吧,没玩过的也应该听说过,作为时下最火的手机MOBA游戏,咳咳,好像跑题了.我们今天的重点是爬取王者荣耀所有英雄的所有皮肤,而且仅仅使用20行Python代码即可完成. 准备工作 ...

  6. 20行Python代码,无损压缩千百张图片!

    前言 每个设计师.摄影师或有图片处理需求小编,都会面临批量高清大图的困扰. 因为高清大图放到网站上会严重拖慢加载速度,或是有的地方明确限制了图片大小,因此,为了完成工作,他们总是需要先把图片压缩,再上 ...

  7. 项目分享丨20行Python代码,无损压缩千百张图片!

    前言 每个设计师.摄影师或有图片处理需求小编,都会面临批量高清大图的困扰. 因为高清大图放到网站上会严重拖慢加载速度,或是有的地方明确限制了图片大小,因此,为了完成工作,他们总是需要先把图片压缩,再上 ...

  8. python小游戏代码大全-20行python代码的入门级小游戏的详解

    背景: 作为一个python小白,今天从菜鸟教程上看了一些python的教程,看到了python的一些语法,对比起来(有其他语言功底),感觉还是非常有趣,就随手添了一点内容,改了一个小例程,当着练练手 ...

  9. 20行Python代码爬取王者荣耀全英雄皮肤改进版

    0 写在前面 看了大神的这篇CSDN:20行Python代码爬取王者荣耀全英雄皮肤访问量那么高,忍不住想要蹭一下热点,但是蹭归蹭,总得有点货才行,于是我品我细品,发现其代码总体有三点我觉得值得改进的地 ...

  10. [转载]20行Python代码爬取王者荣耀全英雄皮肤

    20行Python代码爬取王者荣耀全英雄皮肤,这是高手.原文链接: https://blog.csdn.net/qq_42453117/article/details/103190981 除了语言学习 ...

最新文章

  1. 加固前奏2-替换application
  2. java web中验证码的实现
  3. 神奇的计算器dc和bc
  4. php ziparchive自带吗,PHP自带的ZipArchive压缩文件并下载打包好的文件(重要)
  5. 基础数学落后与高端人才流失
  6. python视频人脸检测_Python基于OpenCV实现视频的人脸检测
  7. SLAM GMapping(6)扫描匹配器
  8. uploadify 初始化的时候会请求当前页面地址
  9. 通信网中的数据报子网和虚电路子网
  10. vscode中微信小程序的代码智能提示
  11. MIT 18.02 多变量微积分笔记总目录
  12. 云服务器网站logo,云服务器 logo
  13. 利用mail 发送163 邮件
  14. Java实现格式化打印慢SQL日志
  15. 代码本色 processing编程练习
  16. 查看Linux发行版名称及版本号
  17. 让最小化安装的CentOS 6.8能够浏览网页
  18. STM32之SPI和W25Q128
  19. echarts中如何配置图例形状、图标宽高、图标和文字间距、图例位置、文字颜色、字体大小
  20. Android 模拟游戏手柄按键(跨进程 KeyEvent 事件)实践方案

热门文章

  1. 求职历程之-----我的求职信
  2. Linux 下 Tomcat 内存大小配置
  3. nginx 405 not allowed问题解决方法
  4. AsciidocFX相关
  5. [RL] 使用 dockerfile 构建 atari 环境
  6. [PyTorch] faster-rcnn
  7. Lua笔记2 变量、循环和流程控制
  8. CMake笔记2 构建动态链接库
  9. Golang中闭包的理解
  10. 拿来即用的 Python 时间范围判断方法