带字符串索引数据集的K-Means聚类离群点识别Python代码实现问询
K-Means聚类离群点识别的Python实现
背景
- 有一个索引为字符串(如
'1234a'、'abcd'等非整数类型)的input_df - 已完成k=100的K-Means聚类,得到两个结果:
centroids:100个聚类中心,对应每个簇的样本均值labels:与input_df行数一致,标记每个样本所属的聚类簇
离群点识别逻辑
先明确伪代码的核心逻辑,尤其是你疑惑的第4行:
c_x : 样本点x对应的聚类中心,其中x ∈ X 1. 计算每个点到其对应聚类中心的L2距离(欧几里得距离)。 2. t = L2距离的95%分位数(即95%的样本距离都小于等于t,剩余5%的大距离样本就是离群点)。 3. 遍历每个样本点x: 4. 若样本x到其对应聚类中心c_x的欧几里得距离 > t,则 5. 将x标记为离群点注:
|| x - c_x ||₂就是L2范数,等价于两点间的欧几里得距离,条件的意思是:当样本到自身簇中心的距离超过95%的样本距离时,判定为离群点。
符合要求的Python实现
以下是完全匹配你给出的代码结构的实现:
import numpy as np from sklearn.cluster import KMeans def remove_outliers(input_df, centroids, labels): # 将DataFrame转为numpy数组,方便向量运算 X = input_df.values # 为每个样本匹配对应的聚类中心 matched_centroids = centroids[labels] # 计算每个样本到对应簇中心的L2距离(欧几里得距离) l2_distances = np.linalg.norm(X - matched_centroids, axis=1) # 计算95%分位数t——95%的样本距离都不超过这个值 threshold = np.percentile(l2_distances, 95) # 生成非离群点的掩码 keep_mask = l2_distances <= threshold # 过滤labels:只保留非离群点的标签 filtered_labels = labels[keep_mask] # 过滤centroids:只保留还有非离群点的簇的中心 remaining_clusters = np.unique(filtered_labels) filtered_centroids = centroids[remaining_clusters] return filtered_centroids, filtered_labels # 示例调用流程 kmeans = KMeans(n_clusters=100, random_state=42) kmeans.fit(input_df) centroids = kmeans.cluster_centers_ labels = kmeans.labels_ filtered_centroids, filtered_labels = remove_outliers(input_df, centroids, labels)
关键代码说明
np.linalg.norm(X - matched_centroids, axis=1):按行计算每个样本与对应簇中心的L2距离,axis=1确保对每个样本单独计算距离np.percentile(l2_distances, 95):直接计算距离的95%分位数,作为离群点判定的阈值- 过滤聚类中心时,会移除所有样本都被判定为离群点的簇(如果有的话)
内容的提问来源于stack exchange,提问作者Ash
相关产品推荐
相关产品推荐

