DAY17 机器学习聚类-
·
首先在聚类之前需要进行标准化
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans, DBSCAN, AgglomerativeClustering
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
import matplotlib.pyplot as plt
import seaborn as sns
# 标准化数据(聚类前通常需要标准化)
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# X_scaled
## 聚类评估指标介绍
以下是三种常用的聚类效果评估指标,分别用于衡量聚类的质量和簇的分离与紧凑程度:
### 1. 轮廓系数 (Silhouette Score)
- **定义**:轮廓系数衡量每个样本与其所属簇的紧密程度以及与最近其他簇的分离程度。
- **取值范围**:[-1, 1]
- 轮廓系数越接近 **1**,表示样本与其所属簇内其他样本很近,与其他簇很远,聚类效果越好。
- 轮廓系数越接近 **-1**,表示样本与其所属簇内样本较远,与其他簇较近,聚类效果越差(可能被错误分类)。
- 轮廓系数接近 **0**,表示样本在簇边界附近,聚类效果无明显好坏。
- **使用建议**:选择轮廓系数最高的 `k` 值作为最佳簇数量。
### 2. CH 指数 (Calinski-Harabasz Index)
- **定义**:CH 指数是簇间分散度与簇内分散度之比,用于评估簇的分离度和紧凑度。
- **取值范围**:[0, +∞)
- CH 指数越大,表示簇间分离度越高,簇内紧凑度越高,聚类效果越好。
- 没有固定的上限,值越大越好。
- **使用建议**:选择 CH 指数最高的 `k` 值作为最佳簇数量。
### 3. DB 指数 (Davies-Bouldin Index)
- **定义**:DB 指数衡量簇间距离与簇内分散度的比值,用于评估簇的分离度和紧凑度。
- **取值范围**:[0, +∞)
- DB 指数越小,表示簇间分离度越高,簇内紧凑度越高,聚类效果越好。
- 没有固定的上限,值越小越好。
- **使用建议**:选择 DB 指数最低的 `k` 值作为最佳簇数量。
KMEANS聚类
## KMeans 聚类
### 算法原理
KMeans 是一种基于距离的聚类算法,需要预先指定聚类个数,即 `k`。其核心步骤如下:
1. 随机选择 `k` 个样本点作为初始质心(簇中心)。
2. 计算每个样本点到各个质心的距离,将样本点分配到距离最近的质心所在的簇。
3. 更新每个簇的质心为该簇内所有样本点的均值。
4. 重复步骤 2 和 3,直到质心不再变化或达到最大迭代次数为止。
### 确定簇数的方法:肘部法
- **肘部法(Elbow Method)** 是一种常用的确定 `k` 值的方法。
- 原理:通过计算不同 `k` 值下的簇内平方和(Within-Cluster Sum of Squares, WCSS),绘制 `k` 与 WCSS 的关系图。
- 选择标准:在图中找到“肘部”点,即 WCSS 下降速率明显减缓的 `k` 值,通常认为是最佳簇数。这是因为增加 `k` 值带来的收益(WCSS 减少)在该点后变得不显著。
### KMeans 算法的优缺点
#### 优点
- **简单高效**:算法实现简单,计算速度快,适合处理大规模数据集。
- **适用性强**:对球形或紧凑的簇效果较好,适用于特征空间中簇分布较为均匀的数据。
- **易于解释**:聚类结果直观,簇中心具有明确的物理意义。
#### 缺点
- **需预先指定 `k` 值**:对簇数量 `k` 的选择敏感,不合适的 `k` 会导致聚类效果较差。
- **对初始质心敏感**:初始质心的随机选择可能导致结果不稳定或陷入局部最优(可通过 KMeans++ 初始化方法缓解)。
- **对噪声和异常值敏感**:异常值可能会显著影响质心的位置,导致聚类结果失真。
- **不适合非球形簇**:对非线性可分或形状复杂的簇效果较差,无法处理簇密度不均的情况。
首先要去寻找一个合适的K值,K值对于整个后续的聚类非常重要哦,方法可以按照下面这个来看,一次性绘制多个子图可以更快速的进行判断
import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score
import matplotlib.pyplot as plt
import seaborn as sns
# 评估不同 k 值下的指标
k_range = range(2, 11) # 测试 k 从 2 到 10
inertia_values = []
silhouette_scores = []
ch_scores = []
db_scores = []
for k in k_range:
kmeans = KMeans(n_clusters=k, random_state=42)
kmeans_labels = kmeans.fit_predict(X_scaled)
inertia_values.append(kmeans.inertia_) # 惯性(肘部法则)
silhouette = silhouette_score(X_scaled, kmeans_labels) # 轮廓系数
silhouette_scores.append(silhouette)
ch = calinski_harabasz_score(X_scaled, kmeans_labels) # CH 指数
ch_scores.append(ch)
db = davies_bouldin_score(X_scaled, kmeans_labels) # DB 指数
db_scores.append(db)
print(f"k={k}, 惯性: {kmeans.inertia_:.2f}, 轮廓系数: {silhouette:.3f}, CH 指数: {ch:.2f}, DB 指数: {db:.3f}")
# 绘制评估指标图
plt.figure(figsize=(15, 10))
# 肘部法则图(Inertia)
plt.subplot(2, 2, 1)
plt.plot(k_range, inertia_values, marker='o')
plt.title('肘部法则确定最优聚类数 k(惯性,越小越好)')
plt.xlabel('聚类数 (k)')
plt.ylabel('惯性')
plt.grid(True)
# 轮廓系数图
plt.subplot(2, 2, 2)
plt.plot(k_range, silhouette_scores, marker='o', color='orange')
plt.title('轮廓系数确定最优聚类数 k(越大越好)')
plt.xlabel('聚类数 (k)')
plt.ylabel('轮廓系数')
plt.grid(True)
# CH 指数图
plt.subplot(2, 2, 3)
plt.plot(k_range, ch_scores, marker='o', color='green')
plt.title('Calinski-Harabasz 指数确定最优聚类数 k(越大越好)')
plt.xlabel('聚类数 (k)')
plt.ylabel('CH 指数')
plt.grid(True)
# DB 指数图
plt.subplot(2, 2, 4)
plt.plot(k_range, db_scores, marker='o', color='red')
plt.title('Davies-Bouldin 指数确定最优聚类数 k(越小越好)')
plt.xlabel('聚类数 (k)')
plt.ylabel('DB 指数')
plt.grid(True)
plt.tight_layout()
plt.show()

选择好合适的k值之后就继续进行聚类了,聚类的结果需要用图表进行呈现
# 提示用户选择 k 值
selected_k = 6
# 使用选择的 k 值进行 KMeans 聚类
kmeans = KMeans(n_clusters=selected_k, random_state=42)
kmeans_labels = kmeans.fit_predict(X_scaled)
X['KMeans_Cluster'] = kmeans_labels
# 使用 PCA 降维到 2D 进行可视化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
# KMeans 聚类结果可视化
plt.figure(figsize=(6, 5))
sns.scatterplot(x=X_pca[:, 0], y=X_pca[:, 1], hue=kmeans_labels, palette='viridis')
plt.title(f'KMeans Clustering with k={selected_k} (PCA Visualization)')
plt.xlabel('PCA Component 1')
plt.ylabel('PCA Component 2')
plt.show()
# 打印 KMeans 聚类标签的前几行
print(f"KMeans Cluster labels (k={selected_k}) added to X:")
print(X[['KMeans_Cluster']].value_counts())


DBSCAN 的聚类效果较差,此处不展示
下面看看层次聚类
## 层次聚类
Agglomerative Clustering 是一种自底向上的层次聚类方法,初始时每个样本是一个簇,然后逐步合并最相似的簇,直到达到指定的簇数量或满足停止条件。由于它需要指定簇数量(类似于 KMeans),我将通过测试不同的簇数量 n_clusters 来评估聚类效果,并使用轮廓系数(Silhouette Score)、CH 指数(Calinski-Harabasz Index)和 DB 指数(Davies-Bouldin Index)作为评估指标。
import numpy as np
import pandas as pd
from sklearn.cluster import AgglomerativeClustering
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.metrics import silhouette_score, calinski_harabasz_score, davies_bouldin_score
import matplotlib.pyplot as plt
import seaborn as sns
# 标准化数据
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)
# 评估不同 n_clusters 下的指标
n_clusters_range = range(2, 11) # 测试簇数量从 2 到 10
silhouette_scores = []
ch_scores = []
db_scores = []
for n_clusters in n_clusters_range:
agglo = AgglomerativeClustering(n_clusters=n_clusters, linkage='ward') # 使用 Ward 准则合并簇
agglo_labels = agglo.fit_predict(X_scaled)
# 计算评估指标
silhouette = silhouette_score(X_scaled, agglo_labels)
ch = calinski_harabasz_score(X_scaled, agglo_labels)
db = davies_bouldin_score(X_scaled, agglo_labels)
silhouette_scores.append(silhouette)
ch_scores.append(ch)
db_scores.append(db)
print(f"n_clusters={n_clusters}, 轮廓系数: {silhouette:.3f}, CH 指数: {ch:.2f}, DB 指数: {db:.3f}")
# 绘制评估指标图
plt.figure(figsize=(15, 5))
# 轮廓系数图
plt.subplot(1, 3, 1)
plt.plot(n_clusters_range, silhouette_scores, marker='o')
plt.title('轮廓系数确定最优簇数(越大越好)')
plt.xlabel('簇数量 (n_clusters)')
plt.ylabel('轮廓系数')
plt.grid(True)
# CH 指数图
plt.subplot(1, 3, 2)
plt.plot(n_clusters_range, ch_scores, marker='o')
plt.title('Calinski-Harabasz 指数确定最优簇数(越大越好)')
plt.xlabel('簇数量 (n_clusters)')
plt.ylabel('CH 指数')
plt.grid(True)
# DB 指数图
plt.subplot(1, 3, 3)
plt.plot(n_clusters_range, db_scores, marker='o')
plt.title('Davies-Bouldin 指数确定最优簇数(越小越好)')
plt.xlabel('簇数量 (n_clusters)')
plt.ylabel('DB 指数')
plt.grid(True)
plt.tight_layout()
plt.show()

# 提示用户选择 n_clusters 值(这里可以根据图表选择最佳簇数)
selected_n_clusters = 10 # 示例值,根据图表调整
# 使用选择的簇数进行 Agglomerative Clustering 聚类
agglo = AgglomerativeClustering(n_clusters=selected_n_clusters, linkage='ward')
agglo_labels = agglo.fit_predict(X_scaled)
X['Agglo_Cluster'] = agglo_labels
# 使用 PCA 降维到 2D 进行可视化
pca = PCA(n_components=2)
X_pca = pca.fit_transform(X_scaled)
# Agglomerative Clustering 聚类结果可视化
plt.figure(figsize=(6, 5))
sns.scatterplot(x=X_pca[:, 0], y=X_pca[:, 1], hue=agglo_labels, palette='viridis')
plt.title(f'Agglomerative Clustering with n_clusters={selected_n_clusters} (PCA Visualization)')
plt.xlabel('PCA Component 1')
plt.ylabel('PCA Component 2')
plt.show()
# 打印 Agglomerative Clustering 聚类标签的分布
print(f"Agglomerative Cluster labels (n_clusters={selected_n_clusters}) added to X:")
print(X[['Agglo_Cluster']].value_counts())

更多推荐



所有评论(0)