想象你是这座城市的夜市规划师,要在空旷的广场上摆 K 个烧烤摊。如果你闭着眼随手扔飞镖决定摊位位置,很可能五枚飞镖全扎在同一片角落——摊主们挤在一起抢客人,广场另一头的顾客却要饿着肚子走上十分钟。这就是聚类算法里“随机初始化”的尴尬:开局选点太差,后面怎么调整都难翻身,最终困在一个“差不多但远非最好”的经营局面,专业说法叫局部最优。 K-Means++ 提供了一套聪明的选址策略:第一家摊位仍然随机选(总得有个开始),但从第二家开始,它给每个候选位置打分——你离已有摊位越远,被选中的概率就越大,而且这个“越远越吃香”的趋势被刻意放大。于是摊位们天然地铺满整个广场,各占一块地盘,顾客走几步就能吃到烤串。 这篇文章带你读懂这套“开局定胜负”的策略:它解决什么问题、背后的概率公式如何运作、为什么能更快收敛、又如何在 sklearn 中正确使用。

岗位关联

对 AI 从业者来说,初始化策略决定了聚类结果的天花板。理解 K-Means++ 能帮你交付更稳定、可信的聚类模型,在用户分群、异常检测等场景中做出质量过硬的结果。

目录
  1. 可视化演示
  2. 随机初始化问题
  3. K-Means++核心原理
  4. 算法执行流程
  5. 收敛速度优势
  6. 聚类质量提升
  7. 工程实现策略
  8. AI 应用场景
  9. Python 演示
  10. 常见误区
  11. 面试题

可视化演示

动态演示K-Means++初始化的核心机制,通过基础/核心/应用/扩展四种模式展示关键概念与交互流程。

本节配有交互动效(进入视口后自动加载,约 3KB)。

K-Means++初始化:随机初始 随机初始化的局部最优问题 K-Means加加的概率加权采 核心机制可视化 K-Means++初始化整体架构与关键组件

随机初始化问题

夜幕降临,广场上人流已经涌来,而你作为夜市规划师,必须立刻从 100 个候选摊位点里选出 5 个。最省事的做法是闭着眼扔 5 枚飞镖,落在哪就在哪摆摊。可结果常常令人哭笑不得:5 枚飞镖全扎在广场东北角同一片空地,摊主们互相抢生意,西南角的顾客只能饿着肚子绕远路。更麻烦的是,再扔一次,飞镖可能又扎到别处,整个经营格局完全不同——这种“开局全靠运气”的做法,就是 K-Means 的随机初始化。

K-Means 算法启动时需要先选定 K 个“初始摊位”,也就是簇中心。最朴素的做法是从数据里随机抽 K 个点作为起点,然后进入“顾客找最近摊位、摊位挪到顾客中心”的循环。问题在于:如果开局几个摊位挤在一起,算法要花很多轮才能把摊位慢慢推开;更糟的是,它可能永远推不到最理想的位置,最终停在一个“比上不足、比下有余”的局部最优解上。

为了度量“开局好不好”,我们引入目标函数——残差平方和(SSE)。它把所有顾客到最近摊位的距离平方加起来,得到一份“总走路距离”账本。SSE 越小,说明摊位分布越合理:

扔飞镖的开局就像买彩票:偶尔能中,大多数时候却把摊位挤成一团。K-Means++ 的出现,正是为了把这门“看运气”的生意,变成一套“有章法”的选址艺术。

J=∑i=1nmin⁡k∈{1,…,K}∥xi−μk∥2J = \sum_{i=1}^{n} \min_{k \in \{1,\dots,K\}} \left\| x_i - \mu_k \right\|^2
SSE 是聚类质量的“总账本”:每个顾客只认最近摊位,把自己的走路距离平方记入账本,所有条目之和越小,说明这盘生意安排得越合理。
  1. 数据点 x_i第 i 个顾客的位置,即数据集里的第 i 个样本。
    xi,i=1,2,…,nx_i, \quad i = 1, 2, \dots, n
  2. 簇中心 μ_k第 k 个摊位的坐标,即第 k 个簇心。
    μk,k=1,2,…,K\mu_k, \quad k = 1, 2, \dots, K
  3. 取最近距离顾客只去最近的摊位,所以对每个 x_i 只保留离它最近的那个 μ_k 的距离平方。
    min⁡k∥xi−μk∥2\min_{k} \left\| x_i - \mu_k \right\|^2
  4. 总和把 n 个顾客的“走路距离平方”全部加起来,得到总成本。
    ∑i=1n⋯\sum_{i=1}^{n} \cdots
  5. 目标 JJ 越小代表簇心越贴近数据、聚类质量越高;随机初始化往往落到 J 偏大的局部最优。
    J=SSEJ = \text{SSE}

K-Means++核心原理

既然随机扔飞镖不靠谱,夜市规划师想到了一条巧妙规则:第一家摊位仍然随机定(总得有个开始的借口),但从第二家开始,每个候选点被选中的概率,取决于它离最近已有摊位有多远——越远越吃香。

具体如何量化“越远越吃香”?把每个候选点到最近摊位的距离记作 D,那么它被选中的概率正比于 D 的平方。注意是平方而不是一次方——这意味着“远一点”的优势会被刻意放大:距离翻一倍,概率变成原来的四倍,像滚雪球一样把摊位推向真正冷清的角落。这样一来,摊位们天然地散布全场,谁也不挤谁。

这套规则的精髓在于:它没有完全排除“较近的点”,只是让远点拥有压倒性优势——就像夜市里最冷清的角落虽不一定每次都被选中,但几乎每次都有最高的中选机会。

P(xi)=D(xi)2∑j=1nD(xj)2P(x_i) = \frac{D(x_i)^2}{\displaystyle\sum_{j=1}^{n} D(x_j)^2}
这是整篇文章的核心公式:每个点被选中当新簇心的概率,等于它到最近已有簇心距离的平方、在所有点距离平方总和中的占比。
  1. 最近距离 D第 i 个候选点到所有已有簇心中最近者的距离,体现了“它有多被冷落”。
    D(xi)=min⁡c∈C∥xi−c∥D(x_i) = \min_{c \in C} \left\| x_i - c \right\|
  2. 距离平方把距离取平方作为权重,让远点的优势像雪球一样放大。
    D(xi)2D(x_i)^2
  3. 归一化分母所有候选点权重的总和,把每个权重变成“占总盘子的比例”。
    ∑j=1nD(xj)2\sum_{j=1}^{n} D(x_j)^2
  4. 选中概率归一化后的概率,所有点概率相加恰好等于 1,像转盘一样决定下一个摊位落在哪。
    P(xi)=D(xi)2∑j=1nD(xj)2P(x_i) = \frac{D(x_i)^2}{\textstyle\sum_{j=1}^{n} D(x_j)^2}

算法执行流程

有了选址规则,K-Means++ 的完整流程可以概括为“三步走”:先布点、再营业、直到稳定。布点阶段,算法先随机挑一个点当首个簇心;随后反复计算每个点到最近簇心的距离平方,按概率加权采样选出下一个簇心;如此循环,直到凑齐 K 个簇心。

布点完成后进入“营业阶段”,也就是标准 K-Means 的迭代微调:先是“顾客认摊”,每个数据点归属到离它最近的簇心;再是“摊位搬家”,每个簇心挪到自己名下所有顾客的几何中心。这两步交替进行,直到簇心几乎不再移动,或者达到预设的最大迭代次数,算法便宣告收敛。

布点讲究策略,营业讲究效率。K-Means++ 把“开局布点”这件事做得足够漂亮,后面的“营业微调”自然就省心省力——这正是它比纯随机初始化更受欢迎的根本原因。

Tinit=O(n⋅K⋅d)T_{\text{init}} = O(n \cdot K \cdot d)
初始化阶段的时间复杂度,与样本数 n、簇数 K、特征维度 d 三者都成正比。
  1. n 样本数广场上候选摊位点的总数,即数据量。
    n=样本数量n = \text{样本数量}
  2. K 簇数最终要选出的摊位个数,即聚类数。
    K=簇中心数量K = \text{簇中心数量}
  3. d 维度每个点用几个坐标描述,即特征维度。
    d=特征维度d = \text{特征维度}
  4. 乘积复杂度每选一个簇心都要遍历所有点、计算 d 维距离,选 K 个簇心所以是三者相乘。
    O(n⋅K⋅d)O(n \cdot K \cdot d)

收敛速度优势

早高峰的夜市里,如果 5 个摊位一开始就均匀铺开,顾客几乎不用走回头路,摊主们稍微挪挪凳子就能进入“稳态营业”。反过来,如果开局挤在角落,摊主们需要反复搬摊、顾客反复认路,折腾十几轮才能勉强消停。收敛速度的差异,本质上就是“开局质量”的差异。

K-Means++ 的初始解已经非常接近最终解,因此后续迭代通常只需很少几轮就能稳定,目标函数 SSE 的下降曲线也格外陡峭。实验里常见的情况是:随机初始化要跑几十轮才收敛,K-Means++ 往往几轮就到位,整体计算时间节省明显。

更让人安心的是,K-Means++ 有理论保证。论文证明了它的近似比:用 K-Means++ 选出的初始化解,最终得到的 SSE 最多是最优解的 O(log K) 倍,不会差得离谱。

摊主们常说“好的开始是成功的一半”。在聚类世界里,K-Means++ 用更少的折腾换来更快的开业,这份“省下来的时间”在百万级数据上就是实实在在的算力成本。

JKM++≤O(log⁡K)⋅JOPTJ_{\text{KM++}} \le O(\log K) \cdot J_{\text{OPT}}
近似比是说:即便 K-Means++ 不是每次都能找到全局最优,它的解也不会比最优解差太多,最坏情况随 K 增长也只是对数级别。
  1. 全局最优 J_OPT理论上所有可能的摊位布局中,SSE 最小的那个“神仙开局”。
    JOPT=理论最优解J_{\text{OPT}} = \text{理论最优解}
  2. K-Means++ 结果 J_KM++用 K-Means++ 开局、再迭代得到的最终 SSE。
    JKM++=实际解J_{\text{KM++}} = \text{实际解}
  3. 对数因子 O(log K)最坏情况下实际解是最优解的多少倍,这个倍数随 K 增长得非常缓慢。
    O(log⁡K)O(\log K)
  4. 不等式含义无论数据多刁钻,K-Means++ 的解都不会比最优差太多,给使用者一颗定心丸。
    JKM++≤O(log⁡K)⋅JOPTJ_{\text{KM++}} \le O(\log K) \cdot J_{\text{OPT}}

聚类质量提升

夜市经营得好不好,最终要看顾客满不满意。顾客满意度对应 SSE——总走路距离越小越好;摊位之间分得开不开,则对应另一个指标:簇间距离。K-Means++ 的开局策略天然让摊位彼此远离,所以最终结果往往是“簇内更紧凑、簇间更疏离”,两头的体验都更好。

簇间离散度 B 用来衡量“摊位之间的地盘分得有多开”:每个摊位中心离全场顾客的大众位置越远,说明簇与簇之间界限越清晰,聚类越有辨识度。K-Means++ 开局就避免了摊位扎堆,所以 B 值通常明显高于随机初始化。

一个“摊位分散、客人满意”的夜市,对应到聚类结果上,就是 SSE 低、B 高、每次重开张结果都差不多。K-Means++ 让聚类从“碰运气”变成了“可预期的稳定发挥”。

B=∑k=1Knk∥μk−xˉ∥2B = \sum_{k=1}^{K} n_k \left\| \mu_k - \bar{x} \right\|^2
B 是“摊位分散度”的评分:所有簇的顾客数量 n_k 乘以簇心到全局中心 x̄ 的距离平方,再求和。B 越大,簇与簇之间隔得越开。
  1. 簇内人数 n_k第 k 个摊位名下有多少顾客,即第 k 个簇的样本量。
    nk=∣{i:min⁡j∥xi−μj∥2=∥xi−μk∥2}∣n_k = \left| \{ i : \textstyle\min_j \|x_i - \mu_j\|^2 = \|x_i - \mu_k\|^2 \} \right|
  2. 全局中心 x̄所有顾客位置的平均值,相当于全场人流的大众重心。
    xˉ=1n∑i=1nxi\bar{x} = \frac{1}{n}\sum_{i=1}^{n} x_i
  3. 距离平方每个摊位离大众重心越远,它对簇间离散度的贡献越大。
    ∥μk−xˉ∥2\left\| \mu_k - \bar{x} \right\|^2
  4. 加权求和顾客多的簇权重更大,避免小簇把分数虚高。
    ∑k=1Knk⋯\sum_{k=1}^{K} n_k \cdots

工程实现策略

老练的摊主摆摊前会做三件事:定好选址规则、试营业几次观察客流、固定同一套开业流程。放到工程上,这三件事对应 sklearn 里 KMeans 的三个关键参数:init、n_init 和 random_state。

第一个参数 init 直接指定初始化策略,默认就是 'k-means++',这也是它成为行业标配的原因。第二个参数 n_init 表示独立运行的轮数,默认 10——即使有了聪明的开局策略,概率采样仍带随机性,多跑几轮取 SSE 最小的一次更稳妥。第三个参数 random_state 固定随机种子,让实验结果可复现,这对调试和团队协作至关重要。

多轮运行取最优的逻辑,可以用一个简洁的式子表达:跑 R 轮,每轮得到一个 SSE,最终只保留最小的那个。

选址规则、试营业、固定流程——这三条“摊主心法”落到代码里就是三行参数。理解它们背后的原理,你才能在真实项目中自信地调参,而不是盲目照抄默认值。

J⋆=min⁡r=1ninitJrJ^{\star} = \min_{r=1}^{n_{\text{init}}} J_r
工程上的“稳健”来自冗余:与其赌一次开局,不如让算法多试几次,把最差情况过滤掉。
  1. 运行轮数 n_init独立初始化并聚类的次数,相当于试营业的场次。
    ninit=独立运行次数n_{\text{init}} = \text{独立运行次数}
  2. 单轮结果 J_r第 r 轮完整 K-Means 跑完的 SSE。
    Jr=第 r 轮的 SSEJ_r = \text{第 } r \text{ 轮的 SSE}
  3. 取最小值在所有轮次里挑 SSE 最小的作为最终模型,相当于留用客流最旺的那次开业方案。
    J⋆=min⁡r=1ninitJrJ^{\star} = \min_{r=1}^{n_{\text{init}}} J_r

AI 应用场景

电商用户分群画像

阶段:无监督学习 / 特征探索与用户画像构建

解决的问题:运营团队要对数十万用户分群,传统手动规则分群主观性强;而随机初始化的 K-Means 每次跑出来的群体都不一样,业务方根本无法信任结论。K-Means++ 让分群结果稳定可复现,且簇间界限清晰,运营策略能落到实处。

具体案例:某电商平台对用户按消费频次、客单价、活跃时长三个特征聚类。采用 K-Means++ 初始化后,分出的“价格敏感型”“品质型”“沉睡用户”等 8 个群体在多次运行中保持稳定,运营团队据此设计差异化优惠券,转化率提升了 12%。

图像颜色量化压缩

阶段:模型训练 / 图像预处理与压缩算法

解决的问题:把一张真彩色照片压缩成 16 色海报风格,本质是让 16 个“颜色摊位”覆盖整个色彩空间。随机初始化会让 16 种颜色挤在相近的色域,导致画面偏色、细节丢失;K-Means++ 让初始颜色均匀散布在整个色域,压缩效果更接近人眼感知。

具体案例:某图片处理 APP 在生成艺术滤镜时,对每个像素的 RGB 值做 K-Means++ 聚类(K=16),再以簇心颜色替代簇内像素。相比随机初始化,压缩后图片的峰值信噪比更高,且同一张图每次处理结果一致,不再出现“滤镜忽深忽浅”的投诉。

异常交易基线建模

阶段:异常检测 / 无监督基线模型构建

解决的问题:风控场景中,正常交易往往聚成若干大簇,而异常交易离群。K-Means++ 保证正常交易被稳定地聚成几簇,离群点才能被可靠识别;若用随机初始化,簇心扎堆会把正常交易和异常混在一起,漏报率飙升。

具体案例:某支付平台对交易金额、频次、设备特征做 K-Means++ 聚类,将距离最近簇心超过 3 倍标准差的交易标记为可疑。上线后相比随机初始化版本,异常召回率提升 20%,且模型每周重训时结果一致,方便风控团队审计。

Python 演示

python57 行
import numpy as npfrom sklearn.datasets import make_blobsfrom sklearn.cluster import KMeans  def kmeans_plusplus_init(X, k, seed=42):    """从零实现 K-Means++ 初始化,返回选中的 k 个簇心索引。"""    rng = np.random.RandomState(seed)    n = len(X)    centers_idx = [rng.randint(n)]    for _ in range(1, k):        dists = []        for c in centers_idx:            dists.append(np.sum((X - X[c]) ** 2, axis=1))        d2 = np.min(np.array(dists), axis=0)        probs = d2 / d2.sum()        centers_idx.append(int(rng.choice(n, p=probs)))    return np.array(centers_idx)  def run_kmeans(X, centers_idx, max_iter=100):    """给定初始簇心,跑标准 K-Means,返回最终簇心和 SSE。"""    centers = X[centers_idx].copy()    labels = np.zeros(len(X), dtype=int)    for _ in range(max_iter):        prev = centers.copy()        labels = np.argmin(            np.array([np.sum((X - c) ** 2, axis=1) for c in centers]), axis=0        )        centers = np.array(            [                X[labels == k].mean(axis=0) if (labels == k).any() else centers[k]                for k in range(len(centers))            ]        )        if np.allclose(prev, centers):            break    sse = float(((X - centers[labels]) ** 2).sum())    return centers, sse  def main():    X, _ = make_blobs(n_samples=300, centers=5, random_state=0)    rng = np.random.RandomState(0)    random_idx = rng.randint(len(X), size=5)    pp_idx = kmeans_plusplus_init(X, 5)    _, sse_random = run_kmeans(X, random_idx)    _, sse_pp = run_kmeans(X, pp_idx)    sk = KMeans(n_clusters=5, init="k-means++", n_init=10, random_state=0)    sk.fit(X)    print("随机初始化 SSE: %.2f" % sse_random)    print("K-Means++ 初始化 SSE: %.2f" % sse_pp)    print("sklearn K-Means++ SSE: %.2f" % sk.inertia_)  if __name__ == "__main__":    main()
目的:从零实现 K-Means++ 初始化,并与随机初始化、sklearn 标准实现在同一份数据上对比 SSE,直观感受开局策略对聚类质量的影响。
  1. X, _ = make_blobs(n_samples=300, centers=5, random_state=0)生成 300 个顾客点,天然分成 5 个“族”,相当于 5 片天然的客流聚集区。
  2. centers_idx = [rng.randint(n)]第一枚飞镖仍然随机扔,第一个簇心随机选。
  3. dists.append(np.sum((X - X[c]) ** 2, axis=1))计算每个候选点到该已选簇心的距离平方。
  4. d2 = np.min(np.array(dists), axis=0)每个点取离最近簇心的那条距离,体现“被冷落程度”。
  5. probs = d2 / d2.sum()距离平方占总盘子的比例,得到每个点被选中的概率。
  6. centers_idx.append(int(rng.choice(n, p=probs)))按概率掷骰子,转盘指针停在哪个点,它就当选下一个簇心。
  7. labels = np.argmin(np.array([np.sum((X - c) ** 2, axis=1) for c in centers]), axis=0)顾客认领最近的摊位,完成一次分配。
  8. centers = np.array([X[labels == k].mean(axis=0) ...])摊位搬到名下顾客的几何中心,完成一次搬家。
  9. sk = KMeans(n_clusters=5, init="k-means++", n_init=10, random_state=0)工程标准做法:K-Means++ 初始化、跑 10 轮取最优、固定种子保证可复现。

常见误区

误区我用了 K-Means++ 之后,聚类结果就是理论最优的,因为教材上说它能提升聚类质量、避免局部最优。

正解K-Means++ 只是把“开局扎堆”的概率大幅降低,让解落在全局最优附近的概率变高,但并不保证一定找到全局最优。它像聪明的选址策略能提高生意火爆的概率,却不能保证每晚都满座。近似比 O(log K) 也说明最坏情况仍是“接近最优”而非“就是最优”。

为何常见:很多文章强调 K-Means++ “避免局部最优”,初学者容易把“大幅改善”理解成“完全消除”,忽略了概率算法的随机本质。

误区K-Means++ 每次选下一个簇心时,就是挑那个离所有已有簇心最远的点,既然是“最远优先”就没必要跑多次。

正解它选的是“概率最大”,而不是“确定最远”。距离平方只决定了每个点被选中的概率权重,最远的点概率最大,但仍可能被其他点“爆冷”选中。这种随机性既让覆盖更全面,也意味着单次运行仍有波动,所以 sklearn 默认 n_init=10 多轮取优。

为何常见:公式里的距离平方占比很容易被简化理解为“排序取最大”,忽略了“加权随机采样”才是算法的灵魂。

误区K-Means++ 已经解决了初始化问题,所以 n_init 设成 1 就行,跑多次纯属浪费算力。

正解K-Means++ 只是让“好开局”的概率变高,不是每次开局都好。概率采样意味着运气差时仍会得到平庸的初始簇心。sklearn 默认 n_init=10,就是让算法多试几轮、从中挑 SSE 最小的,相当于多开几天摊、留用客流最旺的方案。省掉 n_init 等于把好不容易降下去的风险又抬了回来。

为何常见:学习者看到 K-Means++ 效果显著提升,容易高估它的稳定性,忽视了它仍是随机算法的本质。

误区K-Means++ 既然能“更聪明地选簇心”,那它应该也能告诉我数据到底该分成几类。

正解K-Means++ 解决的是“给定 K 之后,初始簇心选哪几个点”的问题,它从来不去判断 K 取值。K 仍要由业务经验、肘部法则或轮廓系数等外部方法决定。类比来说,K-Means++ 是帮你把 5 个摊位摆得更合理,但“今晚该摆 5 个摊还是 8 个摊”是另一码事。

为何常见:K-Means++ 名字里带着"K",容易让人误以为它参与确定 K,实际上 K 是预先给定的超参数。

面试题

Q1. K-Means++ 算法中,第一个簇中心是如何选择的?

单选题 · easy

  • A.选数据集中最中心的点
  • B.均匀随机挑选一个数据点← 正确答案
  • C.选密度最大的区域中心
  • D.选离均值最近的数据点

答案:B。K-Means++ 的第一个簇心是均匀随机选的,因为总得有个“第一摊”才能开始算距离。如果第一个点也精心挑,就违背了算法“用随机换来覆盖”的设计初衷。B 正确,其余选项都是对“最优首个中心”的误解。

Q2. K-Means++ 中,某个数据点被选为新簇心的概率主要取决于什么?

单选题 · mid

  • A.它到最近簇心距离的平方← 正确答案
  • B.它到最远簇心距离的平方
  • C.它到所有簇心距离的平均
  • D.它在数据集中的编号位置

答案:A。核心公式 P ∝ D²,其中 D 是该点到最近已有簇心的距离。选“最远”或“平均”都不符合定义,编号位置更是与概率无关。类比夜市选址:关键是你离最近的摊位有多远,而不是离最远的摊位有多远。

Q3. 为什么 K-Means++ 采用距离平方而非一次方作为权重?

单选题 · mid

  • A.平方能放大远点选择优势← 正确答案
  • B.一次方会导致计算溢出
  • C.平方后概率更容易归一化
  • D.一次方不符合数学定义

答案:A。距离一次方也能归一化、也不会溢出,但平方让“远一点”的优势成倍放大——距离翻倍,权重变四倍。这正是为了让簇心更均匀地铺开,避免远点吸引力不足导致开局仍偏向密集区。

Q4. 随机初始化可能给 K-Means 带来哪些问题?

多选题 · easy

  • A.簇心扎堆导致初始化偏差← 正确答案
  • B.迭代后陷入局部最优解← 正确答案
  • C.多次运行结果很不稳定← 正确答案
  • D.算法必然无法正常收敛

答案:ABC。随机初始化可能扎堆、落入局部最优、结果不稳定,这些都是 K-Means++ 要解决的痛点。但“必然无法收敛”太绝对——随机初始化也能收敛,只是通常收敛到更差的解。就像飞镖开局生意差,但摊位最终还是会稳定下来,只是赚得少。

Q5. sklearn 中 KMeans 的 init 参数默认值是什么?

单选题 · mid

  • A.字符串 k-means++← 正确答案
  • B.random 表示随机初始化
  • C.整数 10 表示聚类轮数
  • D.浮点 0.5 表示距离阈值

答案:A。sklearn 的 KMeans 默认 init='k-means++',这是它被广泛使用的关键配置之一。B 是可选值之一但不是默认;C 是 n_init 的默认值;D 与初始化无关。

Q6. KMeans 中 n_init=10 的含义是什么?

单选题 · hard

  • A.初始化 10 个簇中心
  • B.跑 10 轮取 SSE 最小← 正确答案
  • C.每轮最多迭代 10 次
  • D.数据集分成 10 个部分

答案:B。n_init 是“独立运行次数”,算法用 10 种不同的初始化各跑一遍完整 K-Means,最终保留 SSE 最小的结果。它不改变簇数 K(A 错)、不限制迭代轮数(C 错)、也不切分数据(D 错)。

Q7. K-Means++ 初始化阶段的时间复杂度约为多少(n 为样本数,K 为簇数,d 为维度)?

单选题 · mid

  • A.O(n) 只与样本数相关
  • B.O(nKd) 与三者相关← 正确答案
  • C.O(n²) 平方级复杂度
  • D.O(K³) 主要取决于簇数

答案:B。每选一个簇心需遍历 n 个点、每个点算 d 维距离,共选 K 个,所以是 O(nKd)。它不是线性 O(n),更不是平方级 O(n²),与 K³ 更无关。

Q8. 关于 K-Means++,以下说法正确的有哪些?

多选题 · hard

  • A.首个簇心均匀随机选择← 正确答案
  • B.概率正比于距离平方加权← 正确答案
  • C.一定能得到全局最优解
  • D.最终结果受随机种子影响← 正确答案

答案:ABD。A、B 是算法定义;D 正确,因为首点和后续加权采样都依赖随机数,固定 random_state 才能复现。C 错误——K-Means++ 只保证高概率接近最优,不保证全局最优,近似比 O(log K) 就说明了这一点。

Q9. K-Means++ 主要解决 K-Means 的什么问题?

单选题 · easy

  • A.自动确定聚类数 K
  • B.减少局部最优风险← 正确答案
  • C.加速高维数据计算
  • D.处理缺失值与噪声

答案:B。K-Means++ 的核心贡献是改善初始簇心选择,降低开局扎堆导致的局部最优风险。它不负责选 K(A 错),不改变迭代算法本身的复杂度(C 错),也不做数据清洗(D 错)。

Q10. 以下哪些做法能提升聚类结果的稳定性与质量?

多选题 · hard

  • A.固定 random_state 随机种子← 正确答案
  • B.增大 n_init 多次运行取优← 正确答案
  • C.指定 init 为 k-means++← 正确答案
  • D.只跑一轮不设随机种子

答案:ABC。固定种子让结果可复现,增大 n_init 用冗余换稳健,指定 k-means++ 保证开局质量,三者都是工程上提升稳定性与质量的标配。D 恰好相反——只跑一轮又不设种子,结果最不可控。