Python实现聚类K-means算法详解


Posted in Python onJuly 15, 2022

K-means(K均值)算法是最简单的一种聚类算法,它期望最小化平方误差

Python实现聚类K-means算法详解

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

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

# 下面的内容保存在 melons.txt 中
# 第一列为西瓜的密度;第二列为西瓜的含糖率。我们要把这30个西瓜分为3类
0.697 0.460
0.774 0.376
0.634 0.264
0.608 0.318
0.556 0.215
0.403 0.237
0.481 0.149
0.437 0.211
0.666 0.091
0.243 0.267
0.245 0.057
0.343 0.099
0.639 0.161
0.657 0.198
0.360 0.370
0.593 0.042
0.719 0.103
0.359 0.188
0.339 0.241
0.282 0.257
0.748 0.232
0.714 0.346
0.483 0.312
0.478 0.437
0.525 0.369
0.751 0.489
0.532 0.472
0.473 0.376
0.725 0.445
0.446 0.459

手动实现

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

import random
import numpy as np
import 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:
        break
print('最终迭代%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个均值向量随机选取,每次划分的结果可能会不同):

Python实现聚类K-means算法详解

完整代码:

import random
import numpy as np
import matplotlib.pyplot as plt

k = 3
rnd = 0
ROUND_LIMIT = 10
THRESHOLD = 1e-10
melons = []
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:
        break
print('最终迭代%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 np
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

X = []
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()

运行结果如下,可以看到和我们手写的聚类结果基本一致:

Python实现聚类K-means算法详解

到此这篇关于Python实现聚类K-means算法详解的文章就介绍到这了,更多相关Python K-means算法内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
探寻python多线程ctrl+c退出问题解决方案
Oct 23 Python
python 的列表遍历删除实现代码
Apr 12 Python
python 打印出所有的对象/模块的属性(实例代码)
Sep 11 Python
教你用Python脚本快速为iOS10生成图标和截屏
Sep 22 Python
Python初学时购物车程序练习实例(推荐)
Aug 08 Python
Pytorch入门之mnist分类实例
Apr 14 Python
详解Django中类视图使用装饰器的方式
Aug 12 Python
django mysql数据库及图片上传接口详解
Jul 18 Python
python读写csv文件并增加行列的实例代码
Aug 01 Python
Matplotlib绘制雷达图和三维图的示例代码
Jan 07 Python
Anaconda3+tensorflow2.0.0+PyCharm安装与环境搭建(图文)
Feb 18 Python
python 基于opencv 实现一个鼠标绘图小程序
Dec 11 Python
python自动获取微信公众号最新文章的实现代码
Jul 15 #Python
pytorch实现加载保存查看checkpoint文件
Jul 15 #Python
pytest实现多进程与多线程运行超好用的插件
Jul 15 #Python
python如何将mat文件转为png
Jul 15 #Python
python读取mat文件生成h5文件的实现
Jul 15 #Python
全网非常详细的pytest配置文件
Jul 15 #Python
Python如何加载模型并查看网络
Jul 15 #Python
You might like
自动生成文章摘要的代码[PHP 版本]
2007/03/20 PHP
排序算法之PHP版快速排序、冒泡排序
2014/04/09 PHP
深入理解php printf() 输出格式化的字符串
2016/05/23 PHP
实例讲解PHP表单
2020/06/10 PHP
jquery图片上下tab切换效果
2011/03/18 Javascript
JavaScript排序算法之希尔排序的2个实例
2014/04/04 Javascript
JavaScript实现继承的4种方法总结
2014/10/16 Javascript
node.js中的fs.closeSync方法使用说明
2014/12/17 Javascript
JQuery包裹DOM节点的方法
2015/06/11 Javascript
JavaScript中Date.toSource()方法的使用教程
2015/06/12 Javascript
探索angularjs+requirejs全面实现按需加载的套路
2016/02/26 Javascript
Node.js + Redis Sorted Set实现任务队列
2016/09/19 Javascript
KnockoutJS 3.X API 第四章之事件event绑定
2016/10/10 Javascript
jquery.guide.js新版上线操作向导镂空提示jQuery插件(推荐)
2017/05/20 jQuery
jQuery实现点击关注和取消功能
2017/07/03 jQuery
基于JavaScript实现多级菜单效果
2017/07/25 Javascript
ionic2懒加载配置详解
2017/09/01 Javascript
js构建二叉树进行数值数组的去重与优化详解
2018/03/26 Javascript
vue项目在安卓低版本机显示空白的原因分析(两种)
2018/09/04 Javascript
jquery实现自定义树形表格的方法【自定义树形结构table】
2019/07/12 jQuery
vue iview实现动态新增和删除
2020/06/17 Javascript
微信小程序自定义支持图片的弹窗
2020/12/21 Javascript
python中使用smtplib和email模块发送邮件实例
2014/04/22 Python
如何搜索查找并解决Django相关的问题
2014/06/30 Python
用Python代码来解图片迷宫的方法整理
2015/04/02 Python
python中dir函数用法分析
2015/04/17 Python
详解Django中的form库的使用
2015/07/18 Python
Python判断一个文件夹内哪些文件是图片的实例
2018/12/07 Python
Pretty Little Thing美国:时尚女性服饰
2018/08/27 全球购物
SKECHERS斯凯奇中国官网:来自美国的运动休闲品牌
2018/11/14 全球购物
设计模式的基本要素是什么
2014/04/21 面试题
XML文档定义有几种形式?它们之间有何本质区别?解析XML文档有哪几种方式?
2016/01/12 面试题
销售人员求职信
2014/07/22 职场文书
2014年国庆节演讲稿精选范文1500字
2014/09/25 职场文书
PHP 技巧 * SVG 保存为图片(分享图生成)
2021/04/02 PHP
SpringBoot接入钉钉自定义机器人预警通知
2022/07/15 Java/Android