Python中ROCK算法聚类分组数量异常问题求助
ROCK算法处理分类数据聚类失效的解决办法
问题场景
使用Python做分类数据聚类时,K-modes算法可将286条数据正常分为4组,但改用pyclustering库的ROCK算法时,所有数据各自成组,完全不符合预期。代码如下:
from pyclustering.cluster.rock import rock; rules_rock_dataframe = rules_rock_dataframe.astype(float) rules_rock_dataframe_list = rules_rock_dataframe.values.tolist() rock = rock(rules_rock_dataframe_list, 2.0, number_clusters=4) rock.process() clusters = rock.get_clusters() print(clusters)
问题根源
- 错误转换数据类型:将分类数据转为
float,丢失了类别语义,导致后续距离计算完全偏离分类数据的相似性逻辑。 - 默认距离度量不适配:
pyclustering的ROCK实现默认使用欧氏距离,该距离针对数值型数据设计,无法正确衡量分类数据间的相似性——分类数据的相似性应该基于特征是否匹配,而非数值大小差异,因此算法无法识别样本间的关联,最终每个样本被判定为独立聚类。
解决方案
1. 恢复原始数据类型,取消float转换
分类数据应保留原始编码(整数或字符串均可),不要转为浮点型,避免语义丢失。
2. 自定义分类数据的距离度量
给ROCK算法传入适配分类数据的距离函数,比如计算两个样本不同特征的数量(差异越大,距离越大):
from pyclustering.cluster.rock import rock # 自定义分类数据距离函数:返回两个样本不同特征的数量 def categorical_distance(sample1, sample2): return sum(feature1 != feature2 for feature1, feature2 in zip(sample1, sample2)) # 直接使用原始分类数据转成的列表(不要转float) rules_rock_dataframe_list = rules_rock_dataframe.values.tolist() # 初始化ROCK时传入自定义距离函数,同时可根据数据调整阈值参数 rock_instance = rock( data=rules_rock_dataframe_list, eps=2.0, number_clusters=4, metric=categorical_distance ) rock_instance.process() clusters = rock_instance.get_clusters() print(clusters)
3. 调整阈值参数eps
eps是ROCK算法中用于定义邻域的阈值,需要根据自定义距离的结果调整——如果自定义距离返回的是不同特征的数量,eps的值要符合数据的特征数量和分布,比如特征数为10的话,eps=2表示允许最多2个特征不同的样本视为邻域内的点。
内容的提问来源于stack exchange,提问作者Qba515
相关产品推荐
相关产品推荐

