大家早上好,本人姓吴,如果觉得文章写得还行的话也可以叫我吴老师。欢迎大家跟我一起走进数据分析的世界,一起学习!

感兴趣的朋友可以关注我或者我的数据分析专栏,里面有许多优质的文章跟大家分享哦。


必看前言

本文将大家用sklearn来实现K-Means算法以及各参数详细说明,并且介绍无监督学习算法的评估指标,干货满满,建议收藏!

1 使用sklearn实现K-Means

1.1 重要参数:n_clusters

n_clusters 是 KMeans 中的 k,表示着我们告诉模型我们要分几类。这是 KMeans 当中唯一一个必填的参数,默认为 8 类,但通常我们的聚类结果会是一个小于 8 的结果。通常,在开始聚类之前,我们并不知道n_clusters 究竟是多少,因此我们要对它进行探索。

当我们拿到一个数据集,如果可能的话,我们希望能够通过绘图先观察一下这个数据集的数据分布,以此来为我们聚类时输入的 n_clusters 做一个参考。

首先,我们来自己创建一个数据集。这样的数据集是我们自己创建,所以是有标签的。

from sklearn.datasets import make_blobs
#自己创建数据集
X, y = make_blobs(n_samples=500,n_features=2,centers=4,random_state=1)

plt.scatter(X[:, 0], X[:, 1],  marker='o' ,s=8 );

在这里插入图片描述

#如果我们想要看见这个点的分布,怎么办?
color = ["red","pink","orange","gray"]
for i in range(4):
    plt.scatter(X[y==i, 0], X[y==i, 1]
    ,marker='o' #点的形状
    ,s=8 #点的大小
    ,c=color[i]
    )
plt.show();

在这里插入图片描述
基于这个分布,我们来使用 Kmeans 进行聚类。首先,我们要猜测一下,这个数据中有几簇?

1.2 重要属性 cluster.labels_

重要属性 labels_,查看聚好的类别,每个样本所对应的类。

from sklearn.cluster import KMeans

n_clusters = 3
cluster = KMeans(n_clusters=n_clusters, random_state=0).fit(X)

y_pred = cluster.labels_
y_pred

在这里插入图片描述

  • KMeans 因为并不需要建立模型或者预测结果,- 因此我们只需要 fit 就能够得到聚类结果了
  • KMeans 也有接口 predict 和 fit_predict:
    predict 表示学习数据 X 并对 X 的类进行预测(对分类器.fit()之后,再预测)
  • fit_predict 不需要分类器.fit()之后都可以预测
  • 对于全数据而言,分类器.fit().predict 的结果= 分类器.fit_predict(X)=cluster.labels
fit_pre = KMeans(n_clusters=3, random_state=0).fit_predict(X)

(cluster.predict(X)==fit_pre).sum()
(fit_pre== cluster.labels_).sum()

500
500

  • 我们什么时候需要 predict 呢? 当数据量太大的时候!

  • 当我们数据量非常大的时候,为了提高模型学习效率,我们可以使用部分数据来帮助我们确认质心

  • 剩下的数据的聚类结果,使用 predict 来调用:

cluster_smallsub = KMeans(n_clusters=n_clusters, random_state=0).fit(X[:200])
sample_pred = cluster_smallsub.predict(X)
y_pred == sample_pred

在这里插入图片描述
但这样的结果,肯定与直接 fit 全部数据会不一致。有时候,当我们不要求那么精确,或者我们的数据量实在太大,那我们可以使用这样的方法。

1.3 重要属性 cluster.cluster_centers_

查看质心:

centroid = cluster.cluster_centers_
centroid
centroid.shape

在这里插入图片描述

1.4 重要属性 cluster.inertia_

查看总距离平方和:

inertia = cluster.inertia_
inertia

1903.4503741659223

如果我们把猜测的簇数换成 4,Inertia 会怎么样?

#如果我们把猜测的簇数换成4,Inertia会怎么样?
cluster_ = KMeans(n_clusters=4, random_state=0).fit(X)

inertia_ = cluster_.inertia_
inertia_

908.3855684760613

换成 5呢?

n_clusters = 5
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_

inertia_

811.0841324482415

换成 5呢?

n_clusters = 6
cluster_ = KMeans(n_clusters=n_clusters, random_state=0).fit(X)
inertia_ = cluster_.inertia_

inertia_

733.153835008308

可以看到,当我们选择分类的簇数值越大时,我们的总距离平方和是越来越小。

那这个时候可能就会有小伙伴要问了,我记得你在上一篇文章中提到下面这一句话:
在这里插入图片描述
那这下要想让聚类效果变好就好办了呀,再调小这个n_clusters值不就得了。

不过讲道理,事情不可能这么简单。大家试想一下,如果有一个样本,数据量为100,我把它分成99个簇,那这样子距离平方和不就快小成0了,但是有什么用呢,对吧,分了等于没分。

所以这个时候我们发现,这个距离平方和越小,代表着每个簇内样本越相似,聚类的效果就越好这句话本身并不完全正确,不能用它来评估我们模型的好坏。

2 聚类算法的模型评估指标:轮廓系数

不同于分类模型和回归,聚类算法的模型评估不是一件简单的事。在分类中,有直接结果(标签)的输出,并且分类的结果有正误之分,所以我们使用预测的准确度,混淆矩阵,ROC 曲线等等指标来进行评估,但无论如何评估,都是在”模型找到正确答案“的能力。而回归中,由于要拟合数据,我们有 S S E SSE SSE均方误差,有损失函数来衡量模型的拟合程度。但这些衡量指标都不能够使用于聚类。

那么究竟如何衡量聚类算法的效果呢?

聚类模型的结果不是某种标签输出,并且聚类的结果是不确定的,其优劣由业务需求或者算法需求来决定,并且没有永远的正确答案。那我们如何衡量聚类的效果呢?

上文我们已经知道了使用Inertia 来作为聚类的衡量指标,Inertia 越小模型越好,这个指标的缺点和极限太大。

那我们可以使用什么指标呢?聚类是没有标签,即不知道真实答案的预测算法,我们必须完全依赖评价簇内的稠密程度(簇内差异小)和簇间的离散程度(簇外差异大)来评估聚类的效果。其中轮廓系数是最常用的聚类算法的评价指标。它是对每个样本来定义的,它能够同时衡量:

  1. 样本与其自身所在的簇中的其他样本的相似度 a,等于样本与同一簇中所有其他点之间的平均距离
  2. 样本与其他簇中的样本的相似度 b,等于样本与下一个最近的簇中的所有点之间的平均距离

根据聚类的要求”簇内差异小,簇外差异大“,我们希望 b 永远大于 a,并且大得越多越好。单个样本的轮廓系数计算为: s = b − a m a x ( a , b ) s=\frac{b-a}{max(a,b)} s=max(a,b)ba这个公式可以解析为: s = { 1 − a / b , i f   a < b 0 , i f   a = b b / a − 1 , i f   a > b s=\begin{cases} 1-a/b, & if \: a<b \\ 0, & if \: a=b \\ b/a-1, & if \: a>b \end{cases} s=1a/b,0,b/a1,ifa<bifa=bifa>b不难发现轮廓系数范围是(-1, 1):

  • 轮廓系数越接近 1:样本与自己所在的簇中的样本很相似,并且与其他簇中的样本不相似。
  • 轮廓系数为 0 时:两个簇中的样本相似度一致,两个簇本应该是一个簇
  • 轮廓系数为负时:样本点与簇外的样本更相似

如果一个簇中的大多数样本具有比较高的轮廓系数,则簇会有较高的总轮廓系数,则整个数据集的平均轮廓系数越高,则聚类是合适的。

如果许多样本点具有低轮廓系数甚至负值,则聚类是不合适的,聚类的超参数 K 可能设定得太大或者太小

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

from sklearn.metrics import silhouette_score
from sklearn.metrics import silhouette_samples

X
y_pred

在这里插入图片描述
在这里插入图片描述

观察一下不同的 K 下,轮廓系数发生什么变化?

cluster = KMeans(n_clusters=3, random_state=0).fit(X)
silhouette_score(X,cluster.labels_)          #计算所有样本的轮廓系数均值。
silhouette_samples(X,cluster.labels_)        #计算每个样本的轮廓系数。

在这里插入图片描述

import pandas as pd
score=[]

#将k值从2变化到20
for i in range(2,20):
    cluster= KMeans(n_clusters=i, random_state=0).fit(X)
    score.append(silhouette_score(X,cluster.labels_))
                 
plt.plot(range(2,20),score)
#给k最大的位置加虚线   #idxmax()[] 取最大索引  因为这边从k=2开始 所以+2
plt.axvline(pd.DataFrame(score).idxmax()[0]+2,ls=':')  # 加一条虚线方便查看

在这里插入图片描述
所以这里应该是在k=2的时候取到最大的轮廓系数。

轮廓系数有很多优点,它在有限空间中取值,使得我们对模型的聚类效果有一个“参考”。并且,轮廓系数对数据的分布没有假设,因此在很多数据集上都表现良好,它在每个簇的分割比较清洗时表现最好。但轮廓系数也有缺陷,比如基于密度进行的聚类,或通过 DBSCAN 获得的聚类结果,如果使用轮廓系数来衡量,则会表现出比真实聚类效果更高的分数。

结束语

好啦,关于无监督学习的部分暂时就先介绍到这里了,如果以后还有机会的话我可能会再跟大家分享其他的一些算法模型,当然也有可能是有监督学习方面的。

到这里,我想介绍的机器学习系列的算法模型也就先告一段落啦。喜欢的朋友也欢迎点赞支持哦,当然不点赞也没关系,知识共享到了就行。


推荐关注的专栏

👨‍👩‍👦‍👦 机器学习:分享机器学习实战项目和常用模型讲解
👨‍👩‍👦‍👦 数据分析:分享数据分析实战项目和常用技能整理

机器学习系列往期回顾

🧡 以❤️简单易懂❤️的语言带你搞懂无监督学习算法【附Python代码详解】机器学习系列之K-Means篇
💚 以❤️简单易懂❤️的语言带你搞懂逻辑回归算法【附Python代码详解】机器学习系列之逻辑回归篇
❤️ 以❤️简单易懂❤️的语言带你搞懂无监督学习算法【附Python代码详解】机器学习系列之K-Means篇
💜 如何搞懂机器学习中的线性回归模型?机器学习系列之线性回归基础篇
🖤 你真的了解分类模型评估指标都有哪些吗?【附Python代码实现】
💙 一文带你用Python玩转决策树 ❤️画出决策树&各种参数详细说明❤️决策树的优缺点又有哪些?
🧡 开始学习机器学习时你必须要了解的模型有哪些?机器学习系列之决策树进阶篇
💚 开始学习机器学习时你必须要了解的模型有哪些?机器学习系列之决策树基础篇
❤️ 以❤️简单易懂❤️的语言带你搞懂有监督学习算法【附Python代码详解】机器学习系列之KNN篇
💜 开始学习机器学习之前你必须要了解的知识有哪些?机器学习系列入门篇


往期内容回顾

🖤 我和关注我的前1000个粉丝“合影”啦!收集前1000个粉丝进行了一系列数据分析,收获满满
💚 MySQL必须掌握的技能有哪些?超细长文带你掌握MySQL【建议收藏】
💜 Hive必须了解的技能有哪些?万字博客带你掌握Hive❤️【建议收藏】


关注我,了解更多相关知识!


CSDN@报告,今天也有好好学习

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐