Python实现k-means聚类:质心值更新问题求助
嘿,我来帮你搞定k-means里更新质心的问题!你已经完成了初始簇分配,接下来计算质心其实就是对每个簇里的所有300维特征求平均值对吧?我给你捋捋具体的实现步骤,还有可能踩的坑。
解决k-means质心更新问题的步骤
第一步:按簇编号分组数据
首先得把AllData里的数据按簇编号(1-4)分开,这样才能针对性计算每个簇的质心。用字典来分组最方便,键是簇编号,值存该簇所有样本的300维特征列表:
# 初始化字典存储各簇的特征 cluster_features = {1: [], 2: [], 3: [], 4: []} for item in AllData: word, features, cluster_id = item cluster_features[cluster_id].append(features)
这里要注意:如果你的features是普通Python列表,后续计算均值时转成numpy数组会更高效;要是已经是numpy数组就不用折腾啦。
第二步:计算每个簇的质心
质心的核心逻辑就是簇内所有样本对应维度的平均值,两种实现方式供你选:
方式一:用numpy(推荐,简洁高效)
numpy可以直接对数组的轴做均值计算,省去手动遍历维度的麻烦:
import numpy as np new_centroids = {} for cluster_id, features_list in cluster_features.items(): # 把特征列表转成(n_samples, 300)的numpy数组 features_array = np.array(features_list) # 对每一列(每个维度)求平均,得到(300,)的质心数组 centroid = np.mean(features_array, axis=0) new_centroids[cluster_id] = centroid
方式二:纯Python实现(不用第三方库)
如果不想依赖numpy,就手动遍历每个维度累加再求平均:
new_centroids = {} for cluster_id, features_list in cluster_features.items(): num_samples = len(features_list) # 处理空簇:如果某个簇没有样本,跳过或者保留原质心 if num_samples == 0: continue # 初始化全0的300维质心 centroid = [0.0 for _ in range(300)] # 累加每个样本的对应维度值 for features in features_list: for i in range(300): centroid[i] += features[i] # 求平均得到质心 for i in range(300): centroid[i] /= num_samples new_centroids[cluster_id] = centroid
第三步:处理空簇的特殊情况
迭代过程中可能出现某个簇没有分配到任何样本的情况,这时候不能直接除以0。你可以选这几种处理方式:
- 保留该簇上一轮的质心,继续参与下一次迭代
- 随机从所有样本里选一个新的样本作为该簇的质心
- 如果允许调整k值,可以合并空簇到其他簇(不过k-means一般固定k值,前两种更常用)
第四步:整合到迭代循环里
把上面的步骤放到k-means的主循环中:
- 先给所有样本分配簇编号(你已经完成这一步)
- 按上面的方法计算新质心
- 对比新质心和上一轮质心的差异,如果变化小于设定的阈值(比如所有维度的差值之和小于1e-6),就说明收敛了,停止迭代;否则继续循环分配簇、更新质心。
举个小例子,假设你的AllData结构是这样的:
AllData = [
("apple", [0.1, 0.2, ..., 0.5], 1),
("banana", [0.3, 0.4, ..., 0.7], 2),
# ... 剩下327条数据
]
按照上面的步骤走,应该就能顺利更新质心啦!
内容的提问来源于stack exchange,提问作者Ross Headington
相关产品推荐
相关产品推荐

