flowchart TB classDef start fill:#D1FAE5,stroke:#10B981,stroke-width:2px,color:#064E3B classDef step fill:#DBEAFE,stroke:#2563EB,stroke-width:2px,color:#1E3A8A classDef decide fill:#FEF3C7,stroke:#D97706,stroke-width:2px,color:#78350F classDef guard fill:#FFE4E6,stroke:#BE123C,stroke-width:2px,color:#881337 classDef done fill:#FFEDD5,stroke:#EA580C,stroke-width:2px,color:#7C2D12 input["输入 Y = { yᵢ } ⊂ ℝ³², i = 1…N  (可先随机抽子集拟合:fit_max_samples)
目标   min_{C,μ} J(C,μ) = Σᵢ ‖yᵢ − μ_{c(i)}‖²  — NP-hard,只求局部最优"]:::start subgraph INIT["① k-means++ 初始化  (期望近似比 E[J] ≤ 8(ln k + 2)·J_opt)"] direction LR pick1["均匀随机取 μ₁"]:::step dist["D(y) = min_{j≤t} ‖y − μⱼ‖"]:::step sample["按 p(y) ∝ D(y)² 采样 μ_{t+1}
离已有质心越远越易被选中"]:::step kdone{"够 k 个?"}:::decide pick1 --> dist --> sample --> kdone kdone -.->|"否,继续挑"| dist end subgraph LLOYD["② Lloyd 迭代  (J 单调不增且有下界,故必收敛)"] direction LR assign["指派步
c(i) = argminⱼ ‖yᵢ − μⱼ‖²
一次 cdist 算完 N×k 距离"]:::step update["更新步
μⱼ ← mean{ yᵢ : c(i) = j }
均值是簇内平方距离的唯一最小点"]:::step empty{"有空簇?"}:::decide steal["把离自身质心最远的点
提为该空簇的新质心
保证簇数不缩水"]:::guard conv{"|J_prev − J| ≤ tol·J_prev
或迭代满 100 次?"}:::decide assign --> update --> empty empty -->|"否"| conv empty -->|"是"| steal --> conv conv -.->|"否,回到指派步"| assign end repeat["③ 以上 ①② 整体重复 n_init = 10 次
每次换随机种子 seed + r"]:::step best["④ 取 10 次里 J 最小的一次 (C*, μ*)
缓解 Lloyd 只保证局部最优"]:::done final["⑤ 全量指派  cᵢ = argminⱼ ‖yᵢ − μ*ⱼ‖,i = 1…N
并记录到质心的距离 dᵢ,供排序与离群检查"]:::done input --> INIT kdone ==>|"是,得到初值 μ⁽⁰⁾"| assign conv ==>|"是,本次收敛"| repeat repeat --> best --> final