You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

小体量经纬度数据聚类:KMeans替代方案及DBSCAN问题排查

针对小规模经纬度数据集的聚类解决方案

一、你的DBSCAN代码问题分析

当前DBSCAN参数设置是导致单簇结果的核心原因:

  • min_samples=5:对于仅138条数据的小样本集,要求每个核心点周围至少5个邻居的门槛过高,而你的所有点地理位置接近,大部分点都满足该条件,最终被合并成一个大簇。
  • 调整方向:可尝试将min_samples降到2-3,同时微调epsilon(比如从5km改为3km),但这种方法很难精准控制簇数量在10-12个区间内。

二、更适配需求的聚类方法推荐

1. 凝聚层次聚类(Agglomerative Clustering)

支持haversine地理距离度量,可通过指定簇数或距离阈值精准匹配你的需求,适合小数据集场景:

from sklearn.cluster import AgglomerativeClustering
import pandas as pd
import numpy as np
from geopy.distance import great_circle

coords = pd.read_csv("locs.csv")
coords_rad = np.radians(coords.to_numpy())

# 指定生成12个簇,用平均链接法降低离群点影响
cluster = AgglomerativeClustering(
    n_clusters=12,
    metric='haversine',
    linkage='average'
).fit(coords_rad)

coords['cluster_label'] = cluster.labels_

# 检查各簇大小
print("各簇样本数量:")
print(coords['cluster_label'].value_counts())

# 验证簇内最大距离是否符合5-10km要求
def get_max_cluster_dist(cluster_points):
    max_dist = 0
    for i in range(len(cluster_points)):
        for j in range(i+1, len(cluster_points)):
            dist = great_circle(cluster_points.iloc[i], cluster_points.iloc[j]).km
            if dist > max_dist:
                max_dist = dist
    return max_dist

print("\n各簇最大地理距离:")
for label in coords['cluster_label'].unique():
    cluster_points = coords[coords['cluster_label'] == label][['lat', 'long']]
    print(f"簇{label}: {get_max_cluster_dist(cluster_points):.2f}km")

如果指定簇数后部分簇距离超标,可改用distance_threshold参数(比如设为10),再微调阈值直到簇数量落在10-12区间。

2. K-Medoids(PAM)

K-Means的改进版,以实际数据点作为簇中心,避免K-Means对球面距离的偏差,更适配地理数据:

from sklearn_extra.cluster import KMedoids
import pandas as pd
import numpy as np

coords = pd.read_csv("locs.csv")
coords_rad = np.radians(coords.to_numpy())

# 用haversine距离生成12个簇
kmedoids = KMedoids(
    n_clusters=12,
    metric='haversine',
    random_state=42
).fit(coords_rad)

coords['cluster_label'] = kmedoids.labels_
print(coords['cluster_label'].value_counts())

需先安装依赖库:pip install scikit-learn-extra

3. HDBSCAN

DBSCAN的优化版本,能自动识别不同密度的簇,对小数据集更友好,通过min_cluster_size控制簇的最小规模:

import hdbscan
import pandas as pd
import numpy as np

coords = pd.read_csv("locs.csv")
coords_rad = np.radians(coords.to_numpy())

# 设置最小簇大小为10,可根据结果调整
clusterer = hdbscan.HDBSCAN(
    min_cluster_size=10,
    metric='haversine',
    cluster_selection_method='eom'
).fit(coords_rad)

coords['cluster_label'] = clusterer.labels_
num_clusters = len(set(clusterer.labels_)) - (1 if -1 in clusterer.labels_ else 0)
print(f"生成簇数量:{num_clusters}")
print(coords['cluster_label'].value_counts())

若出现噪声点(标签为-1),可适当降低min_cluster_size至8,或调整min_samples参数。

三、KMeans的优化用法

若想继续使用KMeans,可先将经纬度转换为球面三维坐标,再进行聚类,能大幅降低欧氏距离的偏差:

from sklearn.cluster import KMeans
import pandas as pd
import numpy as np

coords = pd.read_csv("locs.csv")
lat_rad = np.radians(coords['lat'])
lon_rad = np.radians(coords['long'])

# 转换为三维球面坐标
x = np.cos(lat_rad) * np.cos(lon_rad)
y = np.cos(lat_rad) * np.sin(lon_rad)
z = np.sin(lat_rad)
coords_3d = np.column_stack((x, y, z))

kmeans = KMeans(n_clusters=12, random_state=42).fit(coords_3d)
coords['cluster_label'] = kmeans.labels_

内容的提问来源于stack exchange,提问作者Bill Petrosino

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 21:34:55