基于scikit-learn KMeans聚类中心绘制聚类边界线的技术咨询
如何为KMeans聚类绘制边界线
嘿,当然可行!作为scikit-learn新手,你可以用几种实用的方法来实现聚类边界的可视化,下面是我整理的几个方案,附代码示例:
1. 用凸包(Convex Hull)绘制紧凑聚类的边界
如果你的聚类是比较紧凑的凸形分布(比如伦敦、牛津这类区域的聚类),凸包是最简单直观的方法——它能画出包裹聚类所有点的最小凸多边形边界。
实现步骤:
- 导入所需库
- 提取每个聚类的样本点
- 计算每个聚类的凸包
- 绘制凸包的边界线
import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans from scipy.spatial import ConvexHull # 假设你已经有了经纬度数据X,以及拟合好的KMeans模型 # X = 你的经纬度数据(形状为(n_samples, 2)) kmeans = KMeans(n_clusters=2, random_state=42).fit(X) labels = kmeans.labels_ centers = kmeans.cluster_centers_ # 绘制原始数据点和聚类中心 plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', alpha=0.6) plt.scatter(centers[:, 0], centers[:, 1], c='red', marker='X', s=100, label='聚类中心') # 为每个聚类绘制凸包边界 unique_labels = np.unique(labels) for label in unique_labels: # 提取当前聚类的所有点 cluster_points = X[labels == label] if len(cluster_points) >= 3: # 至少3个点才能计算凸包 hull = ConvexHull(cluster_points) # 绘制凸包的边 for simplex in hull.simplices: plt.plot(cluster_points[simplex, 0], cluster_points[simplex, 1], 'k--') plt.legend() plt.xlabel('经度') plt.ylabel('纬度') plt.title('KMeans聚类及凸包边界') plt.show()
2. 绘制KMeans的决策边界(平滑划分线)
如果你想展示KMeans算法实际的划分逻辑(即每个点属于哪个聚类的分界线),可以通过生成网格点并预测聚类,再用等高线绘制边界。这种方法能得到平滑的划分线,适合展示聚类的整体划分效果。
实现步骤:
- 生成覆盖数据范围的网格点
- 用KMeans预测每个网格点的聚类
- 用
contour绘制决策边界
import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans # 同样假设你有数据X和拟合好的kmeans模型 kmeans = KMeans(n_clusters=2, random_state=42).fit(X) labels = kmeans.labels_ centers = kmeans.cluster_centers_ # 绘制原始数据和聚类中心 plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', alpha=0.6) plt.scatter(centers[:, 0], centers[:, 1], c='red', marker='X', s=100, label='聚类中心') # 生成网格点 x_min, x_max = X[:, 0].min() - 0.1, X[:, 0].max() + 0.1 y_min, y_max = X[:, 1].min() - 0.1, X[:, 1].max() + 0.1 xx, yy = np.meshgrid(np.arange(x_min, x_max, 0.01), np.arange(y_min, y_max, 0.01)) # 预测网格点的聚类 Z = kmeans.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) # 绘制决策边界(用虚线区分) plt.contour(xx, yy, Z, colors='k', linestyles='--', levels=np.arange(kmeans.n_clusters + 1) - 0.5) plt.legend() plt.xlabel('经度') plt.ylabel('纬度') plt.title('KMeans聚类及决策边界') plt.show()
3. 提取边界点并绘制精细边界
如果你的聚类形状不规则,凸包和决策边界都不够精细,可以先找出聚类的边界点(即最近邻属于其他聚类的点),再对这些边界点进行处理(比如凸包或插值)来绘制更贴合实际的边界。
实现步骤:
- 用最近邻算法找出每个点的最近邻
- 筛选出最近邻属于不同聚类的点(边界点)
- 对边界点绘制凸包或直接连接
import numpy as np import matplotlib.pyplot as plt from sklearn.cluster import KMeans from sklearn.neighbors import NearestNeighbors from scipy.spatial import ConvexHull # 假设你有数据X和拟合好的kmeans模型 kmeans = KMeans(n_clusters=2, random_state=42).fit(X) labels = kmeans.labels_ centers = kmeans.cluster_centers_ # 绘制原始数据和聚类中心 plt.scatter(X[:, 0], X[:, 1], c=labels, cmap='viridis', alpha=0.4) plt.scatter(centers[:, 0], centers[:, 1], c='red', marker='X', s=100, label='聚类中心') # 找出边界点 nbrs = NearestNeighbors(n_neighbors=1).fit(X) _, indices = nbrs.kneighbors(X) # 筛选出最近邻不属于同一聚类的点 boundary_mask = labels != labels[indices.flatten()] boundary_points = X[boundary_mask] boundary_labels = labels[boundary_mask] # 为每个聚类的边界点绘制凸包 unique_labels = np.unique(boundary_labels) for label in unique_labels: cluster_boundary = boundary_points[boundary_labels == label] if len(cluster_boundary) >= 3: hull = ConvexHull(cluster_boundary) for simplex in hull.simplices: plt.plot(cluster_boundary[simplex, 0], cluster_boundary[simplex, 1], 'k-', linewidth=2) plt.legend() plt.xlabel('经度') plt.ylabel('纬度') plt.title('KMeans聚类及精细边界') plt.show()
方法选择建议:
- 如果聚类是紧凑的凸形 → 用凸包方法,简单高效
- 如果想展示KMeans的划分逻辑 → 用决策边界方法
- 如果聚类形状不规则,需要更精细的边界 → 用边界点+凸包方法
内容的提问来源于stack exchange,提问作者Anant
相关产品推荐
相关产品推荐

