实现带30万人口上限约束的经纬度K-Means聚类问题
带人口规模约束的K-means聚类实现方案
报错原因
你调用KMeansConstrained时传入的size_min、size_max参数,约束的是每个聚类包含的样本点数量,而非你要求的聚类人口总和。你传入的300000远大于数据集的总样本条数,因此触发了参数校验规则,直接报错。
实现方案
方案1:基于约束KMeans的二次调整
- 先计算基础参数:统计数据集总人口,除以300000后向上取整,得到最少需要的聚类数量
n_clusters;再用总样本数除以n_clusters,得到每个聚类的样本数上下限,作为size_min、size_max的入参 - 运行初聚类得到初始聚类标签,统计每个聚类的总人口
- 对人口超过30万的聚类做拆分,单独对该聚类下的样本再跑KMeans拆为2个聚类;对人口远低于阈值的相邻聚类做合并,直到所有聚类的总人口都不超过30万
方案2:自定义带人口容量约束的聚类逻辑
如果不想做二次调整,可以直接修改样本分配规则:
- 初始化聚类中心后,每次分配样本到聚类中心时,先校验当前聚类的累计人口加上该样本人口是否超过30万
- 如果超过阈值,就将样本分配到次近的、还有剩余容量的聚类中心
- 迭代更新聚类中心和样本分配结果,直到收敛
代码示例
import numpy as np import pandas as pd from k_means_constrained import KMeansConstrained # 1. 计算基础参数 total_pop = df['人口'].sum() # 计算最少需要的聚类数 n_clusters = int(np.ceil(total_pop / 300000)) n_samples = len(df) # 计算每个聚类的样本数上下限 size_min = n_samples // n_clusters size_max = size_min + 1 if n_samples % n_clusters != 0 else size_min # 2. 跑初聚类 X = df[['latitude', 'longitude']].values clus = KMeansConstrained( n_clusters=n_clusters, size_min=size_min, size_max=size_max, random_state=42 ) df['cluster'] = clus.fit_predict(X) # 3. 校验聚类人口并调整 cluster_pop = df.groupby('cluster')['人口'].sum() # 筛选超容量的聚类 over_cap_clusters = cluster_pop[cluster_pop > 300000].index.tolist() # 对超容量的聚类单独拆分,迭代直到所有聚类满足阈值即可
内容的提问来源于stack exchange,提问作者kukulu
相关产品推荐
相关产品推荐

