K-means算法结果标准

K-means算法是一种常用的无监督学习算法,用于将数据集分成K个簇。评估K-means聚类结果的标准有很多,主要包括以下几种:

  1. 簇内误差平方和(Within-cluster Sum of Squares, WCSS)

    • 也称为簇内平方和(Inertia),它是衡量簇内数据点与簇中心之间距离的总和。目标是使这个值最小化,表示簇内数据点彼此之间的距离尽可能近。
    • 公式:$WCSS = \sum_{i=1}^{k} \sum_{x \in C_i} | x - \mu_i |^2$ 其中,$C_i$ 是第 $i$ 个簇,$\mu_i$ 是 $C_i$ 的质心,$x$ 是 $C_i$ 中的一个数据点。

在K-means算法中,通过手肘法确定最佳的K值通常需要以下步骤:

  1. 计算不同K值下的SSE(误差平方和)

    • 对于每一个K值(从1到某个较大的值),运行K-means算法,并计算其对应的SSE。
  2. 绘制K值与SSE的关系图

    • 将不同K值对应的SSE绘制成图,观察曲线的形状。
  3. 寻找肘部位置

    • 观察图中的“肘部”位置,即SSE开始显著变平缓的点,对应的K值就是最佳的聚类数。

以下是一个Python代码示例,展示了如何使用手肘法确定K值:

import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.datasets import make_blobs

# 生成示例数据

X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)

# 定义要测试的K值范围

k_values = range(1, 11)

# 存储每个K值对应的SSE

sse = []

for k in k_values:
kmeans = KMeans(n_clusters=k, random_state=0)
kmeans.fit(X)
sse.append(kmeans.inertia_)  # inertia_属性即为SSE

# 绘制K值与SSE的关系图

plt.figure(figsize=(8, 5))
plt.plot(k_values, sse, 'bo-', markersize=8)
plt.xlabel('Number of clusters (k)')
plt.ylabel('Sum of squared errors (SSE)')
plt.title('Elbow Method For Optimal k')
plt.show()

解释代码:

  1. 生成示例数据

    • 使用make_blobs函数生成一个包含300个样本的示例数据集,假设有4个簇。
  2. 定义要测试的K值范围

    • 这里我们测试从1到10的K值。
  3. 计算每个K值对应的SSE

    • 使用K-means算法对每个K值进行聚类,并记录其对应的SSE(通过kmeans.inertia_获取)。
  4. 绘制K值与SSE的关系图

    • 使用Matplotlib绘制K值与SSE的关系图,观察曲线形状以确定肘部位置。

通过观察图中的“肘部”位置,即SSE显著变平缓的点,可以确定最佳的K值。通常,这个点对应的K值就是数据的真实聚类数。

  1. 轮廓系数(Silhouette Coefficient)

    • 轮廓系数结合了簇内紧密度和簇间分离度。其值在-1到1之间,值越大表示聚类效果越好。
    • 公式:$s(i) = \frac{b(i) - a(i)}{\max(a(i), b(i))}$ 其中,$a(i)$ 是数据点 $i$ 到其簇内其他点的平均距离,$b(i)$ 是数据点 $i$ 到最近簇的平均距离。

    以下是如何使用轮廓系数法确定最佳聚类数的步骤:

    1. 计算不同K值下的轮廓系数
      • 对于每一个K值(从2到某个较大的值),运行K-means算法,并计算其对应的轮廓系数。
    2. 绘制K值与平均轮廓系数的关系图
      • 将不同K值对应的平均轮廓系数绘制成图,观察曲线的形状。
    3. 选择平均轮廓系数最大的K值
      • 平均轮廓系数最大的K值即为最佳聚类数。

    以下是一个Python代码示例,展示了如何使用轮廓系数法确定最佳K值:

import matplotlib.pyplot as plt
from sklearn.cluster import KMeans
from sklearn.metrics import silhouette_score
from sklearn.datasets import make_blobs

# 生成示例数据
X, _ = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)

# 定义要测试的K值范围
k_values = range(2, 11)

# 存储每个K值对应的平均轮廓系数
silhouette_scores = []

for k in k_values:
    kmeans = KMeans(n_clusters=k, random_state=0)
    kmeans.fit(X)
    labels = kmeans.labels_
    silhouette_avg = silhouette_score(X, labels)
    silhouette_scores.append(silhouette_avg)

# 绘制K值与平均轮廓系数的关系图
plt.figure(figsize=(8, 5))
plt.plot(k_values, silhouette_scores, 'bo-', markersize=8)
plt.xlabel('Number of clusters (k)')
plt.ylabel('Average Silhouette Score')
plt.title('Silhouette Method For Optimal k')
plt.show()

# 找到平均轮廓系数最大的K值
optimal_k = k_values[silhouette_scores.index(max(silhouette_scores))]
print(f'The optimal number of clusters is {optimal_k}')

解释代码:

  1. 生成示例数据

    • 使用make_blobs函数生成一个包含300个样本的示例数据集,假设有4个簇。
  2. 定义要测试的K值范围

    • 这里我们测试从2到10的K值(注意K值从2开始,因为K=1时轮廓系数没有意义)。
  3. 计算每个K值对应的平均轮廓系数

    • 使用K-means算法对每个K值进行聚类,获取每个样本的簇标签。
    • 使用silhouette_score函数计算每个K值对应的平均轮廓系数,并存储结果。
  4. 绘制K值与平均轮廓系数的关系图

    • 使用Matplotlib绘制K值与平均轮廓系数的关系图,观察曲线形状。
  5. 找到平均轮廓系数最大的K值

    • 通过查找平均轮廓系数最大的K值,确定最佳的聚类数。

通过这种方式,我们可以使用轮廓系数法确定最佳的K值,以获得更好的聚类效果。

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

    • 也称为方差比准则(Variance Ratio Criterion, VRC),其值越大表示聚类效果越好。
    • 公式:$\text{CH} = \frac{B_k / (k-1)}{W_k / (n-k)}$ 其中,$B_k$ 是簇间离散度矩阵的迹,$W_k$ 是簇内离散度矩阵的迹,$n$ 是样本总数,$k$ 是簇的数量。
  2. Davies-Bouldin指数(Davies-Bouldin Index)

    • 该指数衡量的是簇之间的相似度,值越小表示聚类效果越好。
    • 公式:$\text{DB} = \frac{1}{k} \sum_{i=1}^{k} \max_{j \ne i} \left( \frac{\sigma_i + \sigma_j}{d(c_i, c_j)} \right)$ 其中,$\sigma_i$ 是第 $i$ 个簇的平均距离,$d(c_i, c_j)$ 是簇 $i$ 和簇 $j$ 的质心之间的距离。
  3. 轮廓系数图(Elbow Method)

    • 通过绘制不同K值对应的簇内误差平方和(WCSS)图,寻找"肘部"位置,以确定最佳的K值。肘部位置通常是曲线开始变平缓的点。
  4. BIC(Bayesian Information Criterion)和AIC(Akaike Information Criterion)

    • 这两种信息准则常用于模型选择,值越小表示模型越好。尽管它们更多用于有监督学习,但在某些情况下也可以用于K-means聚类。
  5. 实际应用中的可解释性

    • 聚类结果是否具有实际意义,是否能被领域专家解释和利用,也是一个重要的标准。

在实际应用中,通常会结合多个指标来综合评估K-means聚类的效果。