能否获取KMeans聚类中样本归属特定簇的不等式规则?
KMeans簇的不等式规则推导方案
可以推导这类不等式规则,但KMeans本身没有原生提供规则输出功能——因为它的核心逻辑是基于样本到质心的距离分配簇,我们可以把这个距离条件展开成不等式组。
核心原理
KMeans中,一个样本属于簇i的充要条件是:该样本到簇i质心的距离,严格小于到其他所有簇质心的距离。
如果用欧氏距离(KMeans默认距离),把这个条件展开后会得到一组线性不等式(平方项会相互抵消):
假设目标簇质心为C_i = (c_i1, c_i2, ..., c_id),其他簇质心为C_j = (c_j1, c_j2, ..., c_jd),样本为X = (x1, x2, ..., xd),则:
||X - C_i||² < ||X - C_j||²
展开化简后得到:
2*(c_j1 - c_i1)x1 + 2*(c_j2 - c_i2)x2 + ... + 2*(c_jd - c_id)xd < (c_j1² + c_j2² + ... + c_jd²) - (c_i1² + c_i2² + ... + c_id²)
对每个其他簇j都生成这样的不等式,组合起来就是判断样本属于簇i的规则。
sklearn下的实现步骤
1. 训练KMeans模型并获取质心
先完成模型训练,通过cluster_centers_属性拿到所有簇的质心:
from sklearn.cluster import KMeans import numpy as np # 示例数据 X = np.random.rand(100, 3) # 3维数据 kmeans = KMeans(n_clusters=3, random_state=42).fit(X) centers = kmeans.cluster_centers_
2. 生成目标簇的不等式规则
写一个函数,输入训练好的模型和目标簇索引,输出对应的不等式系数与阈值:
def get_cluster_rules(kmeans_model, target_cluster_idx): centers = kmeans_model.cluster_centers_ target_center = centers[target_cluster_idx] rules = [] for idx, center in enumerate(centers): if idx == target_cluster_idx: continue # 计算不等式系数和阈值 coeff = 2 * (center - target_center) threshold = np.sum(center ** 2) - np.sum(target_center ** 2) rules.append((coeff, threshold)) return rules
3. 使用规则判断样本
再写一个判断函数,验证样本是否满足所有不等式:
def is_in_cluster(sample, rules): sample = np.array(sample) for coeff, threshold in rules: # 不满足任意一个不等式就不属于目标簇 if np.dot(coeff, sample) >= threshold: return False return True
测试示例
# 取一个已知属于簇0的样本 test_sample = X[kmeans.labels_ == 0][0] # 获取簇0的规则 cluster_0_rules = get_cluster_rules(kmeans, 0) # 判断 print(is_in_cluster(test_sample, cluster_0_rules)) # 输出True
注意事项
- 只有欧氏距离下,规则是线性不等式;如果使用曼哈顿距离等其他度量,规则形式会不同,甚至是非线性的。
- 高维数据下,生成的不等式组会非常冗长,可读性差,此时直接用模型的
predict方法会更高效。 - 对于恰好落在簇边界(到两个质心距离相等)的样本,规则会返回
False,而KMeans会随机分配簇标签(这种情况在实际数据中极少出现)。
内容的提问来源于stack exchange,提问作者Mangostino
相关产品推荐
相关产品推荐

