使用k-Means聚类识别2D异常点未检出预期结果的问题排查
问题1:计算逻辑错误
你对kmeans.transform()的输出理解是对的,但后续距离计算逻辑完全错误:
transform()返回的二维数组中,每一行的两个值本身就是当前样本到两个簇质心的欧氏距离,不需要再将这两个值作为坐标计算二次欧氏距离。- 基于k-means的异常检测逻辑应该是:取每个样本到自身所属簇质心的距离作为异常得分,得分越高越可能是异常点。
我们先验证两个簇的质心:
你给定的7个样本在k=2的情况下,聚类得到的两个质心分别是(2,9)(对应前三个样本组成的簇)和(9.75,4)(对应后四个样本组成的簇)。我们把每个样本到自身所属簇的距离列出来:
- 前三个样本到所属簇的距离分别为1、0、1,均为正常值
- 后四个样本到所属簇
(9.75,4)的距离分别为:- (10,10):6.005
- (10,3):1.03
- (9,1):3.09
- (10,2):2.01
很明显(10,10)的距离远高于同簇的其他样本,就是你要找的异常点。你之前的计算相当于把两个簇的距离做了平方和开根号,混淆了数值含义,才会得到所有得分接近的结果。
问题2:k-means用于该场景异常检测的合理性
这个方案在当前场景下是合理的:
- 你的数据本身是明显的两个球形簇分布,符合k-means的聚类假设
- 你要找的是远离所属簇质心的点,正好匹配基于聚类的异常检测的核心逻辑,也是Charu《An Introduction to Outlier Analysis》中提到的经典聚类异常检测思路
但要注意k-means做异常检测的通用局限性: - 依赖k值的正确选择,k值错误会直接导致聚类结果偏差,异常检测失效
- k-means本身对异常点敏感,如果数据中异常点占比过高,会拉偏质心,导致漏检
- 仅对球形分布的簇效果好,如果数据簇是任意形状,需要换用DBSCAN等密度聚类方案
内容的提问来源于stack exchange,提问作者EJoshuaS
相关产品推荐
相关产品推荐

