二分K-Means(Bisecting K-Means)

二分K-Means(Bisecting K-Means)是一种改进的聚类算法,它是K-Means算法的一种变体。

与传统的K-Means算法一次性生成K个聚类不同,二分K-Means通过递归将一个聚类分裂成两个,直到达到所需的聚类数目。

二分K-Means算法流程:

  1. 初始化:将所有数据点视为一个簇
  2. 分裂:从当前的簇中选择一个簇进行分裂。选择的标准通常是选择那些分裂后可以最大程度减少误差平方和(SSE)的簇。
  3. 应用K-Means:对选定的簇应用标准的K-Means算法,将其分成两个簇。
  4. 评估:检查是否达到了所需的聚类数目。如果没有,返回步骤2;如果达到了,算法结束。

涉及到的公式:

在二分K-Means中,最重要的公式是计算误差平方和(SSE),它用于决定哪个簇应该被分裂以及评估聚类的效果。SSE的公式如下:

S S E = ∑ i = 1 k ∑ x ∈ C i ( x − μ i ) 2 SSE = \sum_{i=1}^{k} \sum_{x \in C_i} (x - \mu_i)^2 SSE=i=1kxCi(xμi)2

这里:

  • k k k聚类的数量;
  • C i C_i Ci 是第 i i i聚类中的所有数据点;
  • x x x 是聚类 C i C_i Ci 中的某个数据点;
  • μ i \mu_i μi 是聚类 C i C_i Ci质心,计算方式为 μ i = 1 ∣ C i ∣ ∑ x ∈ C i x \mu_i = \frac{1}{|C_i|} \sum_{x \in C_i} x μi=Ci1xCix,其中 ∣ C i ∣ |C_i| Ci 表示聚类 C i C_i Ci数据点的数量。

对公式中每个字符的解释:

  • ∑ \sum :求和符号,表示对一系列项进行累加。
  • i i i:聚类的索引。
  • k k k:总的聚类数目。
  • x x x:数据集中的一点。
  • C i C_i Ci:第 i i i个聚类的所有数据点组成的集合。
  • μ i \mu_i μi:第 i i i个聚类的质心。
  • ( x − μ i ) 2 (x - \mu_i)^2 (xμi)2:数据点 x x x与质心 μ i \mu_i μi之间的欧氏距离的平方。
  • ∣ C i ∣ |C_i| Ci:聚类 C i C_i Ci中数据点的数量。

二分K-Means的目标是通过最小化SSE来获得更加紧凑和分离良好的聚类。

python代码

# 导入所需的库
from sklearn.cluster import KMeans
import numpy as np

# 定义数据点,这是一个二维数组,其中每个子数组代表一个数据点的坐标
data_points = np.array([[1, 2], [1.5, 1.8], [5, 8], [8, 8], [1, 0.6], [9, 11]])

# 定义二分K-Means算法的函数
def bisecting_kmeans(data, k):
    # 初始化,将所有数据点视为一个簇
    clusters = [data]
    
    # 当前簇的数量小于目标簇的数量时,继续循环
    while len(clusters) < k:
        # 初始化最大SSE为0,用于记录当前找到的最大SSE值
        max_sse = 0
        # 初始化要分裂的簇的索引为0
        index_to_split = 0
        # 遍历当前的所有簇
        for i, cluster in enumerate(clusters):
            # 对当前簇使用KMeans算法,将其分为两个簇
            kmeans = KMeans(n_clusters=2).fit(cluster)
            # 计算SSE,即簇内所有点到其所属簇质心距离的平方和
            # 使用np.linalg.norm计算每个点到最近质心的欧氏距离,然后平方求和
            sse = np.sum(np.linalg.norm(cluster - kmeans.cluster_centers_[kmeans.labels_], axis=1) ** 2)
            # 如果当前簇的SSE大于已知的最大SSE,则更新最大SSE和要分裂的簇的索引
            if sse > max_sse:
                max_sse = sse
                index_to_split = i
        
        # 根据找到的具有最大SSE的簇,使用KMeans算法将其分为两个簇
        split_cluster = clusters.pop(index_to_split)
        kmeans = KMeans(n_clusters=2).fit(split_cluster)
        
        # 将分裂后的簇按标签排序后分割成两个簇
        labels_sorted = np.argsort(kmeans.labels_)
        # 使用切片操作,根据标签排序后的结果,将split_cluster分为cluster1和cluster2
        cluster1 = split_cluster[labels_sorted[:len(labels_sorted)//2]]
        cluster2 = split_cluster[labels_sorted[len(labels_sorted)//2:]]
        
        # 将新生成的两个簇添加到clusters列表中
        clusters.append(cluster1)
        clusters.append(cluster2)
    
    # 当达到指定的簇数k时,返回当前的簇列表
    return clusters

# 设置聚类的数量
k = 2

# 调用bisecting_kmeans函数,传入数据点和聚类数量
clusters = bisecting_kmeans(data_points, k)

# 输出最终的聚类结果
for i, cluster in enumerate(clusters):
    print(f"Cluster {i+1}:")
    print(cluster)
  • 13
    点赞
  • 31
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不易撞的网名

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值