kmeans++聚类python
时间: 2025-05-09 19:16:53 浏览: 13
### KMeans++聚类算法的Python实现
KMeans++ 是一种改进版的 KMeans 聚类算法,其核心在于优化初始质心的选择方式。通过引入基于距离的概率分布机制,KMeans++可以有效减少收敛时间并提高聚类质量。
以下是完整的 Python 实现代码:
#### 初始化函数
初始化阶段采用 KMeans++ 的策略来选择初始质心。
```python
import numpy as np
def initialize_centroids(data, k):
"""
使用KMeans++方法初始化质心
:param data: 数据集 (n_samples, n_features)
:param k: 质心数量
:return: 初始质心数组
"""
centroids = []
first_centroid_index = np.random.choice(len(data)) # 随机选择第一个质心
centroids.append(data[first_centroid_index])
for _ in range(1, k):
distances = [] # 存储每个点到最近质心的距离平方
for point in data:
min_distance = float('inf')
for centroid in centroids:
dist = np.linalg.norm(point - centroid)**2
if dist < min_distance:
min_distance = dist
distances.append(min_distance)
probabilities = distances / np.sum(distances) # 将距离转换为概率分布
next_centroid_index = np.random.choice(len(data), p=probabilities) # 基于概率选择新质心
centroids.append(data[next_centroid_index])
return np.array(centroids)[^4]
```
#### 主体聚类过程
完成初始化后,按照标准 KMeans 流程执行迭代更新操作。
```python
def assign_clusters(data, centroids):
"""
分配数据点至最近的质心簇
:param data: 数据集 (n_samples, n_features)
:param centroids: 当前质心位置
:return: 每个样本所属的簇索引
"""
clusters = []
for point in data:
closest_centroid_idx = np.argmin([np.linalg.norm(point - c) for c in centroids]) # 找到最近质心
clusters.append(closest_centroid_idx)
return np.array(clusters)
def update_centroids(data, clusters, k):
"""
更新质心的位置
:param data: 数据集 (n_samples, n_features)
:param clusters: 每个样本所属的簇索引
:param k: 质心数量
:return: 新的质心位置
"""
new_centroids = []
for i in range(k):
cluster_points = data[clusters == i] # 获取属于当前簇的数据点
if len(cluster_points) > 0:
new_centroid = np.mean(cluster_points, axis=0) # 计算均值作为新的质心
new_centroids.append(new_centroid)
else:
new_centroids.append(np.zeros_like(data[0])) # 如果某个簇为空,则保持原样
return np.array(new_centroids)
def kmeans_plus_plus(data, k, max_iter=300, tol=1e-4):
"""
完整的KMeans++聚类流程
:param data: 输入数据集 (n_samples, n_features)
:param k: 聚类数
:param max_iter: 最大迭代次数
:param tol: 收敛容忍度
:return: 最终质心和分配结果
"""
centroids = initialize_centroids(data, k) # 初始化质心
prev_centroids = None
iteration = 0
while iteration < max_iter and not np.allclose(prev_centroids, centroids, atol=tol): # 迭代终止条件
prev_centroids = centroids.copy()
clusters = assign_clusters(data, centroids) # 分配簇
centroids = update_centroids(data, clusters, k) # 更新质心
iteration += 1
return centroids, clusters[^1][^2]
```
#### 示例运行
以下是一个简单的测试案例:
```python
if __name__ == "__main__":
from sklearn.datasets import make_blobs
X, y_true = make_blobs(n_samples=300, centers=4, cluster_std=0.60, random_state=0)
final_centroids, labels = kmeans_plus_plus(X, k=4)
print("最终质心:\n", final_centroids)
print("标签分配:", labels[:10]) # 显示部分结果
```
---
### 如何确定最佳聚类数目?
为了找到合适的 `k` 值,通常可使用 **手肘法** 或 **轮廓系数** 方法。具体如下:
1. **手肘法**: 绘制 SSE(误差平方和)随 `k` 增加的变化曲线,观察拐点处对应的 `k` 即为最优解[^3]。
2. **轮廓系数**: 对不同 `k` 值分别计算轮廓系数,选取最大值所对应的最佳聚类数目。
---
阅读全文
相关推荐


















