PySpark中K-means含k=1的最优k值求解方法(轨迹起点坐标聚类场景)
PySpark包含k=1场景的K-means最优k值实现方案
前置问题澄清
- 轮廓系数不支持k=1场景:该指标的计算逻辑依赖「样本到最近异簇的平均距离」,当只有1个簇时没有异簇存在,数学上无合法取值,PySpark内置的
ClusteringEvaluator传入k=1的预测结果会直接抛出参数异常,因此评估k=1的聚类效果直接采用**簇内平方和(SSE,即K-means的训练损失值)**即可,完全适配肘部法则的判断逻辑。 - 经纬度坐标适配:你的轨迹起点波动范围仅2公里,小范围下经纬度直接计算欧氏距离的误差可忽略,如果需要更高精度可先将经纬度转换为平面墨卡托投影坐标再输入模型。
- PySpark原生支持
k=1的K-means训练,无需额外改造算法。
完整实现代码
from pyspark.ml.feature import VectorAssembler from pyspark.ml.clustering import KMeans # 1. 特征预处理:经纬度转特征向量 vecAssembler = VectorAssembler(inputCols=["lat", "lon"], outputCol="features") df_feature = vecAssembler.transform(df) # 2. 遍历k=1到k=3,计算每个k对应的簇内平方和(SSE) k_range = [1,2,3] k_cost = {} seed = 1 for k in k_range: kmeans = KMeans().setK(k).setSeed(seed) model = kmeans.fit(df_feature.select('features')) # 直接取模型内置的训练损失值(即簇内所有点到对应质心的平方距离之和) k_cost[k] = model.summary.trainingCost # 可选:输出每个k的簇中心,匹配你的出发点刻画需求 print(f"k={k}的簇中心:{model.clusterCenters()}") # 输出所有k对应的SSE print("各k值对应的簇内平方和:", k_cost)
适配业务场景的最优k判断逻辑
你可以根据轨迹起点「在质心周边2公里范围内波动」的业务规则,结合以下逻辑选最优k:
- 先校验k=1的SSE是否低于预设阈值:可根据你所在区域的经纬度换算比例(纬度1公里≈0.009度,经度1公里≈0.009/cos(纬度)度),计算2公里波动范围对应的最大可接受SSE,若k=1的SSE低于该值,直接判定所有起点属于同一区域,最优k=1。
- 若k=1的SSE超过阈值,再对比k=1、k=2、k=3的SSE下降幅度:如果k=2相对k=1的SSE下降幅度≥30%,说明存在至少两个明显的聚集区域,再对比k=2和k=3的SSE下降幅度,若k=3的下降幅度<10%则最优k为2,否则为3。
内容的提问来源于stack exchange,提问作者Alex Germain
相关产品推荐
相关产品推荐

