Python精进系列: K-Means 聚类算法调用库函数和手动实现对比分析

一、引言

在机器学习领域,聚类分析是一种重要的无监督学习方法,用于将数据集中的样本划分为不同的组或簇,使得同一簇内的样本具有较高的相似性,而不同簇之间的样本具有较大的差异性。K-Means 聚类算法是最常用的聚类算法之一,它以其简单性和高效性在数据挖掘、图像分割、模式识别等领域得到了广泛应用。本文将详细介绍 K-Means 聚类算法,并分别给出调用现成函数和不调用任何现成函数实现 K-Means 聚类的代码示例,同时对两种实现方式进行对比分析。

二、K-Means 聚类算法原理

K-Means 聚类算法的基本思想是通过迭代的方式将数据集中的样本分配到 k k k 个不同的簇中,使得每个样本到其所属簇的质心(即聚类中心)的距离之和最小。具体步骤如下:

  1. 初始化:随机选择 k k k 个样本作为初始的聚类中心。
  2. 分配样本:计算每个样本到各个聚类中心的距离,将样本分配到距离最近的聚类中心所在的簇。
  3. 更新聚类中心:对于每个簇,计算该簇内所有样本的均值,将其作为新的聚类中心。
  4. 重复步骤 2 和 3:直到聚类中心不再发生显著变化或达到最大迭代次数。

三、调用现成函数实现 K-Means 聚类

(一)代码实现

import numpy as np
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

# 超参数设置
n_samples = 100  # 样本数量
n_features = 3  # 数据维度
k = 3  # 聚类数量

# 生成一些示例数据
X = np.random.rand(n_samples, n_features)

# 创建 K-Means 模型,指定聚类的数量
kmeans = KMeans(n_clusters=k, random_state=0).fit(X)

# 获取聚类标签
labels = kmeans.labels_

# 获取聚类中心
centroids = kmeans.cluster_centers_

# 若为二维数据,进行可视化
if n_features == 2:
    plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis')
    plt.scatter(centroids[:, 0], centroids[:, 1], marker='X', s=200, c='red')
    plt.title('K-Means Clustering with scikit-learn')
    plt.show()
elif n_features == 3:
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=labels, cmap='viridis')
    ax.scatter(centroids[:, 0], centroids[:, 1], centroids[:, 2], marker='X', s=200, c='red')
    plt.title('K-Means Clustering with scikit-learn (3D)')
    plt.show()
else:
    print(f"数据维度为 {n_features},无法直接可视化。")

(二)代码解释

这段代码使用了 Python 的 numpysklearnmatplotlib 库来实现 K-Means 聚类。具体步骤如下:

  1. 导入必要的库:导入 numpy 用于数值计算,sklearn.cluster.KMeans 用于实现 K-Means 聚类,matplotlib.pyplot 用于数据可视化。
  2. 设置超参数:设置样本数量 n_samples、数据维度 n_features 和聚类数量 k
  3. 生成示例数据:使用 np.random.rand 函数生成随机样本数据。
  4. 创建并训练 K-Means 模型:使用 KMeans 类创建模型,并调用 fit 方法对数据进行训练。
  5. 获取聚类结果:通过 labels_ 属性获取每个样本的聚类标签,通过 cluster_centers_ 属性获取聚类中心。
  6. 数据可视化:根据数据维度,使用 matplotlib 库对聚类结果进行可视化。

四、不调用任何现成函数实现 K-Means 聚类

(一)代码实现

import numpy as np
import matplotlib.pyplot as plt

def kmeans(X, k, max_iterations=100):
    # 随机初始化聚类中心
    centroids = X[np.random.choice(X.shape[0], k, replace=False)]

    for _ in range(max_iterations):
        # 计算每个样本到每个聚类中心的距离
        distances = np.array([np.linalg.norm(X - centroid, axis=1) for centroid in centroids])

        # 分配每个样本到最近的聚类中心
        labels = np.argmin(distances, axis=0)

        # 更新聚类中心
        new_centroids = np.array([X[labels == i].mean(axis=0) for i in range(k)])

        # 判断聚类中心是否收敛
        if np.allclose(centroids, new_centroids):
            break

        centroids = new_centroids

    return labels, centroids

# 超参数设置
n_samples = 100  # 样本数量
n_features = 3  # 数据维度
k = 3  # 聚类数量

# 生成一些示例数据
X = np.random.rand(n_samples, n_features)

# 调用自定义的 K-Means 函数
labels, centroids = kmeans(X, k)

# 若为二维数据,进行可视化
if n_features == 2:
    plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis')
    plt.scatter(centroids[:, 0], centroids[:, 1], marker='X', s=200, c='red')
    plt.title('K-Means Clustering without Library')
    plt.show()
elif n_features == 3:
    fig = plt.figure()
    ax = fig.add_subplot(111, projection='3d')
    ax.scatter(X[:, 0], X[:, 1], X[:, 2], c=labels, cmap='viridis')
    ax.scatter(centroids[:, 0], centroids[:, 1], centroids[:, 2], marker='X', s=200, c='red')
    plt.title('K-Means Clustering without Library (3D)')
    plt.show()
else:
    print(f"数据维度为 {n_features},无法直接可视化。")

(二)代码解释

这段代码手动实现了 K-Means 聚类算法,不依赖任何现成的聚类库。具体步骤如下:

  1. 定义 kmeans 函数:该函数接受数据矩阵 X、聚类数量 k 和最大迭代次数 max_iterations 作为参数。
  2. 随机初始化聚类中心:从数据集中随机选择 k k k 个样本作为初始的聚类中心。
  3. 迭代更新聚类中心:在每次迭代中,计算每个样本到各个聚类中心的距离,将样本分配到距离最近的聚类中心所在的簇,并更新聚类中心。
  4. 判断收敛条件:如果聚类中心不再发生显著变化,则提前终止迭代。
  5. 返回聚类结果:返回每个样本的聚类标签和最终的聚类中心。
  6. 生成示例数据并调用 kmeans 函数:设置超参数,生成随机样本数据,调用 kmeans 函数进行聚类。
  7. 数据可视化:根据数据维度,使用 matplotlib 库对聚类结果进行可视化。

五、两种实现方式的对比

(一)调用现成函数的优势

  • 代码简洁:使用 sklearn 库的 KMeans 类,只需几行代码就可以完成聚类任务,无需手动实现复杂的迭代过程。
  • 功能丰富sklearn 库提供了许多额外的功能,如随机种子设置、初始化方法选择、收敛判断标准等,可以方便地进行参数调整和模型优化。
  • 性能优化sklearn 库的实现经过了优化,具有较高的计算效率和稳定性。

(二)手动实现的优势

  • 深入理解算法原理:手动实现 K-Means 聚类算法可以帮助我们更好地理解算法的原理和细节,提高对机器学习算法的掌握程度。
  • 灵活性高:手动实现可以根据具体需求对算法进行定制和扩展,例如修改距离度量方法、更新聚类中心的方式等。

六、总结

K-Means 聚类算法是一种简单而有效的聚类方法,在实际应用中具有广泛的用途。本文分别介绍了调用现成函数和不调用任何现成函数实现 K-Means 聚类的方法,并对两种实现方式进行了对比分析。在实际应用中,我们可以根据具体需求选择合适的实现方式。如果追求代码简洁和功能丰富,建议使用现成的机器学习库;如果需要深入理解算法原理或进行定制化开发,则可以手动实现算法。

你可能感兴趣的:(Python,精进系列,算法,python,kmeans)