K-Means 均值聚类聚类算法可以说是最简单但是使用最广的一种聚类算法了,原理也简单易懂,sklearn中提供了很多聚类算法的实现,所以这里就学习一下K-Means算法。接下来会介绍一些关键性的概念,原理,sklearn中的K-Means以及参数,最后介绍一个K-Means在图像中的应用案例。

介绍与使用

:KMeans算法将一组N个样本的特征矩阵X划分为K个无交集的簇,直观上来看是簇是一组一组聚集在一起的数据,在一个簇中的数据就认为是同一类。簇就是聚类的结果表现。

质心:簇中所有数据的均值 通常被称为这个簇的“质心”(centroids)。在一个二维平面中,一簇数据点的质心的横坐标就是这一簇数据点的横坐标的均值,质心的纵坐标就是这一簇数据点的纵坐标的均值。同理可推广至高维空间。

在KMeans算法中,簇的个数K是一个超参数,需要我们人为输入来确定。KMeans的核心任务就是根据我们设定好的K,找出K个最优的质心,并将离这些质心最近的数据分别分配到这些质心代表的簇中去。具体过程可以总结如下:

那什么情况下,质心的位置会不再变化呢?当我们找到一个质心,在每次迭代中被分配到这个质心上的样本都是一致的,即每次新生成的簇都是一致的,所有的样本点都不会再从一个簇转移到另一个簇,质心就不会变化了

2.1步中说的分配到最近的质心,是根据距离来计算的,离哪个质心μi\mu_iμi​ 近,就分到对应的簇CiC_iCi​,在sklearn中距离的计算使用的是欧氏距离

d(xi,μ)=∑j=1m(xij−μj)2d(x_i,\mu)=\sqrt{\sum\limits_{j=1}^{m}(x^j_i-\mu^j)^2}d(xi​,μ)=j=1∑m​(xij​−μj)2​

其中m表示的特征数量,当然根据需要可以使用不同的距离公式,只是sklearn中没法让我们改。

显然,一个簇中所有样本点到簇 μ\muμ 的距离平方和为:

CSSl=∑i=1n∑j=1m(xij−μj)2CSS_l = \sum\limits_{i=1}^{n}\sum\limits_{j=1}^{m}(x^j_i-\mu^j)^2CSSl​=i=1∑n​j=1∑m​(xij​−μj)2

其中m是样本个数,CSSlCSS_lCSSl​又叫做inertial。那么所有簇的平方和为:

∑l=1KCSl\sum\limits_{l=1}^{K}CS_ll=1∑K​CSl​

K为簇的个数,又叫做total inertial,K-Means追求的是簇间距离尽量大,簇内距离尽量小,即total inertial要尽量小,当然是不能用total inertial来做K划分的指标的,具体的后面会说。

注意:虽然上面说了最小化,但是K-Means是没有损失函数的,损失函数本质是用来衡量模型的拟合效果的,只有有着求解参数需求的算法,才会有损失函数,所以线性回归是有损失函数的,极小化后求得参数θ\thetaθ。

下面就开始使用sklearn中的K-Means

class sklearn.cluster.KMeans (n_clusters=8, init=’k-means++’, n_init=10, max_iter=300, tol=0.0001,precompute_distances=’auto’, verbose=0, random_state=None, copy_x=True, n_jobs=None, algorithm=’auto’)

先自己生成一些数据,并可视化一下

from sklearn.datasets import make_blobs
import matplotlib.pyplot as plt
#样本500个,特征2个,分4类
X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=15)
plt.scatter(X[:,0],X[:,1],color="blue")
plt.show()

colors = ["red","blue","green","yellow"]
for i in range(4):plt.scatter(X[y==i,0],X[y==i,1],color=colors[i])
plt.show()

现在基于这个生成的数据X来使用K-Means来进行聚类,假设我们不知道y中有多少种类,来猜

#基于这个分布,我们使用KMeans来进行聚类,慢慢猜测有多少个簇
from sklearn.cluster import KMeans
n_cluster = 3
#参数n_clusters指定生成的类簇的个数 。 fit进行拟合,此时已经完成了聚类
kmeans = KMeans(n_clusters=n_cluster,random_state=10).fit(X)#
y_pre = kmeans.labels_ #查看500个数据对应的标签,只有0,1,2三种
y_pre

y_pre2 = KMeans(n_clusters=n_cluster,random_state=10).fit_predict(X)# = fit + predict
(y_pre != y_pre2).sum()  #

输出:0

y_pre3 = kmeans.predict(X)
(y_pre != y_pre3).sum()

输出:0,说明了y_pre=y_pre2=y_pre3 所以可以仅使用fit即可。

#使用部分数据进行聚类
kmeans_sub = KMeans(n_clusters=n_cluster,random_state=10).fit(X[:200])
y_pre_sub = kmeans_sub.predict(X)
(y_pre_sub == y_pre).sum()

输出:125,说明有125个预测错了,但是使用300个数据那就输出0了。

centers = kmeans.cluster_centers_#获得质心,== n_cluster
centers

inertial_ = kmeans.inertia_  #整体簇内平方和
inertial_

输出:2211.198063723221

下面进行可视化

colors = ["red","blue","green","yellow"]
for i in range(n_cluster):plt.scatter(X[y_pre == i,0],X[y_pre == i,1],color=colors[i])
plt.scatter(centers[:,0],centers[:,1],color="black")
plt.show()

上面是猜测三个簇的情况,如果使用四个簇呢

n_cluster = 4
kmeans = KMeans(n_clusters=n_cluster,random_state=10).fit(X)#此时已经完成了聚类
y_pre = kmeans.labels_
centers = kmeans.cluster_centers_
colors = ["red","blue","green","yellow","pink"]
for i in range(n_cluster):plt.scatter(X[y_pre == i,0],X[y_pre == i,1],color=colors[i])
plt.scatter(centers[:,0],centers[:,1],color="black")
plt.show()
print(kmeans.inertia_)

通过改变n_cluster大小发现inertia_越来越小,当值为500的时候inertia_成了0
因为inertia_反应的是簇内平方和,而不能反应簇间,所以不能作为聚类指标,聚类的目标是簇内距离小,簇间距离大

前面说了,KMeans的目标是确保“簇内差异小,簇外差异大。既然inertia不行,那么可以使用什么指标呢?常见的就是轮廓系数(标签未知的情况)它是对每个样本来定义的,它能够同时衡量:
1)样本与其自身所在的簇中的其他样本的相似度a,等于样本与同一簇中所有其他点之间的平均距离
2)样本与其他簇中的样本的相似度b,等于样本与下一个最近的簇中的所有点之间的平均距离
根据聚类的要求”簇内差异小,簇外差异大“,我们希望b永远大于a,并且大得越多越好。
单个样本的轮廓系数计算为

显然s的取值范围是(-1,1),s越接近1越好

其中值越接近1表示样本与自己所在的簇中的样本很相似,并且与其他簇中的样
本不相似,当样本点与簇外的样本更相似的时候,轮廓系数就为负。当轮廓系数为0时,则代表两个簇中的样本相似度一致,两个簇本应该是一个簇。
如果一个簇中的大多数样本具有比较高的轮廓系数,则簇会有较高的总轮廓系数,则整个数据集的平均轮廓系数越高,则聚类是合适的。如果许多样本点具有低轮廓系数甚至负值,则聚类是不合适的,聚类的超参数K可能设定得太大或者太小。

在sklearn中,我们使用模块metrics中的类silhouette_score来计算轮廓系数,它返回的是一个数据集中,所有样本的轮廓系数的均值。但我们还有同在metrics模块中silhouette_sample,它的参数与轮廓系数一致,但返回的是数据集中每个样本自己的轮廓系数。

#轮廓系数做指标来看n_cluster
from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples
n_cluster = 3
kmeans = KMeans(n_clusters=n_cluster,random_state=10).fit(X)#此时已经完成了聚类
y_pre = kmeans.labels_
silhouette_score(X,y_pre)

输出:0.5807467806485663

n_cluster = 4 #4的时候最好
kmeans = KMeans(n_clusters=n_cluster,random_state=10).fit(X)#此时已经完成了聚类
y_pre = kmeans.labels_
silhouette_score(X,y_pre)

输出:0.6645176788544125

n_cluster = 5
kmeans = KMeans(n_clusters=n_cluster,random_state=10).fit(X)#此时已经完成了聚类
y_pre = kmeans.labels_
silhouette_score(X,y_pre)

输出:0.5832385807644762,是不是发现了簇数为4的时候轮廓系数最高呢?所以无其他限制条件的时候我们选簇为4

注意:为什么这里加个限制条件呢?选4也不是绝对的,具体的其实还是看业务需求,比如对客户进行聚类,很可能我们就选2,因为簇数是2的时候,其中有一类肯定不会错也就是最有下角的类色的簇(客户),那么我们可以针对部分客户制定专门的销售计划,等以后有钱了再对剩下的几个簇进行划分制定计划。

n_cluster = 4
kmeans = KMeans(n_clusters=n_cluster,random_state=10).fit(X)#此时已经完成了聚类
y_pre = kmeans.labels_
silhouette_samples(X,y_pre).shape

其实也可以使用其他指标,比如卡林斯基-哈拉巴斯指数,数值越大越好,下面使用看看

from sklearn.metrics import calinski_harabaz_score
from time import time  #计算比轮廓系数快
calinski_harabaz_score(X,y_pre) - t

输出:3372.441423564358

为了计算运行时间,下面补充点python中时间的知识

from sklearn.metrics import calinski_harabaz_score
from time import time  #计算比轮廓系数快
t = time()
calinski_harabaz_score(X,y_pre)
time() - t

输出:0.0055162906646728516

#时间转换
import datetime
datetime.datetime.fromtimestamp(time()).strftime("%Y-%m-%d %H:%M:%S")

输出:‘19-02-16 17:48:31’

属性和参数

init:可输入"k-means++",“random"或者一个n维数组。这是初始化质心的方法,默认"k-means++”。输入"k -means++":一种为K均值聚类选择初始聚类中心的聪明的办法,以加速收敛。如果输入了n维数组,数组的形状应该是(n_clusters,n_features)并给出初始质心

n_init:如果不指定随机数种子,则sklearn中的K-means并不
会只选择一个随机模式扔出结果,而会在每个随机数种子下运行多次,并使用结果最好的一个随机数种子来作为初始质心。我们可以使用参数n_init来选择,每个随机数种子下运行的次数。这个参数不常用到,默认10次。

max_iter:整数,默认300,单次运行的k-means算法的最大迭代次数

tol:浮点数,默认1e-4,两次迭代间Inertia下降的量,如果两次迭代之间Inertia下降的值小于tol所设定的值,迭代就会停下

属性n_iter_:迭代次数

best = KMeans(n_clusters=10).fit(X)
best.n_iter_ #迭代次数  一般是不会去改了  12

修改init获取迭代次数

rand = KMeans(n_clusters=10,init="random",random_state=10).fit(X)
rand.n_iter_#次数明显多了  20

迭代次数的影响

r1 = KMeans(n_clusters=15,init="random",random_state=10,max_iter=1).fit(X)
r2 = KMeans(n_clusters=15,init="random",random_state=10,max_iter=10).fit(X)
silhouette_score(X,r1.labels_),silhouette_score(X,r2.labels_)

输出:(0.314112933070629, 0.35997373235991825)

函数k_means 参数与类KMeans一致

from sklearn.cluster import k_means #方法
k_means(X,4,return_n_iter=True)#返回质心,标签,inertial,迭代次数

K-Means的矢量量化应用

K-Means聚类最重要的应用之一是非结构数据(图像,声音)上的矢量量化(VQ)。非结构化数据往往占用比较多的储存空间,文件本身也会比较大,运算非常缓慢,我们希望能够在保证数据质量的前提下,尽量地缩小非结构化数据的大小,或者简化非结构化数据的结构。矢量量化就可以帮助我们实现这个目的。KMeans聚类的矢量量化本质是一种降维运用,但它与我们之前学过的任何一种降维算法的思路都不相同。特征选择的降维是直接选取对模型贡献最大的特征,PCA的降维是聚合信息,而矢量量化的降维是在同等样本量上压缩信息的大小,即不改变特征的数目也不改变样本的数目,只改变在这些特征下的样本上的信息量。对于图像来说,一张图片上的信息可以被聚类如下表示:

这是一组40个样本的数据,分别含有40组不同的信息(x1,x2)。我们将代表所有样本点聚成4类,找出四个质心,我们认为,这些点和他们所属的质心非常相似,因此他们所承载的信息就约等于他们所在的簇的质心所承载的信息。于是,我们可以使用每个样本所在的簇的质心来覆盖原有的样本,有点类似四舍五入的感觉,类似于用1来代替0.9和0.8。这样,40个样本带有的40种取值,就被我们压缩了4组取值,虽然样本量还是40个,但是这40个样本所带的取值其实只有4个,就是分出来的四个簇的质心

为了看的更加直观,接下来只进行截图

sklearn机器学习:K均值聚类相关推荐

  1. 机器学习-*-K均值聚类及代码实现

    KMeans聚类 在聚类算法中,最出名的应该就是k均值聚类(KMeans)了,几乎所有的数据挖掘/机器学习书籍都会介绍它,有些初学者还会将其与KNN等混淆.k均值是一种聚类算法,属于无监督学习的一种, ...

  2. 机器学习--K均值聚类

    机器学习--聚类 一.无监督学习 二.KMeans聚类 2.1 概览 2.2 理论介绍 2.2.1 模型 2.2.2 策略 2.2.3 算法 2.3 案例讲解 2.4 Python实现 2.4.1 导 ...

  3. 机器学习-K均值聚类(python3代码实现)

    K均值聚类 哈尔滨工程大学-537 算法原理: K均值是发现给定数据集的 k k k个簇的算法.簇个数k" role="presentation" style=" ...

  4. 机器学习K均值聚类 python

    机器学习算法与Python实践这个系列主要是参考<机器学习实战>这本书.因为自己想学习Python,然后也想对一些机器学习算法加深下了解,所以就想通过Python来实现几个比较常用的机器学 ...

  5. 机器学习--k均值聚类(K-means)

    数据分析入门与实战  公众号: weic2c 1.摘要 分类作为一种监督学习方法,要求必须事先明确知道各个类别的信息,并且断言所有待分类项都有一个类别与之对应.但是很多时候上述条件得不到满足,尤其是在 ...

  6. 机器学习 K均值聚类(K-means) 鸢尾花数据集

    聚类的目标是使聚类后的各个簇,具有簇内聚合,簇间分离的特点. 如何度量簇之间,簇内样本之间的差异度?常用距离计算,最常用的是"闵可夫斯基距离"(Minkowski distance ...

  7. 机器学习-k均值聚类算法-k_means原理14

    非监督学习

  8. python机器学习库sklearn——k均值聚类

    全栈工程师开发手册 (作者:栾鹏) python数据挖掘系列教程 k均值聚类的相关的知识内容可以参考 http://blog.csdn.net/luanpeng825485697/article/de ...

  9. 机器学习之无监督学习-K均值聚类算法

    机器学习之无监督学习-K均值聚类算法 对于无监督学习,有两类重要的应用,一个是聚类,一个是降维.我们今天主要学习聚类中的K均值聚类. 我们先看看下图,图a为原始的数据点,我们想要对图a的数据点进行分类 ...

最新文章

  1. perl XML创建XML文件
  2. Java8 - 接口默认方法
  3. Python初探---2x版本与3x版本的区别
  4. 【视频】v-html的使用
  5. html文字粒子效果简陋,5个很棒的CSS3文本粒子动画特效
  6. mysql创建数据库没有默认值报错_详解Mysql数据库date, datetime类型设置0000-00-00默认值(default)报错问题...
  7. java peek函数_Java 8 Stream Api 中的 peek 操作
  8. 《人人都可以创业》连载1:创业很简单,从心开始
  9. Blog从Hexo迁移至Wordpress
  10. yum install gcc 下载失败有可能是这个原因?
  11. Win10系统下如何设置共享打印机
  12. linux安装wine
  13. (附源码)springboot电影院售票与管理系统 毕业设计 011449
  14. 输出边长为n的正六边形(c语言)
  15. java绘图-绘制图片
  16. 考研中国科学院大学计算机分数线,中国科学院大学2017年考研分数线
  17. C++: 生成给定范围内的所有多维索引。 模拟任意数量的嵌套循环的行为(附完整源码)
  18. (跟新至2019)历年研究生数学建模题目与优秀论文
  19. 随谈——那些前端的事1:关于坚持1
  20. r语言c()函数格式,R语言基本操作函数

热门文章

  1. 男人不知道女人的16件事
  2. 《三国演义》人物出场统计
  3. 电脑技巧:分享6个实用的资源网站
  4. 当python小白遇到QQ钓鱼网站
  5. linux学校_10本Linux内核书籍推荐
  6. 大学课程计算机鼠标和键盘的介绍,计算机基础课程鼠标和键盘”.ppt
  7. mybatis-plus插入效率
  8. matlab 创建一个X矩阵,里面的变量从x1、x2...xn
  9. 利用OpenVSwitch构建多主机Docker网络
  10. 跨越平台桌面应用开发框架electron使用的心路历程