机器学习 – 聚类算法

机器学习 – 聚类算法聚类是一种无监督学习方法 用于将数据集划分成若干个组 簇 使得同一簇内的数据点之间的相似度尽可能高 而不同簇之间的相似度尽可能低

大家好,欢迎来到IT知识分享网。

聚类算法概述

聚类是一种无监督学习方法,用于将数据集划分成若干个组(簇),使得同一簇内的数据点之间的相似度尽可能高,而不同簇之间的相似度尽可能低。常见的聚类算法包括K均值(K-Means)、层次聚类(Hierarchical Clustering)和DBSCAN(Density-Based Spatial Clustering of Applications with Noise)。

1. K均值聚类(K-Means Clustering)

K均值是一种迭代的聚类算法,目标是将数据集分为K个簇,使得簇内数据点的总方差(即距离平方和)最小。其步骤如下:

  1. 随机选择K个初始质心(Centroid)。
  2. 将每个数据点分配给距离最近的质心,形成K个簇。
  3. 计算每个簇的质心(即簇内所有数据点的平均值)。
  4. 重复步骤2和3,直到质心不再变化或达到最大迭代次数。
K均值算法的数学描述
  1. 初始化质心: μ 1 , μ 2 , … , μ K \mu_1, \mu_2, \ldots, \mu_K μ1,μ2,,μK
  2. 对于每个数据点 xi,计算其到每个质心的距离,并分配给最近的质心:

c i = arg ⁡ min ⁡ j ∥ x i − μ j ∥ 2 c_i = \arg\min_{j} \| x_i – \mu_j \|^2 ci=argjminxiμj2

  1. 重新计算质心:

μ j = 1 ∣ C j ∣ ∑ x i ∈ C j x i \mu_j = \frac{1}{|C_j|} \sum_{x_i \in C_j} x_i μj=Cj1xiCjxi

其中, Cj 是第 j 个簇的所有数据点集合。

Python实现案例
from sklearn.cluster import KMeans import numpy as np import matplotlib.pyplot as plt # 生成示例数据 np.random.seed(42) X = np.random.rand(100, 2) # K均值聚类 kmeans = KMeans(n_clusters=3, random_state=42) kmeans.fit(X) y_kmeans = kmeans.predict(X) # 绘制聚类结果 plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis') centers = kmeans.cluster_centers_ plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.75) plt.show() 

2. 层次聚类(Hierarchical Clustering)

层次聚类是一种基于树形结构的聚类方法,主要分为两种:凝聚层次聚类(Agglomerative Clustering)和分裂层次聚类(Divisive Clustering)。凝聚层次聚类从每个数据点开始,每次合并最相似的簇,直到所有点都在一个簇内;而分裂层次聚类则从一个大簇开始,每次将最不相似的簇分开,直到每个点成为一个簇。

距离计算方法
  1. 单链接(Single Linkage):最短距离
    d single ( C i , C j ) = min ⁡ x ∈ C i , y ∈ C j ∥ x − y ∥ d_{\text{single}}(C_i, C_j) = \min_{x \in C_i, y \in C_j} \|x – y\| dsingle(Ci,Cj)=xCi,yCjminxy
  2. 全链接(Complete Linkage):最长距离
    d complete ( C i , C j ) = max ⁡ x ∈ C i , y ∈ C j ∥ x − y ∥ d_{\text{complete}}(C_i, C_j) = \max_{x \in C_i, y \in C_j} \|x – y\| dcomplete(Ci,Cj)=xCi,yCjmaxxy
  3. 平均链接(Average Linkage):平均距离
    d average ( C i , C j ) = 1 ∣ C i ∣ ∣ C j ∣ ∑ x ∈ C i ∑ y ∈ C j ∥ x − y ∥ d_{\text{average}}(C_i, C_j) = \frac{1}{|C_i||C_j|} \sum_{x \in C_i} \sum_{y \in C_j} \|x – y\| daverage(Ci,Cj)=Ci∣∣Cj1xCiyCjxy
Python实现案例
from scipy.cluster.hierarchy import dendrogram, linkage import matplotlib.pyplot as plt from sklearn.datasets import make_blobs # 生成示例数据 X, y = make_blobs(n_samples=50, centers=3, random_state=42) # 层次聚类 Z = linkage(X, 'ward') # 绘制树状图 plt.figure(figsize=(10, 7)) dendrogram(Z) plt.show() 

3. DBSCAN(Density-Based Spatial Clustering of Applications with Noise)

DBSCAN是一种基于密度的聚类方法,能够有效处理噪声和发现任意形状的簇。其主要思想是通过两个参数:最小样本数(minPts)和半径(ε),来定义簇的密度。

DBSCAN算法步骤
  1. 对于每个数据点,计算其ε邻域内的点的数量。
  2. 如果ε邻域内的点的数量大于或等于minPts,则将该点标记为核心点,并将其ε邻域内的所有点标记为同一簇。
  3. 对于非核心点,如果其ε邻域内包含至少一个核心点,则将其分配到该核心点所在的簇,否则标记为噪声点。
Python实现案例
from sklearn.cluster import DBSCAN import numpy as np import matplotlib.pyplot as plt # 生成示例数据 np.random.seed(42) X = np.random.rand(100, 2) # DBSCAN聚类 db = DBSCAN(eps=0.1, min_samples=5).fit(X) labels = db.labels_ # 绘制聚类结果 plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis') plt.show() 

聚类算法的评估方法

1. 轮廓系数(Silhouette Coefficient)

轮廓系数用于评估单个数据点的聚类质量,取值范围为[-1, 1]。对于数据点 i ,定义如下:

s ( i ) = b ( i ) − a ( i ) max ⁡ ( a ( i ) , b ( i ) ) s(i) = \frac{b(i) – a(i)}{\max(a(i), b(i))} s(i)=max(a(i),b(i))b(i)a(i)

其中, a(i) 是数据点 i 到其簇内其他点的平均距离, b(i) 是数据点 i 到最近的其他簇的平均距离。

计算示例
from sklearn.metrics import silhouette_score # 计算轮廓系数 score = silhouette_score(X, y_kmeans) print(f'Silhouette Score: { 
     score}') 

2. Davies-Bouldin指数(Davies-Bouldin Index)

Davies-Bouldin指数用于评估聚类的紧密性和分离度,值越小表示聚类效果越好。定义如下:

D B = 1 K ∑ i = 1 K max ⁡ j ≠ i ( σ i + σ j d ( μ i , μ j ) ) DB = \frac{1}{K} \sum_{i=1}^{K} \max_{j \ne i} \left( \frac{\sigma_i + \sigma_j}{d(\mu_i, \mu_j)} \right) DB=K1i=1Kj=imax(d(μi,μj)σi+σj)

其中, \sigmai 是第 i 个簇内的数据点到质心的平均距离, d ( μ i , μ j ) d(\mu_i, \mu_j) d(μi,μj)是簇 i 和簇 j 的质心之间的距离。

计算示例
from sklearn.metrics import davies_bouldin_score # 计算Davies-Bouldin指数 db_index = davies_bouldin_score(X, y_kmeans) print(f'Davies-Bouldin Index: { 
     db_index}') 

3. Calinski-Harabasz指数(Calinski-Harabasz Index)

Calinski-Harabasz指数(或方差比准则)用于评估聚类的紧密性和分离度,值越大表示聚类效果越好。定义如下:

C H = tr ( B k ) / ( K − 1 ) tr ( W k ) / ( n − K ) CH = \frac{ \text{tr}(B_k) / (K – 1) }{ \text{tr}(W_k) / (n – K) } CH=tr(Wk)/(nK)tr(Bk)/(K1)

其中, tr ( B k ) \text{tr}(B_k) tr(Bk)是簇间离散度矩阵的迹, tr ( W k ) \text{tr}(W_k) tr(Wk)是簇内离散度矩阵的迹, K 是簇的数量, n 是数据点的数量。

下面我们详细推导这一指标。

类内散度矩阵(Within-cluster scatter matrix)

类内散度矩阵 Wk 定义为每个簇内的样本点到该簇质心(centroid)的平方欧氏距离之和。对于第 i 个簇,类内散度矩阵 Wi 定义如下:

W i = ∑ x ∈ C i ( x − c i ) ( x − c i ) T W_i = \sum_{x \in C_i} (x – c_i)(x – c_i)^T Wi=xCi(xci)(xci)T

其中:

  • ( Ci ) 是第 ( i ) 个簇的样本集合。
  • ( ci ) 是第 ( i ) 个簇的质心。

类内散度矩阵 ( W_k ) 是所有簇的类内散度矩阵之和:

[ W_k = \sum_{i=1}^{k} W_i ]

类间散度矩阵(Between-cluster scatter matrix)

类间散度矩阵 ( Bk ) 定义为各簇质心到所有样本点的整体质心的平方欧氏距离之和。整体质心 ( c ) 是所有样本点的平均值:

c = 1 N ∑ i = 1 N x i c = \frac{1}{N} \sum_{i=1}^{N} x_i c=N1i=1Nxi

类间散度矩阵 ( Bk ) 定义如下:

B k = ∑ i = 1 k n i ( c i − c ) ( c i − c ) T B_k = \sum_{i=1}^{k} n_i (c_i – c)(c_i – c)^T Bk=i=1kni(cic)(cic)T

其中:

  • ( ni ) 是第 ( i ) 个簇中的样本数量。

迹(Trace)

矩阵的迹是指矩阵主对角线元素之和。对于类内散度矩阵 ( Wk ) 和类间散度矩阵 ( Bk ) 的迹分别为:

Tr ( W k ) = ∑ i = 1 k ∑ x ∈ C i ∥ x − c i ∥ 2 \text{Tr}(W_k) = \sum_{i=1}^{k} \sum_{x \in C_i} \|x – c_i\|^2 Tr(Wk)=i=1kxCixci2
Tr ( B k ) = ∑ i = 1 k n i ∥ c i − c ∥ 2 \text{Tr}(B_k) = \sum_{i=1}^{k} n_i \|c_i – c\|^2 Tr(Bk)=i=1knicic2

Calinski-Harabasz Score的计算

根据以上定义和公式,CH Score的计算公式为:

CH Score = Tr ( B k ) Tr ( W k ) × N − k k − 1 \text{CH Score} = \frac{\text{Tr}(B_k)}{\text{Tr}(W_k)} \times \frac{N – k}{k – 1} CH Score=Tr(Wk)Tr(Bk)×k1Nk

其中:

  • Tr ( B k ) \text{Tr}(B_k) Tr(Bk) 表示各簇之间的离散度
  • Tr ( W k ) \text{Tr}(W_k) Tr(Wk) 表示各簇内部的紧密度
  • N − k k − 1 \frac{N – k}{k – 1} k1Nk 是一个标准化因子,用于调整不同聚类数的影响

Calinski-Harabasz Score通过比较类间距离和类内距离来评估聚类的效果,得分越高,表示聚类效果越好,即簇内数据越紧密,簇间数据越分散。这一指标在聚类分析中常用于选择最优聚类数。

计算示例
from sklearn.metrics import calinski_harabasz_score # 计算Calinski-Harabasz指数 ch_index = calinski_harabasz_score(X, y_kmeans) print(f'Calinski-Harabasz Index: { 
     ch_index}') 

4. 简单实现案例

结合上述所有内容,以下是一个完整的示例代码,用于生成数据、进行聚类并评估聚类效果:

from sklearn.cluster import KMeans from sklearn.datasets import make_blobs from sklearn.metrics import silhouette_score, davies_bouldin_score, calinski_harabasz_score import matplotlib.pyplot as plt # 生成示例数据 X, y = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=42) # K均值聚类 k means = KMeans(n_clusters=4, random_state=42) kmeans.fit(X) y_kmeans = kmeans.predict(X) # 评估聚类效果 sil_score = silhouette_score(X, y_kmeans) db_score = davies_bouldin_score(X, y_kmeans) ch_score = calinski_harabasz_score(X, y_kmeans) print(f'Silhouette Score: { 
     sil_score}') print(f'Davies-Bouldin Index: { 
     db_score}') print(f'Calinski-Harabasz Index: { 
     ch_score}') # 绘制聚类结果 plt.scatter(X[:, 0], X[:, 1], c=y_kmeans, s=50, cmap='viridis') centers = kmeans.cluster_centers_ plt.scatter(centers[:, 0], centers[:, 1], c='red', s=200, alpha=0.75) plt.show() 

常见问题

1. 选择合适的聚类算法

问题:如何选择合适的聚类算法?
解决方案

  • 数据量较大且簇的形状较规则时,选择K均值(K-Means)。
  • 需要处理噪声和发现任意形状的簇时,选择DBSCAN。
  • 需要层次化展示簇时,选择层次聚类(Hierarchical Clustering)。
  • 可以通过尝试不同的算法,并使用评估指标(如轮廓系数、Davies-Bouldin指数等)来比较不同算法的效果。

2. 确定聚类数目(K值)

问题:如何确定K均值中的K值?
解决方案

  • 使用肘部法则(Elbow Method):绘制K值与聚类总误差平方和(Sum of Squared Errors, SSE)的图,选择“SSE陡降后逐渐平缓”的拐点处。
  • 使用轮廓系数(Silhouette Coefficient):尝试不同的K值,选择轮廓系数最高的K值。
  • 使用Calinski-Harabasz指数:选择Calinski-Harabasz指数最高的K值。

3. 处理异常点和噪声

问题:如何处理数据中的异常点和噪声?
解决方案

  • 使用DBSCAN,可以有效识别并处理噪声点。
  • 对数据进行预处理,删除或修正明显的异常点。
  • 使用鲁棒的聚类算法,如均值漂移(Mean Shift)。

4. 数据标准化

问题:是否需要对数据进行标准化?
解决方案

  • 通常需要对数据进行标准化,特别是当数据具有不同的量纲和单位时。
  • 可以使用标准化(StandardScaler)或归一化(MinMaxScaler)等方法。

5. 高维数据处理

问题:如何处理高维数据?
解决方案

  • 使用降维技术,如主成分分析(PCA)或t-SNE,将数据降维到2D或3D进行可视化。
  • 使用核方法(如核PCA)保留非线性结构。
  • 使用高维聚类算法,如谱聚类(Spectral Clustering)。

6. 聚类结果的不稳定性

问题:聚类结果不稳定,如何解决?
解决方案

  • 对初始质心进行多次随机选择,取平均结果。
  • 使用聚类结果的可视化(如t-SNE)观察结果的稳定性。
  • 使用稳健的初始化方法(如k-means++)。

7. 聚类结果的解释性

问题:如何解释聚类结果?
解决方案

  • 对每个簇内的特征进行统计分析(如均值、方差等),找出每个簇的特征模式。
  • 使用决策树等方法对聚类结果进行解释。
  • 可视化簇的中心和边界,帮助理解聚类结果。

8. 处理类别不平衡

问题:如何处理类别不平衡的问题?
解决方案

  • 在聚类前对数据进行采样(如过采样或欠采样)以平衡类别。
  • 使用加权聚类方法,对少数类赋予更高的权重。
  • 使用适应性方法,根据类别分布调整算法参数。

9. 评估聚类效果

问题:如何评估聚类效果?
解决方案

  • 使用内在评估指标,如轮廓系数、Davies-Bouldin指数、Calinski-Harabasz指数等。
  • 使用外在评估指标(如果有真实标签),如Rand指数、调整兰德指数(Adjusted Rand Index, ARI)等。
  • 可视化聚类结果,观察聚类效果。

10. 大规模数据聚类

问题:如何处理大规模数据的聚类?
解决方案

  • 使用Mini-Batch K均值算法,对大规模数据进行小批量迭代更新。
  • 使用分布式聚类算法(如Apache Spark中的MLlib库)。
  • 对数据进行采样,先在小规模数据上聚类,再扩展到全数据集。

示例代码实现案例

下面是一些示例代码,展示如何解决上述部分问题:

import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans, DBSCAN from sklearn.preprocessing import StandardScaler from sklearn.metrics import silhouette_score, calinski_harabasz_score # 生成示例数据 X, _ = make_blobs(n_samples=1000, centers=4, cluster_std=0.60, random_state=42) # 数据标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 确定K值(肘部法) sse = [] for k in range(1, 11): kmeans = KMeans(n_clusters=k, random_state=42) kmeans.fit(X_scaled) sse.append(kmeans.inertia_) plt.plot(range(1, 11), sse, marker='o') plt.xlabel('Number of clusters') plt.ylabel('SSE') plt.show() # K均值聚类 kmeans = KMeans(n_clusters=4, random_state=42) kmeans.fit(X_scaled) y_kmeans = kmeans.predict(X_scaled) # DBSCAN聚类 dbscan = DBSCAN(eps=0.3, min_samples=5) y_dbscan = dbscan.fit_predict(X_scaled) # 评估聚类效果 silhouette_kmeans = silhouette_score(X_scaled, y_kmeans) ch_kmeans = calinski_harabasz_score(X_scaled, y_kmeans) print(f'Silhouette Score (K-Means): { 
     silhouette_kmeans}') print(f'Calinski-Harabasz Index (K-Means): { 
     ch_kmeans}') # 绘制K均值聚类结果 plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=y_kmeans, cmap='viridis', s=50) plt.title('K-Means Clustering') plt.show() # 绘制DBSCAN聚类结果 plt.scatter(X_scaled[:, 0], X_scaled[:, 1], c=y_dbscan, cmap='viridis', s=50) plt.title('DBSCAN Clustering') plt.show() 

以上代码展示了如何标准化数据、确定K值、执行K均值和DBSCAN聚类,并评估聚类效果。这些步骤和技术可以帮助解决许多常见的聚类问题。

更多问题咨询

Cos机器人

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/136075.html

(0)
上一篇 2025-06-30 12:20
下一篇 2025-06-30 12:33

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信