K-means 聚类:Python 和 Scikit-learn实现
一、说明
虽然深度学习算法无疑是当今最流行的机器学习算法,但还有更多算法。聚类是一种机器学习,您不需要向模型提供训练集,而是尝试在运行时从数据集中得出特征,以便以不同的方式构造数据集。它属于无监督机器学习算法。
二、无监督K 均值聚类
2.1 关于K均值聚类的一般概念
K 均值聚类就是这样一种算法,我们将在今天的博客文章中对其进行深入研究。我们首先通过研究生成聚类所需的步骤来了解它是什么。然后我们来看看惯性度量,它用于计算算法是否需要继续或是否已经完成,即是否存在收敛。接下来我们来看看收敛本身,以及在什么情况下 K 均值聚类可能没有用。
理论部分之后是通过 Python 脚本进行实际实现的。它提供了使用 Scikit-learn 实现 K-means 聚类的示例,Scikit-learn 是当今最流行的机器学习 Python 库之一。总的来说,我们将通过一个示例来了解 K-means 聚类的理论组成部分。
在本文中,我们将学习……
让我们来看看!
2.2 什么是 K 均值聚类?
假设我们有一个数据集 X,其中包含许多 n 维向量x_1,x_2,…,x_n。假设 n = 2,则x_1可以是 [3.12, 4.14]。将其映射到二维空间(即平面)上,可得出以下结果:
图片来自作者。
假设我们上面抽象描述的向量以“blob”的形式构建,就像我们合并了两个温度测量数据集一样——一个是来自恒温器的测量值,测量室内温度约为 20 摄氏度,另一个是来自冰箱的测量值,测量温度约为 4 摄氏度。纵轴显示今天的温度,而横轴显示昨天同一时间的温度。
这可能就是冰箱测量温度的要点。整套测量结果如下:
现在,假设我们想知道一个样本是属于“冰箱”集群还是“室温”集群。从视觉上看,我们可以轻松判断它是属于其中之一:两组数据点之间有足够的空间,可以准确评估它是放在冰箱里还是放在客厅里。
但是如果我们想通过算法来做到这一点该怎么办?
K-均值聚类在这种情况下很有用。它使我们能够获得以下结果:
图片来自作者
对于每个样本,都可以清楚知道它是室温样本(红色)还是冰箱温度样本(蓝色),这是通过算法确定的!
三、多维度K 均值聚类
3.1 多维度K均值聚类一般描述
现在,虽然这是一个非常简单的例子,但 K 均值聚类可以应用于更困难的问题,即具有多个聚类的问题,甚至具有多维数据的问题(稍后会详细介绍)。让我们首先看看什么是 K 均值聚类。
为此,我们求助于我们的老朋友维基百科 – 并从相对抽象的定义中挑选出最重要的方面:
K 均值聚类是一种将 n 个观测值划分为 k
个聚类的方法,其中每个观测值属于具有最接近均值的聚类(聚类中心或聚类质心),并作为该聚类的原型。
维基百科(2020)
让我们把它分解成我们可以原子理解的部分:
让我们看看该算法是如何工作的。
3.2 K 均值聚类算法
为此,我们求助于 Scikit-learn 网站,该网站用简单的英语很好地解释了这一点:
确实是一个非常简单、优雅但功能强大的算法!
3.1 惯性/聚类内平方和标准
虽然我们用非常简单的方式表达了上述算法,但我们也可以用更数学的方式表达。例如,我们可以将 K 均值聚类视为一种试图最小化惯性或簇内平方和标准的算法(Scikit-learn,nd)。它通过选择质心来实现这一点——因此,选择最小化该值的质心。
这个值是如何确定的?如下所示(Scikit-learn,nd):
让我们分解一下这个公式。
第一部分,即 sigma 符号,本质上告诉你这个值是数据集中所有 n 个样本的某个值的总和。目前没有什么特别的。但这是什么?
最小值。更准确地说,是每个样本与特定簇的平均值之间的差值的平方的最小值。
当此值最小化时,集群被称为内部连贯(Scikit-learn,nd),并且“质心校正”步骤中的移动将很低。如果它为零,则它已收敛到最佳值。在 Scikit 中,我们指定一个特定的阈值,如果惯性较低,则认为算法已经收敛。这加快了拟合过程。
3.3 关于 K 均值聚类的收敛性
只要有足够的时间,K 均值聚类就会始终收敛到最优值(Scikit-learn,nd)。但是,这不一定是全局最优值——它也可以是局部最优值。根据 Scikit-learn(nd),这完全取决于质心的初始化;也就是说,我们是否使用random初始化策略或k-means++。
在随机情况下,很明显初始化有时会产生非常好的结果,经常产生中等到好的结果,有时产生非常差的结果。这就是抛硬币来决定是否包含样本的问题。至少从形象上讲是这样。
该k-means++策略的工作方式略有不同。让我们再次看一下随机策略,以解释为什么它通常效果更好。在随机策略中,没有人可以确保所选样本彼此相距甚远。尽管几率很小,但它们可能都非常接近。在这种情况下,收敛将成为一项非常困难且耗时的工作(Scikit-learn,nd)。我们显然不希望这样。
K-means++ 确保质心“[通常] 彼此远离”(Scikit-learn,nd)。可以想象,这在收敛性方面,尤其是收敛速度方面,被证明是一个实质性的改进(Scikit-learn,nd)。
四、K 均值聚类的缺点:不选择它的情况?
如果您查看此页面,您会发现 K 均值聚类并不总是有效。具体来说,在以下情况下效果不佳(Scikit-learn,nd):
在天真地做出“仅仅”让它起作用的决定之前,请仔细考虑应用 K-means。它可能根本不起作用!
五、使用 Python 和 Scikit-learn 实现 K-means 聚类
现在我们已经介绍了有关 K 均值聚类的大部分理论,我想是时候给出一些用 Python 编写的示例代码了。为此,我们使用了库scikit-learn,它是应用机器学习模型最广为人知的库之一。具体来说,它广泛用于应用相对传统的机器学习类型,即非深度学习模型。
5.1 原始试验数据生成
让我们打开文件管理器。创建一个名为的文件scikit-blobs.py。在代码编辑器中打开此文件并确保系统上安装了以下依赖项:
Scikit-learn
Matplotlib
Numpy
如果是,那就太好了!我们继续。
生成凸和各向同性的簇
在使用 Scikit-learn 应用 K 均值聚类之前,我们要做的第一件事是生成那些凸且各向同性的聚类。用更通俗的英语来说,就是那些可分离且宽度和高度相等的聚类。不用英语,用可视化来表达,我的意思是:
啊,原来你的意思就是你现在可能会这么想的😂哎呀。
为了使其工作,我们首先必须声明我们的导入:
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
这些就是今天要导入的所有文件,而不仅仅是用于生成 blob 的文件(这才是make_blobs导入文件)。此外,我们还KMeans从 Scikit-learn导入了numpy用于数字处理的库,以及用于可视化集群的PyPlot库matplotlib(即生成上面的可视化文件)。
现在我们已经指定了导入,是时候设置一些配置选项了:
# Configuration options
num_samples_total = 1000
cluster_centers = [(20,20), (4,4)]
num_classes = len(cluster_centers)
这些真的很简单:
然后我们生成数据:
# Generate data
X, targets = make_blobs(n_samples = num_samples_total, centers = cluster_centers, n_features = num_classes, center_box=(0, 1), cluster_std = 2)
生成数据只是调用make_blobsScikit-learn 中的定义,它完成了所有艰苦的工作。我们指定之前配置的中心和样本数量,以及特征数量。我们将标准差设置为 2 – 这意味着我们在这两个位置生成的样本分布在中心周围,偏差很可能为正/负 2。
如果您希望保存数据以便以后可以重复使用确切位置(例如,在您想要生成不同的可视化效果的情况下),您可以添加此代码 – 它只是保存数据并立即重新加载,以便您相应地应用。但这不是必需的。
np.save('./clusters.npy', X)
X = np.load('./clusters.npy')
5.2 应用 K 均值聚类算法
是时候应用 K 均值聚类了!首先,我们实例化算法:
# Fit K-means with Scikit
kmeans = KMeans(init='k-means++', n_clusters=num_classes, n_init=10)
kmeans.fit(X)
在这里,我们选择一个初始化策略(要么是 ,random要么k-means++是 ,其中后者可能会节省我们的计算时间,所以我们选择它)、聚类的数量和 ,n_init其作用如下:
使用不同质心种子运行 k-means 算法的次数。最终结果将是 n_init 次连续运行中惯性最好的输出。
Sklearn.cluster.KMeans(nd)
一旦我们完成了这一点,就该实际拟合数据并生成聚类预测了:
# Predict the cluster for all the samples
P = kmeans.predict(X)
就这样——K 均值聚类完成了!如果你希望生成两个类以不同颜色显示的可视化效果,你可能还需要添加以下内容:
# Generate scatter plot for training data
colors = list(map(lambda x: '#3b4cc0' if x == 1 else '#b40426', P))
plt.scatter(X[:,0], X[:,1], c=colors, marker="o", picker=True)
plt.title('Two clusters of data')
plt.xlabel('Temperature yesterday')
plt.ylabel('Temperature today')
plt.show()
5.3 完整模型代码
如果您希望立即获得完整的模型代码 — 当然,这也是可能的。如下所示:
import matplotlib.pyplot as plt
import numpy as np
from sklearn.datasets import make_blobs
from sklearn.cluster import KMeans
# Configuration options
num_samples_total = 1000
cluster_centers = [(20,20), (4,4)]
num_classes = len(cluster_centers)
# Generate data
X, targets = make_blobs(n_samples = num_samples_total, centers = cluster_centers, n_features = num_classes, center_box=(0, 1), cluster_std = 2)
np.save('./clusters.npy', X)
X = np.load('./clusters.npy')
# Fit K-means with Scikit
kmeans = KMeans(init='k-means++', n_clusters=num_classes, n_init=10)
kmeans.fit(X)
# Predict the cluster for all the samples
P = kmeans.predict(X)
# Generate scatter plot for training data
colors = list(map(lambda x: '#3b4cc0' if x == 1 else '#b40426', P))
plt.scatter(X[:,0], X[:,1], c=colors, marker="o", picker=True)
plt.title('Two clusters of data')
plt.xlabel('Temperature yesterday')
plt.ylabel('Temperature today')
plt.show()
结果
结果非常清楚,不是吗:
几乎立即(考虑到样本数量少且斑点高度可分离的事实),我们首次执行了 K 均值聚类!
六、总结
在这篇博文中,我们研究了使用 Python 和 Scikit-learn 进行 K-means 聚类。更具体地说,我们研究了一组问题:
K 均值聚类究竟是什么?
K 均值聚类如何工作?
K 均值聚类的惯性是什么?
使用 K 均值聚类有什么缺点;即什么时候使用它是不明智的?
如何使用 Python 和 Scikit-learn 实现 K-means 聚类?你能举个例子吗?
希望您从今天的文章中有所收获!欢迎并鼓励您提出任何评论、建议或问题。
作者:无水先生