如何对分组数据使用聚类分析,以便一个聚类每组只能包含不超过一项?

数据挖掘 聚类
2022-02-16 23:59:52

我需要在多(<5)维空间中按彼此的近似程度对项目进行分组。这些项目还具有分类特征。我需要形成组(集群),以便同一类别的所有记录都不会出现在同一集群中。有没有一类聚类算法可以做到这一点?

我的想法是使用自定义距离来测量同一类别中的两条记录,然后再测量不同类别中的两条记录。这在某种程度上有效,但不能保证满足给定的要求。

一个简单的一维 (x) + 类别 (c) 示例:

    xc
0 0.80 0
1 0.90 1
2 0.10 0
3 0.30 1
4 0.20 0

目标是将记录分为两个集群 [0, 1]; 和 [2 or 4, 3]; 那么记录 4 或 2 应该分别保留在第二个集群之外,因为集群中已经存在 c=0 的记录。

有什么建议么?

2个回答

您可以编写自己的算法。我很快草拟了一些东西。它可以显着优化。

让我们做一些随机数据

import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline

n = 9
x = np.random.rand(n,2)
y = np.zeros((n,))
y[n//3:2*n//3] = 1
y[2*n//3::] = 2

plt.scatter(x[:,0], x[:,1], c=y)
plt.show()

在此处输入图像描述

现在让我们得到每个点的间距。

dists = np.asarray([np.linalg.norm(i-j) for i in x for j in x]).reshape(n,n)

plt.imshow(dists)
plt.show()

在此处输入图像描述

我们将制作一个列表,其中包含每个点的每个圆的半径。对于每个点,我们将通过它们的相对接近度来迭代其他点。如果尚未看到关联的标签,请将其添加到临时列表中。否则,我们结束函数并取最后距离和当前非法点的平均值。

radii = []

for row in dists:
    labels = []
    dis = []
    for i in np.argsort(row):
        if y[i] not in labels:
            labels.append(y[i])
            dis = row[i]
        else:
            dis = (dis + row[i])/2
            break
    radii.append(dis)

现在我们可以绘制这些圆圈

fig, ax = plt.subplots(figsize=(10,10))

for ix, i in enumerate(radii):
    circle = plt.Circle((x[ix, 0], x[ix, 1]), i, color='b', fill=False, alpha = 0.5)
    ax.add_artist(circle)

plt.scatter(x[:,0], x[:,1], c=y)
plt.xlim([-0.2,1.4])
plt.ylim([-0.2,1.4])
plt.show()

在此处输入图像描述


如果我们增加数据点的数量n我们得到

在此处输入图像描述

请改用约束优化器。

定义你的目标——什么是好的结果。

然后定义你的约束(所有点都在一个组中,任何组中没有重复的标签)并运行它。