Python 中的 K 均值聚类:实用指南

2023-10-12

k- 表示聚类方法是一个无监督机器学习用于识别数据集中的数据对象集群的技术。聚类方法有很多种,但是k-means 是最古老、最平易近人的手段之一。这些特征使得实施k- 意味着 Python 中的聚类相当简单,即使对于新手程序员和数据科学家也是如此。

如果您有兴趣了解如何以及何时实施k- 在Python中表示聚类,那么这里就是正确的地方。您将了解一个端到端的示例k- 表示使用Python进行聚类,从预处理数据到评估结果。

在本教程中,您将学习:

  • 什么k- 表示聚类 is
  • 何时使用k- 表示聚类到分析您的数据
  • 如何实施k- 在 Python 中表示聚类scikit学习
  • 如何选择有意义的簇数

单击下面的链接下载您将用于遵循本教程中的示例并实现您自己的代码k-表示集群管道:

下载示例代码: 单击此处获取您将使用的代码了解如何在本教程中编写 k-means 聚类管道。

什么是聚类?

聚类是一组用于将数据划分为组或簇的技术。集群松散地定义为与集群中的其他对象比与其他集群中的数据对象更相似的数据对象组。在实践中,聚类有助于识别数据的两种质量:

  1. 意义
  2. 用处

有意义的集群扩展了领域知识。例如,在医学领域,研究人员将聚类应用于基因表达实验。聚类结果确定了对药物治疗反应不同的患者群体。

有用另一方面,集群作为一个中间步骤数据管道。例如,企业使用集群来进行客户细分。聚类结果将客户分为具有相似购买历史的组,然后企业可以使用这些组来创建有针对性的广告活动。

笔记:您将了解无监督机器学习本教程中的技术。如果您有兴趣了解更多信息监督机器学习技术,然后查看Python 中的逻辑回归.

还有很多其他的聚类的应用,例如文档聚类和社交网络分析。这些应用程序几乎与每个行业相关,使得集群成为任何领域处理数据的专业人员的宝贵技能。

聚类技术概述

您可以使用许多不同的方法来执行聚类 - 事实上,有很多不同的聚类算法类别。每个类别都有其独特的优点和缺点。这意味着某些聚类算法将根据输入数据产生更自然的聚类分配。

笔记:如果您有兴趣了解本节中未提及的聚类算法,请查看聚类算法综合综述对流行技术的精彩回顾。

由于可用选择的数量众多,为数据集选择合适的聚类算法通常很困难。影响这一决策的一些重要因素包括聚类的特征、数据集的特征、异常值的数量和数据对象的数量。

您将通过查看三种流行的聚类算法类别,探索这些因素如何帮助确定哪种方法最合适:

  1. 分区聚类
  2. 层次聚类
  3. 基于密度的聚类

在直接进入之前,值得先从高层次回顾一下这些类别k-方法。您将了解每个类别的优点和缺点,以便为如何做到这一点提供背景信息k-means 适合聚类算法的领域。

分区聚类

分区聚类将数据对象划分为不重叠的组。换句话说,任何对象都不能是多个簇的成员,并且每个簇必须至少有一个对象。

这些技术要求用户指定簇的数量,由多变的 k。许多分区聚类算法通过迭代过程将数据点子集分配到k集群。分区聚类算法的两个示例是k- 意味着和k-medoids。

这些算法都是不确定性的,这意味着即使运行基于相同的输入,它们也可能从两次单独的运行中产生不同的结果。

分区聚类方法有以下几种优势:

  • 当集群有一个球形.
  • 他们是可扩展关于算法复杂度。

他们还有几个弱点:

  • 它们不太适合集群复杂的形状和不同的尺寸。
  • 当与不同的集群一起使用时,它们会崩溃密度.

层次聚类

层次聚类通过构建层次结构来确定集群分配。这是通过自下而上或自上而下的方法实现的:

  • 凝聚聚类是自下而上的方法。它合并最相似的两个点,直到所有点都合并到一个簇中。

  • 分裂聚类是自上而下的方法。它从所有点作为一个簇开始,并在每一步中分割最不相似的簇,直到只剩下单个数据点。

这些方法产生一个基于树的点层次结构,称为树状图。与分区聚类类似,在层次聚类中聚类的数量 (k)通常由用户预先确定。通过在指定深度切割树状图来分配簇,从而产生k较小的树状图组。

与许多分区聚类技术不同,层次聚类是一种确定性的过程,这意味着当您对相同的输入数据运行算法两次时,聚类分配不会改变。

优势层次聚类方法包括以下几种:

  • 他们经常透露有关关系数据对象之间。
  • 他们提供了一个可解释的树状图.

弱点层次聚类方法包括以下几种:

  • 他们是计算成本昂贵关于算法复杂度。
  • 他们敏感于噪音异常值.

基于密度的聚类

基于密度的聚类根据区域中数据点的密度确定聚类分配。聚类被分配在由低密度区域分隔的高密度数据点的地方。

与其他聚类类别不同,此方法不需要用户指定聚类的数量。相反,有一个基于距离的参数充当可调阈值。该阈值决定了点必须有多接近才能被视为集群成员。

基于密度的聚类算法的示例包括具有噪声的应用程序的基于密度的空间聚类,或数据库扫描,和排序点来识别聚类结构,或者光学.

优势基于密度的聚类方法包括以下几种:

  • 他们擅长识别集群非球形.
  • 他们有抵抗力异常值.

弱点基于密度的聚类方法包括以下几种:

  • 他们不太适合高维空间中的聚类.
  • 他们很难识别集群不同的密度.

如何在 Python 中执行 K 均值聚类

在本节中,您将逐步浏览传统版本的k- 表示算法。了解算法的细节是编写算法过程中的基本步骤k- 表示Python中的集群管道。您在本节中学到的内容将帮助您决定是否k-means 是解决您的聚类问题的正确选择。

了解 K 均值算法

传统的k- 意味着只需要几个步骤。第一步是随机选择k质心,其中k等于您选择的簇数。质心是代表簇中心的数据点。

该算法的主要元素通过一个称为期望最大化。这期待步骤将每个数据点分配给最近的质心。然后,最大化步骤计算每个簇的所有点的平均值并设置新的质心。这是传统版本的k- 意味着算法看起来像:

k means algorithm

聚类分配的质量是通过计算误差平方和 (SSE)在质心之后收敛,或匹配上一次迭代的分配。 SSE 定义为每个点到其最近质心的欧氏距离平方和。由于这是对误差的衡量,因此目标k- 意思就是尽量最小化这个值。

下图显示了两次不同运行的前五次迭代中的质心和 SSE 更新k- 表示同一数据集上的算法:

k means centroids iterations

该图的目的是表明质心的初始化是重要的一步。它还强调了使用 SSE 作为集群性能的衡量标准。选择多个簇和初始质心后,重复期望最大化步骤,直到质心位置达到收敛并且不变。

随机初始化步骤导致k- 表示算法为不确定性的,这意味着如果您在同一数据集上运行相同的算法两次,聚类分配将会有所不同。研究人员通常会对整个系统进行多次初始化k-means 算法并从具有最低 SSE 的初始化中选择簇分配。

使用 Python 编写您的第一个 K-Means 聚类代码

值得庆幸的是,有一个强大的实施k- 表示来自流行机器学习包的 Python 聚类scikit学习。您将学习如何编写一个实际的实现k- 表示算法使用算法的 scikit-learn 版本.

笔记:如果您有兴趣更深入地了解如何编写自己的k-Python 中的算法,然后查看Python 数据科学手册.

本教程中的代码需要一些流行的外部Python 包并假设您已经安装了 Python 和 Anaconda。有关在 Windows 中设置 Python 环境以进行机器学习的更多信息,请通读在 Windows 上设置 Python 进行机器学习.

否则,您可以开始安装所需的软件包:

(base) $ conda install matplotlib numpy pandas seaborn scikit-learn ipython
(base) $ conda install -c conda-forge kneed

提供代码以便您可以按照蟒蛇控制台或 Jupyter Notebook。单击提示(>>>)位于每个代码块的右上角,以查看复制粘贴格式的代码。您还可以点击下面的链接下载本文中使用的源代码:

下载示例代码: 单击此处获取您将使用的代码了解如何在本教程中编写 k-means 聚类管道。

此步骤将导入本节中所有代码所需的模块:

>>>
In [1]: import matplotlib.pyplot as plt
   ...: from kneed import KneeLocator
   ...: from sklearn.datasets import make_blobs
   ...: from sklearn.cluster import KMeans
   ...: from sklearn.metrics import silhouette_score
   ...: from sklearn.preprocessing import StandardScaler

您可以使用上面的 GIF 生成数据make_blobs(),scikit-learn 中的一个便利函数,用于生成合成簇。make_blobs()使用这些参数:

  • n_samples是要生成的样本总数。
  • centers是要生成的中心数。
  • cluster_std是标准差。

make_blobs()返回两个值的元组:

  1. 二维 NumPy 数组x 和 y 值对于每个样本
  2. 包含以下内容的一维 NumPy 数组簇标签对于每个样本

笔记:许多 scikit-learn 算法在其实现中严重依赖 NumPy。如果您想了解有关 NumPy 数组的更多信息,请查看看,马,没有 for 循环:使用 NumPy 进行数组编程.

生成合成数据和标签:

>>>
In [2]: features, true_labels = make_blobs(
   ...:     n_samples=200,
   ...:     centers=3,
   ...:     cluster_std=2.75,
   ...:     random_state=42
   ...: )

不确定性机器学习算法,例如k- 手段难以重现。这random_state参数设置为整​​数值,以便您可以遵循教程中提供的数据。实际上,最好离开random_state作为默认值,None.

以下是返回的每个变量的前五个元素make_blobs():

>>>
In [3]: features[:5]
Out[3]:
array([[  9.77075874,   3.27621022],
       [ -9.71349666,  11.27451802],
       [ -6.91330582,  -9.34755911],
       [-10.86185913, -10.75063497],
       [ -8.50038027,  -4.54370383]])

In [4]: true_labels[:5]
Out[4]: array([1, 0, 2, 2, 2])

数据集通常包含以不同单位测量的数字特征,例如身高(以英寸为单位)和体重(以磅为单位)。机器学习算法会认为体重比身高更重要,只是因为体重值更大并且人与人之间的变异性更大。

机器学习算法需要考虑公平竞争环境中的所有特征。这意味着所有特征的值必须转换为相同的比例。

将数值特征转换为使用相同尺度的过程称为特征缩放。这是一个重要的数据预处理大多数基于距离的机器学习算法的步骤,因为它会对算法的性能产生重大影响。

有多种方法可以实现特征缩放。确定哪种技术适合您的数据集的一个好方法是阅读 scikit-learn 的预处理文档.

在此示例中,您将使用StandardScaler班级。此类实现了一种称为特征缩放的类型标准化。标准化对数据集中每个数值特征的值进行缩放或移动,以便这些特征的平均值为 0,标准差为 1:

>>>
In [5]: scaler = StandardScaler()
   ...: scaled_features = scaler.fit_transform(features)

看看这些值是如何缩放的scaled_features:

>>>
In [6]: scaled_features[:5]
Out[6]:
array([[ 2.13082109,  0.25604351],
       [-1.52698523,  1.41036744],
       [-1.00130152, -1.56583175],
       [-1.74256891, -1.76832509],
       [-1.29924521, -0.87253446]])

现在数据已准备好进行聚类。这KMeansscikit-learn 中的 estimator 类是您在将估计器拟合到数据之前设置算法参数的地方。 scikit-learn 实现非常灵活,提供了多个可以调整的参数。

以下是本示例中使用的参数:

  • init控制初始化技术。标准版的k- 表示算法是通过设置来实现的init"random"。将其设置为"k-means++"采用高级技巧来加速收敛,稍后您将使用它。

  • n_clustersk用于聚类步骤。这是最重要的参数k-方法。

  • n_init设置要执行的初始化次数。这很重要,因为两次运行可以收敛于不同的集群分配。 scikit-learn 算法的默认行为是执行十次k- 表示运行并返回 SSE 最低的结果。

  • max_iter设置每次初始化的最大迭代次数k- 表示算法。

实例化KMeans具有以下参数的类:

>>>
In [7]: kmeans = KMeans(
   ...:     init="random",
   ...:     n_clusters=3,
   ...:     n_init=10,
   ...:     max_iter=300,
   ...:     random_state=42
   ...: )

参数名称与用于描述的语言相匹配k- 表示本教程前面的算法。现在既然k- 表示类已​​准备就绪,下一步是将其适合于中的数据scaled_features。这将执行十次运行k- 表示对数据的算法最多300每次运行的迭代次数:

>>>
In [8]: kmeans.fit(scaled_features)
Out[8]:
KMeans(init='random', n_clusters=3, random_state=42)

使用最低 SSE 运行的初始化统计数据可作为以下属性使用:kmeans打电话后.fit():

>>>
In [9]: # The lowest SSE value
   ...: kmeans.inertia_
Out[9]: 74.57960106819854

In [10]: # Final locations of the centroid
   ...: kmeans.cluster_centers_
Out[10]:
array([[ 1.19539276,  0.13158148],
       [-0.25813925,  1.05589975],
       [-0.91941183, -1.18551732]])

In [11]: # The number of iterations required to converge
   ...: kmeans.n_iter_
Out[11]: 6

最后,聚类分配作为一维 NumPy 数组存储在kmeans.labels_。以下是前五个预测标签:

>>>
In [12]: kmeans.labels_[:5]
Out[12]: array([0, 1, 2, 2, 2], dtype=int32)

请注意,前两个数据对象的簇标签的顺序被翻转。订单是[1, 0]true_labels[0, 1]kmeans.labels_即使这些数据对象仍然是其原始集群的成员kmeans.lables_.

这种行为是正常的,因为簇标签的顺序取决于初始化。第一次运行中的簇 0 在第二次运行中可以标记为簇 1,反之亦然。这不会影响聚类评估指标。

选择适当的簇数量

在本节中,您将了解两种常用于评估适当簇数的方法:

  1. 肘法
  2. 轮廓系数

这些通常被用作补充评估技术,而不是一种优于另一种的评估技术。要执行肘法,运行几个k- 均值、增量k每次迭代,并记录 SSE:

>>>
In [13]: kmeans_kwargs = {
   ...:     "init": "random",
   ...:     "n_init": 10,
   ...:     "max_iter": 300,
   ...:     "random_state": 42,
   ...: }
   ...:
   ...: # A list holds the SSE values for each k
   ...: sse = []
   ...: for k in range(1, 11):
   ...:     kmeans = KMeans(n_clusters=k, **kmeans_kwargs)
   ...:     kmeans.fit(scaled_features)
   ...:     sse.append(kmeans.inertia_)

前面的代码块使用了Python的字典解包运算符(**)。要了解有关这个强大的 Python 运算符的更多信息,请查看如何在 Python 中迭代字典.

当您将 SSE 绘制为簇数的函数时,请注意,SSE 随着您的增加而持续减少k。随着添加更多质心,每个点到最近质心的距离将会减小。

SSE 曲线有一个开始弯曲的最佳点,称为肘点。该点的 x 值被认为是误差和簇数量之间的合理权衡。在本例中,肘部位于x=3:

>>>
In [14]:  plt.style.use("fivethirtyeight")
   ...:  plt.plot(range(1, 11), sse)
   ...:  plt.xticks(range(1, 11))
   ...:  plt.xlabel("Number of Clusters")
   ...:  plt.ylabel("SSE")
   ...:  plt.show()

上面的代码产生以下图:

k means elbow method

确定 SSE 曲线中的肘点并不总是那么简单。如果您在选择曲线的肘点时遇到困难,那么您可以使用 Python 包,跪下,以编程方式识别肘点:

>>>
In [15]: kl = KneeLocator(
   ...:     range(1, 11), sse, curve="convex", direction="decreasing"
   ...: )

In [16]: kl.elbow
Out[16]: 3

轮廓系数是集群凝聚力和分离度的度量。它根据两个因素量化数据点与其分配的簇的契合程度:

  1. 数据点与簇中其他点的接近程度
  2. 数据点距离其他簇中的点有多远

轮廓系数值范围介于-11。较大的数字表明样本与其集群的距离比与其他集群的距离更近。

在 scikit-learn 中轮廓系数的实现,将所有样本的平均轮廓系数汇总为一个分数。这silhouette score()函数至少需要两个簇,否则会引发异常。

循环遍历值k再次。这次,不计算 SSE,而是计算轮廓系数:

>>>
In [17]: # A list holds the silhouette coefficients for each k
   ...: silhouette_coefficients = []
   ...:
   ...: # Notice you start at 2 clusters for silhouette coefficient
   ...: for k in range(2, 11):
   ...:     kmeans = KMeans(n_clusters=k, **kmeans_kwargs)
   ...:     kmeans.fit(scaled_features)
   ...:     score = silhouette_score(scaled_features, kmeans.labels_)
   ...:     silhouette_coefficients.append(score)

绘制每个的平均轮廓分数k表明最好的选择是k3因为它有最高分:

>>>
In [18]: plt.style.use("fivethirtyeight")
   ...: plt.plot(range(2, 11), silhouette_coefficients)
   ...: plt.xticks(range(2, 11))
   ...: plt.xlabel("Number of Clusters")
   ...: plt.ylabel("Silhouette Coefficient")
   ...: plt.show()

上面的代码产生以下图:

k means silhouette analysis

最终,您对要使用的集群数量的决定应以领域知识和集群评估指标的组合为指导。

使用先进技术评估集群性能

肘法和轮廓系数评估聚类性能,无需使用地面实况标签。真实标签根据人类或现有算法的分配将数据点分类为组。这些类型的指标尽最大努力建议正确的集群数量,但在没有上下文的情况下使用时可能会产生欺骗。

笔记:在实践中,很少遇到具有真实标签的数据集。

比较时k- 与非球形簇上基于密度的方法相比,肘部方法和轮廓系数的结果很少与人类的直觉相匹配。这种情况凸显了为什么需要先进的聚类评估技术。要可视化示例,请导入以下附加模块:

>>>
In [19]: from sklearn.cluster import DBSCAN
   ...: from sklearn.datasets import make_moons
   ...: from sklearn.metrics import adjusted_rand_score

这次,使用make_moons()生成新月形状的合成数据:

>>>
In [20]: features, true_labels = make_moons(
   ...:     n_samples=250, noise=0.05, random_state=42
   ...: )
   ...: scaled_features = scaler.fit_transform(features)

适合两个k-对新数据使用平均值和 DBSCAN 算法,并通过绘制聚类分配来直观地评估性能Matplotlib:

>>>
In [21]: # Instantiate k-means and dbscan algorithms
   ...: kmeans = KMeans(n_clusters=2)
   ...: dbscan = DBSCAN(eps=0.3)
   ...:
   ...: # Fit the algorithms to the features
   ...: kmeans.fit(scaled_features)
   ...: dbscan.fit(scaled_features)
   ...:
   ...: # Compute the silhouette scores for each algorithm
   ...: kmeans_silhouette = silhouette_score(
   ...:     scaled_features, kmeans.labels_
   ...: ).round(2)
   ...: dbscan_silhouette = silhouette_score(
   ...:    scaled_features, dbscan.labels_
   ...: ).round (2)

打印两种算法的轮廓系数并进行比较。轮廓系数越高表明聚类越好,这在这种情况下会产生误导:

>>>
In [22]: kmeans_silhouette
Out[22]: 0.5

In [23]: dbscan_silhouette
Out[23]: 0.38

轮廓系数较高k- 表示算法。 DBSCAN 算法似乎可以根据数据的形状找到更自然的聚类:

k means clustering crescents

这表明您需要一种更好的方法来比较这两种聚类算法的性能。

如果您有兴趣,可以通过展开下面的框找到上图的代码。

要了解有关使用 Matplotlib 和 Python 绘图的更多信息,请查看使用 Matplotlib 进行 Python 绘图(指南)。以下是如何绘制新月示例中两种算法的比较:

>>>
In [24]: # Plot the data and cluster silhouette comparison
   ...: fig, (ax1, ax2) = plt.subplots(
   ...:     1, 2, figsize=(8, 6), sharex=True, sharey=True
   ...: )
   ...: fig.suptitle(f"Clustering Algorithm Comparison: Crescents", fontsize=16)
   ...: fte_colors = {
   ...:     0: "#008fd5",
   ...:     1: "#fc4f30",
   ...: }
   ...: # The k-means plot
   ...: km_colors = [fte_colors[label] for label in kmeans.labels_]
   ...: ax1.scatter(scaled_features[:, 0], scaled_features[:, 1], c=km_colors)
   ...: ax1.set_title(
   ...:     f"k-means\nSilhouette: {kmeans_silhouette}", fontdict={"fontsize": 12}
   ...: )
   ...:
   ...: # The dbscan plot
   ...: db_colors = [fte_colors[label] for label in dbscan.labels_]
   ...: ax2.scatter(scaled_features[:, 0], scaled_features[:, 1], c=db_colors)
   ...: ax2.set_title(
   ...:     f"DBSCAN\nSilhouette: {dbscan_silhouette}", fontdict={"fontsize": 12}
   ...: )
   ...: plt.show()

由于真实标签是已知的,因此可以使用在评估中考虑标签的聚类指标。您可以使用scikit-learn 实现一个称为调整兰特指数(ARI)。与轮廓系数不同,ARI 使用真实的聚类分配来测量真实标签和预测标签之间的相似性。

比较DBSCAN和DBSCAN的聚类结果k- 表示使用 ARI 作为性能指标:

>>>
In [25]: ari_kmeans = adjusted_rand_score(true_labels, kmeans.labels_)
   ...: ari_dbscan = adjusted_rand_score(true_labels, dbscan.labels_)

In [26]: round(ari_kmeans, 2)
Out[26]: 0.47

In [27]: round(ari_dbscan, 2)
Out[27]: 1.0

ARI 输出值范围为-11。分数接近0.0表示随机分配,并且分数接近1表示完美标记的簇。

根据上面的输出,您可以看到轮廓系数具有误导性。 ARI 表明,与相比,DBSCAN 是合成新月示例的最佳选择k-方法。

有几个评估聚类算法质量的指标。通读scikit-learn 中的实现将帮助您选择合适的聚类评估指标。

如何在 Python 中构建 K-Means 聚类管道

现在您已经有了基本的了解k- 表示Python中的聚类,该执行了k- 表示在真实数据集上进行聚类。这些数据包含来自作者撰写的手稿的基因表达值癌症基因组图谱(TCGA) 泛癌症分析项目研究人员。

881代表五种不同癌症亚型的样本(行)。每个样本都有基因表达值20,531基因(列)。这数据集可以从加州大学欧文分校机器学习存储库,但您可以使用下面的 Python 代码以编程方式获取数据。

要按照下面的示例进行操作,您可以通过单击以下链接下载源代码:

下载示例代码: 单击此处获取您将使用的代码了解如何在本教程中编写 k-means 聚类管道。

在本节中,您将构建一个强大的k- 表示集群管道。由于您将对原始输入数据执行多次转换,因此您的管道也将充当实用的集群框架。

构建 K-Means 聚类管道

假设你想从一个新的开始名称空间,导入构建和评估管道所需的所有模块,包括熊猫西博恩对于更高级的可视化:

>>>
In [1]: import tarfile
   ...: import urllib
   ...:
   ...: import numpy as np
   ...: import matplotlib.pyplot as plt
   ...: import pandas as pd
   ...: import seaborn as sns
   ...:
   ...: from sklearn.cluster import KMeans
   ...: from sklearn.decomposition import PCA
   ...: from sklearn.metrics import silhouette_score, adjusted_rand_score
   ...: from sklearn.pipeline import Pipeline
   ...: from sklearn.preprocessing import LabelEncoder, MinMaxScaler

下载并从 UCI 中提取 TCGA 数据集:

>>>
In [2]: uci_tcga_url = "https://archive.ics.uci.edu/ml/machine-learning-databases/00401/"
   ...: archive_name = "TCGA-PANCAN-HiSeq-801x20531.tar.gz"

   ...: # Build the url
   ...: full_download_url = urllib.parse.urljoin(uci_tcga_url, archive_name)
   ...:
   ...: # Download the file
   ...: r = urllib.request.urlretrieve (full_download_url, archive_name)

   ...: # Extract the data from the archive
   ...: tar = tarfile.open(archive_name, "r:gz")
   ...: tar.extractall()
   ...: tar.close()

下载并解压完成后,您应该有一个如下所示的目录:

TCGA-PANCAN-HiSeq-801x20531/
|
├── data.csv
└── labels.csv

KMeansscikit-learn 中的类需要 NumPy 数组作为参数。 NumPy 包有一个辅助函数将文本文件中的数据作为 NumPy 数组加载到内存中:

>>>
In [3]: datafile = "TCGA-PANCAN-HiSeq-801x20531/data.csv"
   ...: labels_file = "TCGA-PANCAN-HiSeq-801x20531/labels.csv"
   ...:
   ...: data = np.genfromtxt(
   ...:     datafile,
   ...:     delimiter=",",
   ...:     usecols=range(1, 20532),
   ...:     skip_header=1
   ...: )
   ...:
   ...: true_label_names = np.genfromtxt(
   ...:     labels_file,
   ...:     delimiter=",",
   ...:     usecols=(1,),
   ...:     skip_header=1,
   ...:     dtype="str"
   ...: )

查看前五个样本的前三列数据以及前五个样本的标签:

>>>
In [4]: data[:5, :3]
Out[4]:
array([[0.        , 2.01720929, 3.26552691],
       [0.        , 0.59273209, 1.58842082],
       [0.        , 3.51175898, 4.32719872],
       [0.        , 3.66361787, 4.50764878],
       [0.        , 2.65574107, 2.82154696]])


In [5]: true_label_names[:5]
Out[5]: array(['PRAD', 'LUAD', 'PRAD', 'PRAD', 'BRCA'], dtype='<U4')

data变量包含来自的所有基因表达值20,531基因。这true_label_names是每种癌症的类型881样品。第一条记录在data对应于第一个标签true_labels.

标签是包含癌症类型缩写的字符串:

  • BRCA: 乳腺浸润性癌
  • COAD: 结肠腺癌
  • KIRC: 肾肾透明细胞癌
  • LUAD: 肺腺癌
  • PRAD: 前列腺腺癌

要在评估方法中使用这些标签,您首先需要将缩写转换为整数LabelEncoder:

>>>
In [6]: label_encoder = LabelEncoder()

In [7]: true_labels = label_encoder.fit_transform(true_label_names)

In [8]: true_labels[:5]
Out[8]: array([4, 3, 4, 4, 0])

自从label_encoder已拟合数据,您可以看到使用表示的独特类.classes_。将数组的长度存储到变量中n_clusters供以后使用:

>>>
In [9]: label_encoder.classes_
Out[9]: array(['BRCA', 'COAD', 'KIRC', 'LUAD', 'PRAD'], dtype='<U4')

In [10]: n_clusters = len(label_encoder.classes_)

在实际的机器学习管道中,数据在输入聚类算法之前通常会经历多个序列的转换。您在本教程的前面部分了解了这些转换步骤之一(特征缩放)的重要性。同样重要的数据转换技术是降维,通过删除或组合特征来减少数据集中的特征数量。

降维技术有助于解决机器学习算法的问题维度的诅咒。简而言之,随着特征数量的增加,特征空间变得稀疏。这种稀疏性使得算法很难在高维空间中找到彼此靠近的数据对象。由于基因表达数据集已超过20,000特征,它有资格作为降维的一个很好的候选者。

主成分分析(PCA)是众多降维技术中的一种。 PCA 通过将输入数据投影到称为成分。这些组件通过输入数据特征的线性组合来捕获输入数据的可变性。

笔记:PCA 的完整描述超出了本教程的范围,但您可以在scikit-learn 用户指南.

下一个代码块向您介绍以下概念scikit-learn 管道。 scikit-learnPipeline类是机器学习管道抽象思想的具体实现。

您的基因表达数据的格式不适合KMeans类,所以你需要构建一个预处理管道。该管道将​​实施替代方案StandardScaler类称为MinMaxScaler用于特征缩放。你用MinMaxScaler当你不要假设所有特征的形状都遵循正态分布。

预处理管道的下一步将实现PCA执行降维的类:

>>>
In [11]: preprocessor = Pipeline(
   ...:     [
   ...:         ("scaler", MinMaxScaler()),
   ...:         ("pca", PCA(n_components=2, random_state=42)),
   ...:     ]
   ...: )

现在您已经构建了一个管道来处理数据,您将构建一个单独的管道来执行k- 表示聚类。您将覆盖以下默认参数KMeans班级:

  • 在里面:你将使用"k-means++"代替"random"确保质心初始化时它们之间有一定的距离。在大多数情况下,这将是一个改进"random".

  • n_init:您将增加初始化次数以确保找到稳定的解决方案。

  • 最大迭代次数:您将增加每次初始化的迭代次数以确保k- 均值将收敛。

构建k- 表示使用用户定义的参数对管道进行聚类KMeans构造函数:

>>>
In [12]: clusterer = Pipeline(
   ...:    [
   ...:        (
   ...:            "kmeans",
   ...:            KMeans(
   ...:                n_clusters=n_clusters,
   ...:                init="k-means++",
   ...:                n_init=50,
   ...:                max_iter=500,
   ...:                random_state=42,
   ...:            ),
   ...:        ),
   ...:    ]
   ...: )

Pipeline类可以链接起来形成更大的管道。构建端到端k- 表示通过传递集群管道"preprocessor""clusterer"管道至Pipeline:

>>>
In [13]: pipe = Pipeline(
   ...:     [
   ...:         ("preprocessor", preprocessor),
   ...:         ("clusterer", clusterer)
   ...:     ]
   ...: )

呼唤.fit()data当参数执行所有管道步骤时data:

>>>
In [14]: pipe.fit(data)
Out[14]:
Pipeline(steps=[('preprocessor',
                 Pipeline(steps=[('scaler', MinMaxScaler()),
                                 ('pca',
                                  PCA(n_components=2, random_state=42))])),
                ('clusterer',
                 Pipeline(steps=[('kmeans',
                                  KMeans(max_iter=500, n_clusters=5, n_init=50,
                                         random_state=42))]))])

管道执行所有必要的步骤来执行k- 意味着对基因表达数据进行聚类!取决于您的Python REPL, .fit()可以打印管道的摘要。管道内定义的对象可以使用其步骤名称进行访问。

通过计算轮廓系数来评估性能:

>>>
In [15]: preprocessed_data = pipe["preprocessor"].transform(data)

In [16]: predicted_labels = pipe["clusterer"]["kmeans"].labels_

In [17]: silhouette_score(preprocessed_data, predicted_labels)
Out[17]: 0.5118775528450304

也计算 ARI,因为地面实况集群标签可用:

>>>
In [18]: adjusted_rand_score(true_labels, predicted_labels)
Out[18]: 0.722276752060253

如前所述,每个聚类性能指标的范围从 -1 到 1。轮廓系数 0 表示聚类彼此明显重叠,轮廓系数 1 表示聚类分离良好。 ARI 分数为 0 表示聚类标签是随机分配的,ARI 分数为 1 表示真实标签和预测标签形成相同的聚类。

既然你指定了n_components=2在PCA步骤中k-表示聚类管道,您还可以在真实标签和预测标签的上下文中可视化数据。使用 pandas DataFrame 和 seaborn 绘图库绘制结果:

>>>
In [19]: pcadf = pd.DataFrame(
   ...:     pipe["preprocessor"].transform(data),
   ...:     columns=["component_1", "component_2"],
   ...: )
   ...:
   ...: pcadf["predicted_cluster"] = pipe["clusterer"]["kmeans"].labels_
   ...: pcadf["true_label"] = label_encoder.inverse_transform(true_labels)

In [20]: plt.style.use("fivethirtyeight")
   ...: plt.figure(figsize=(8, 8))
   ...:
   ...: scat = sns.scatterplot(
   ...:     "component_1",
   ...:     "component_2",
   ...:     s=50,
   ...:     data=pcadf,
   ...:     hue="predicted_cluster",
   ...:     style="true_label",
   ...:     palette="Set2",
   ...: )
   ...:
   ...: scat.set_title(
   ...:     "Clustering results from TCGA Pan-Cancer\nGene Expression Data"
   ...: )
   ...: plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.0)
   ...:
   ...: plt.show()

情节如下:

k means clustering pca

聚类的视觉表示证实了两个聚类评估指标的结果。你们的管道性能非常好。聚类仅略有重叠,并且聚类分配比随机分配要好得多。

调整 K-Means 聚类管道

你的第一个k-表示集群管道表现良好,但仍有改进的空间。这就是为什么您在构建管道时遇到了麻烦:您可以调整参数以获得最理想的聚类结果。

的过程参数调整包括依次更改算法参数的输入值之一并记录结果。在参数调整过程结束时,您将获得一组性能分数,给定参数的每个新值都有一个分数。参数调整是最大限度提高集群管道性能的强大方法。

通过设置PCA范围n_components=2,您将所有特征压缩为两个组件或维度。该值便于在二维图上可视化。但仅使用两个组件意味着 PCA 步骤将无法捕获所有解释方差输入数据的。

解释方差衡量 PCA 转换数据与实际输入数据之间的差异。这n_components 和解释方差之间的关系可以在图中进行可视化,以显示 PCA 中需要多少组件才能捕获输入数据中一定百分比的方差。您还可以使用集群性能指标来评估需要多少组件才能获得满意的集群结果。

在此示例中,您将使用集群性能指标来确定 PCA 步骤中适当数量的组件。这Pipeline在这种情况下,阶级是强大的。它允许您使用执行基本参数调整for循环.

迭代一个范围n_components并记录每次迭代的评估指标:

>>>
In [21]: # Empty lists to hold evaluation metrics
   ...: silhouette_scores = []
   ...: ari_scores = []
   ...: for n in range(2, 11):
   ...:     # This set the number of components for pca,
   ...:     # but leaves other steps unchanged
   ...:     pipe["preprocessor"]["pca"].n_components = n
   ...:     pipe.fit(data)
   ...:
   ...:     silhouette_coef = silhouette_score(
   ...:         pipe["preprocessor"].transform(data),
   ...:         pipe["clusterer"]["kmeans"].labels_,
   ...:     )
   ...:     ari = adjusted_rand_score(
   ...:         true_labels,
   ...:         pipe["clusterer"]["kmeans"].labels_,
   ...:     )
   ...:
   ...:     # Add metrics to their lists
   ...:     silhouette_scores.append(silhouette_coef)
   ...:     ari_scores.append(ari)

将评估指标绘制为以下函数的图n_components可视化添加组件与性能之间的关系k- 表示聚类结果:

>>>
In [22]: plt.style.use("fivethirtyeight")
   ...: plt.figure(figsize=(6, 6))
   ...: plt.plot(
   ...:     range(2, 11),
   ...:     silhouette_scores,
   ...:     c="#008fd5",
   ...:     label="Silhouette Coefficient",
   ...: )
   ...: plt.plot(range(2, 11), ari_scores, c="#fc4f30", label="ARI")
   ...:
   ...: plt.xlabel("n_components")
   ...: plt.legend()
   ...: plt.title("Clustering Performance as a Function of n_components")
   ...: plt.tight_layout()
   ...: plt.show()

上面的代码生成一个图,显示性能指标作为函数n_components:

k means performance evaluation

从这个图中可以得出两个结论:

  1. 轮廓系数线性减小。轮廓系数取决于点之间的距离,因此随着维数的增加,稀疏性也会增加。

  2. ARI当您添加组件时,性能会显着提高。似乎开始逐渐减少n_components=7,因此这将是用于呈现此管道的最佳聚类结果的值。

与大多数机器学习决策一样,您必须平衡优化聚类评估指标与聚类任务的目标。在聚类标签可用的情况下(如本教程中使用的癌症数据集的情况),ARI 是一个合理的选择。 ARI 量化您的管道重新分配集群标签的准确度。

另一方面,轮廓系数是探索性聚类的不错选择,因为它有助于识别子簇。这些子集群需要进行额外的调查,这可以带来新的重要见解。

结论

您现在知道如何执行k- 在 Python 中表示聚类。你的决赛k-意味着聚类管道能够使用真实世界的基因表达数据对患有不同癌症类型的患者进行聚类。您可以使用在这里学到的技术对自己的数据进行聚类,了解如何获得最佳聚类结果,并与他人分享见解。

在本教程中,您学习了:

  • 流行什么聚类技术是以及何时使用它们
  • 什么是k-均值算法 is
  • 如何实施k- 表示聚类在Python中
  • 如何评价聚类算法的性能
  • 如何构建和调整稳健的k- 表示集群管道在Python中
  • 如何分析并呈现聚类结果来自k-均值算法

您还快速浏览了 scikit-learn,这是一个可访问且可扩展的工具,用于实现k- 在 Python 中表示聚类。如果您想重现上面看到的示例,请务必单击以下链接下载源代码:

下载示例代码: 单击此处获取您将使用的代码了解如何在本教程中编写 k-means 聚类管道。

现在您已准备好表演k- 意味着对您感兴趣的数据集进行聚类。请务必在下面的评论中分享您的结果!

笔记:本教程中使用的数据集来自 UCI 机器学习存储库。 Dua, D. 和 Graff, C. (2019)。UCI 机器学习存储库。加利福尼亚州欧文:加利福尼亚大学信息与计算机科学学院。

原始数据集由癌症基因组图谱泛癌症分析项目维护。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Python 中的 K 均值聚类:实用指南 的相关文章

  • 朴素分类器 matlab

    在 matlab 中测试朴素分类器时 即使我在相同的样本数据上进行训练和测试 我也会得到不同的结果 我想知道我的代码是否正确 是否有人可以帮助解释这是为什么 dimensionality reduction columns 6 U S V
  • 实例标准化与批量标准化

    据我所知 批量归一化通过将激活转向单位高斯分布来帮助加快训练速度 从而解决梯度消失问题 批量归一化行为在训练 使用每个批次的平均值 var 和测试时间 使用训练阶段的最终运行平均值 var 时应用不同 另一方面 实例归一化充当本文提到的对比
  • Tensorflow:np数组的next_batch函数

    我的火车数据为 xTrain numpy asarray 100 1 5 6 yTrain numpy asarray 200 2 10 12 如何定义 next batch size 方法以从训练数据中获取随机元素的 size 个数 您可
  • Node2vec 的工作原理

    我一直在读关于node2vec https cs stanford edu jure pubs node2vec kdd16 pdf嵌入算法 我有点困惑它是如何工作的 作为参考 node2vec 由 p 和 q 参数化 并通过模拟来自节点的
  • 使用 libsvm 交叉验证后重新训练

    我知道交叉验证用于选择好的参数 找到它们后 我需要在不使用 v 选项的情况下重新训练整个数据 但我面临的问题是 在使用 v 选项训练后 我得到了交叉验证精度 例如 85 没有模型 我看不到 C 和 gamma 的值 在这种情况下我该如何重新
  • 如何在 k 均值中使用欧氏距离以外的不同距离公式

    我正在处理纬度经度数据 我必须根据两点之间的距离进行聚类 现在两个不同点之间的距离是 ACOS SIN lat1 SIN lat2 COS lat1 COS lat2 COS lon2 lon1 6371 我想在 R 中使用 k 均值 有什
  • 如何制作 U 矩阵?

    为了可视化一个 U 矩阵到底是如何构建的自组织映射 http en wikipedia org wiki Self organizing map 更具体地说 假设我有一个 3x3 节点的输出网格 已经经过训练 我如何从中构造一个 U 矩阵
  • tf.keras.utils.image_dataset_from_directory,但标签来自 csv?

    请告诉我哪里出错了 我正在研究 Kaggle 狗品种分类挑战 我想尝试 one hot 编码与标签编码 图像未在图像目录中拆分 因此我无法将 推断 与 tf keras utils image dataset from directory
  • R 中 svm 特征选择的示例

    我正在尝试使用 R 包在 SVM 中应用特征选择 例如递归特征选择 我已经安装了 Weka 它支持 LibSVM 中的特征选择 但我还没有找到任何 SVM 语法的示例或类似的东西 一个简短的例子会有很大的帮助 功能rfe in the ca
  • 具有多个输入的 Keras TimeDistributed 层

    我正在尝试使以下代码行正常工作 low encoder out TimeDistributed AutoregressiveDecoder X tf embeddings Where AutoregressiveDecoder是一个需要两个
  • 使用sklearn进行多标签特征选择

    我希望使用 sklearn 对多标签数据集执行特征选择 我想要获得最终的功能集across标签 然后我将在另一个机器学习包中使用它 我打算使用我看到的方法here https stackoverflow com questions 1640
  • 如何在 R 中绘制预测的子集?

    我有一个简单的 R 脚本来根据文件创建预测 自 2014 年以来就有数据记录 但我在尝试实现以下两个目标时遇到了困难 仅绘制预测信息的子集 从 11 2017 开始 以特定格式包含月份和年份 即 6 月 17 日 这是链接到dataset
  • 预测测试图像时出现错误 - 无法重塑大小数组

    我正在尝试使用 TensorFlow 和 Keras 在 Python 中进行图像识别 并且我已经关注了下面的博客 https stackabuse com image recognition in python with tensorfl
  • Java 的支持向量机?

    我想用Java编写一个 智能监视器 它可以随时发出警报detects即将到来的性能问题 我的 Java 应用程序正在以结构化格式将数据写入日志文件
  • 如何重现 Ridge(normalize=True) 的行为?

    这段代码 from sklearn pipeline import make pipeline from sklearn preprocessing import StandardScaler from sklearn linear mod
  • 为什么LeNet5使用32×32图像作为输入?

    我知道mnist数据集中的手写数字图像是28 28 但是为什么LeNet5中的输入是32 32 您的问题已在原纸 http yann lecun com exdb publis pdf lecun 98 pdf 卷积步骤始终采用比前一层的特
  • 编辑 Jupyter Notebook 时 VS Code 中缺少“在选择中查找”

    使用 Jupyter Notebook 时 VSCode 中缺少 在选择中查找 按钮 它会减慢开发速度 所以我想请问有人知道如何激活它吗 第一张图显示了在 python 文件中的搜索 替换 第二张图显示了笔记本电脑中缺少的按钮 Python
  • randomForest 包在删除一个预测类时的奇怪行为

    我正在运行一个随机森林模型 它产生的结果从统计角度来看对我来说完全没有意义 因此我确信有些东西mustrandomForest 包的代码出现错误 至少在模型的本次迭代中 预测 左侧变量是具有 3 种可能结果的政党 ID 民主党 独立党 共和
  • 具有定制损失函数的随机森林

    我是机器学习领域的初学者 对于一个项目 我必须在随机森林分类中使用自定义损失函数 到目前为止我一直使用 scikit 通过 scikit 实现这一点的建议会更有帮助 损失函数 分类树中的基尼杂质和熵 在 scikit 的 tree pyx
  • 使用 scikit-learn 进行二次采样 + 分类

    我正在使用 Scikit learn 进行二元分类任务 并且我有 0 级 有 200 个观察值 第 1 类 有 50 个观察值 而且因为我有不平衡的数据 我想抽取多数类的随机子样本 其中观察数量与少数类相同 并且希望使用新获得的数据集作为分

随机推荐

  • Python 中使用 spaCy 进行自然语言处理

    目录 NLP 和 spaCy 简介 安装spaCy 已处理文本的 Doc 对象 句子检测 spaCy 中的令牌 停用词 词形还原 词频 词性标注 可视化 使用 displaCy 预处理函数 使用 spaCy 基于规则的匹配 使用 spaCy
  • 关于盖尔·阿恩·耶勒

    关于盖尔 阿恩 耶勒 推特 GitHub 经过多年思考这个问题我们在哪里 我现在与数据科学和机器学习在挪威奥斯陆 早些时候 我接触过从 Basic Awk Java 和 C 到 Assembly 的所有语言 现在 我很幸运能够用 Pytho
  • 计算机视觉技术

    人脸检测是一种计算机视觉技术 能够识别数字图像中的人脸 这对人类来说很容易 但计算机需要精确的指令 这些图像可能包含许多非人脸的物体 例如建筑物 汽车 动物等 它与其他涉及人脸的计算机视觉技术 例如面部识别 分析和跟踪 不同 面部识别涉及将
  • 2021 年 6 月 16 日

    主持人大卫 阿莫斯回答会员的问题 在这次会议上 我们讨论了 Python 新闻和更新 为什么不能在续行符后发表评论 如何使用括号隐式连接字符串 一些替代的 Python REPL 是什么 如何开始为开源做出贡献 在哪里可以找到 Python
  • 惯用的熊猫:你可能不知道的技巧和功能

    pandas 是一个用于分析 数据处理和数据科学的基础库 这是一个巨大的项目 具有大量的可选性和深度 在本课程中 您将了解如何使用一些较少使用但惯用的 pandas 功能 使您的代码具有更好的可读性 多功能性和速度 包含内容 11 Less
  • 继承和内部原理:Python 中的面向对象编程

    Python 包含编写面向对象代码的机制 其中 数据和对该数据的操作被结构化在一起 这class关键词这就是在 Python 中创建这些结构的方式 类的定义可以是 基于其他类 允许创建层次结构和 促进代码重用 这种机制称为继承 在本课程中
  • 创建“附近商店”视图

    我们的应用程序后端的几乎所有内容都已完成 在本视频中 我们将重点关注前端 以便为用户提供一种查看其位置附近的商店的方法 在本视频中 我们将要做的是在附近的商店应用程序中创建一个 Django 视图 然后通过主 urls py 将用户路由到该
  • 用于近似重复检测的指纹图像

    目录 我们会做什么 什么是图像指纹 哈希 为什么不能使用md5 sha 1等 图像指纹可以用在哪里 我们需要什么库 第 1 步 对数据集进行指纹识别 第 2 步 搜索数据集 结果 改进我们的算法 概括 这是 Adrian Rosebrock
  • Django 和 AJAX 表单提交 – 更多练习

    目录 设置事件处理程序 创建 AJAX 请求 更新 Django 视图 处理回调 更新 DOM 下一步是什么 这是 Real Python 和 Mr 的合作作品 内森 尼科尔斯 于 2014 年 9 月 5 日更新 使应用程序更加 REST
  • 设置您的工作环境

    要下载本课程的数据集 您可以访问真正的 Python GitHub 存储库 有关本课程所涵盖概念的更多信息 您可以查看 Python 虚拟环境 入门 Visual Studio Code 中的 Python 开发 Jupyter Noteb
  • Python 中的字典

    目录 定义字典 访问字典值 字典键与列表索引 增量构建字典 字典键的限制 对字典值的限制 运算符和内置函数 Built in Dictionary Methods d clear d get d items d keys d values
  • 纯Python直方图

    当您准备绘制直方图时 最简单的方法是不要考虑箱 而是报告每个值出现的次数 频率表 一条蟒蛇字典非常适合这项任务 gt gt gt gt gt gt Need not be sorted necessarily gt gt gt a 0 1
  • 了解日期和时间是混乱的

    日期和时间并不是简单的事情 尤其是现在大多数计算都是远程完成的 无法保证计算机和用户位于同一个地方 由于管理夏令时和时区的规则不是静态的 这一事实使情况变得更加复杂 在本课程中 您将探索所有奇怪的边缘情况 并了解程序员通常如何处理它们
  • 掌握Python的内置时间模块

    蟒蛇time模块提供了多种方式代表时间代码中 例如对象 数字和字符串 它还提供除表示时间之外的功能 例如在代码执行期间等待和测量代码的效率 本课程将引导您了解最常用的函数和对象time 完成本课程后 您将能够 理解处理日期和时间的核心概念
  • 关于奥尔德伦·桑托斯

    关于奥尔德伦 桑托斯 个人网站 大家好 我是 Aldren Santos 担任自由平面设计师 插画师已有 3 年了 我的任务是尽我所能 让这个网站变得更加精彩 我真心希望我的插图能够吸引您通过我们团队辛勤工作的这些教程学习 Python 的
  • 编写和测试 Python 函数:面试练习(概述)

    无论您是想在编码面试中取得好成绩 还是只是想提高您的开发技能 解决编码挑战可以帮助您成长为一名程序员 在这个真实的 Python 代码对话中 Philipp 向 Martin 提出挑战 要求他编写一个函数 将字符串中的每个字符加倍 通过他们
  • 引导 Django 项目

    有关本课程所涵盖概念的更多信息 您可以查看 如何设置 Django 项目 真正的Python文章 使用 Django 和 Python 构建个人日记 真正的Python文章 以下是本课程中使用的命令行片段 mkdir portfolio p
  • Python 石头剪刀布:命令行游戏(概述)

    游戏编程是学习如何编程的好方法 您可以使用许多在现实世界中看到的工具 此外您还可以玩游戏来测试您的结果 开始 Python 游戏编程之旅的理想游戏是剪刀石头布 在本课程中 您将学习如何 自己编写代码剪刀石头布游戏 接受用户输入input 使
  • 2021 年 4 月 21 日

    主持人大卫 阿莫斯回答会员的问题 在这次会议上 我们讨论了 Real Python 的新功能 在哪里可以找到要阅读的代码以提高您的 Python 技能 为什么 0xfor x in 1 2 3 回报 15 数据科学 Django 和 Fla
  • Python 中的 K 均值聚类:实用指南

    目录 What Is Clustering 聚类技术概述 分区聚类 层次聚类 基于密度的聚类 How to Perform K Means Clustering in Python 了解 K 均值算法 使用 Python 编写您的第一个 K