我正在尝试对数据集进行一些聚类分析。我使用了许多不同的方法来估计簇的数量,然后我将每个方法给出的内容(簇的数量)放在列表中,如下所示:
total_pred = [0, 0, 1, 1, 0, 1, 1]
现在我想估计集群的实际数量,所以我让上面的方法投票,例如,上面,找到1个集群比0更多的模型,所以我把1作为实际的集群数。
我是这样做的:
counts = np.bincount(np.array(total_pred))
real_nr_of_clusters = np.argmax(counts))
然而,这种方法存在问题。如果上面的列表包含以下内容:
[2, 0, 1, 0, 1, 0, 1, 0, 1]
我将得到0个簇作为平均值,因为0经常重复。但是,如果一个模型找到2个集群,则可以安全地假设它至少考虑了1个集群,因此实数将为1.
如何通过修改上述代码段来完成此操作?
为了解决问题,这里有一些例子:
[1, 1, 1, 0, 0, 0, 3]
应该返回1,
[0, 0, 0, 1, 1, 3, 4]
也应该返回1(因为大多数人同意至少有1个群集)。
答案 0 :(得分:1)
以下是所述算法的实现。
l = [2, 0, 1, 0, 1, 0, 1, 0, 1]
l = sorted(l, reverse=True)
votes = {x: i for i, x in enumerate(l, start=1)}
{2: 1, 1: 5, 0: 9}
请注意,由于您将投票定义为与小于自身的任何内容达成一致,因此min(l)
将始终获胜,因为每个人都会同意至少有min(l)
个集群。在这种情况下min(l) == 0
。
事先注意,取均值或中位数是有效且轻量级的选项,它们都能满足你的例子所需的输出。
虽然,如果您遇到[0, 0, 7, 8, 10]
等方差较高的投票而且答案不是5
,那么取平均值可能不是您想要的。
更常见的解决方法是将选民偏向于接近他们的选票。当然,2名选民会同意1
而不是0
。
您可以通过实施指标(请注意:这不是数学意义上的指标)来确定投票支持x
的实例愿意同意对y
投票的数量。在0
到1
的范围内。
请注意,这种方法可以让选民同意一个不在列表中的数字。
我们需要更新我们的代码以应用该伪测量。
def d(x, y):
return x <= y
l = [2, 0, 1, 0, 1, 0, 1, 0, 1]
votes = {y: sum(d(x, y) for x in l) for y in range(min(l), max(l) + 1)}
{0: 9, 1: 5, 2: 1}
上述指标是一项健全性检查。这是你在问题中提供的那个,它最终确定0
获胜。
你必须对你的指标玩一点,但这里有一些可能有意义。
def d(x, y):
return 1 / (1 + abs(x - y))
l = [2, 0, 1, 0, 1, 0, 1, 0, 1]
votes = {y: sum(d(x, y) for x in l) for y in range(min(l), max(l) + 1)}
# {0: 6.33, 1: 6.5, 2: 4.33}
这是前一个概括。随着n
的增长,选民倾向于越来越少地同意远程投票。
def d(x, y, n=1):
return 1 / (1 + abs(x - y)) ** n
l = [2, 0, 1, 0, 1, 0, 1, 0, 1]
votes = {y: sum(d(x, y, n=2) for x in l) for y in range(min(l), max(l) + 1)}
# {0: 5.11, 1: 5.25, 2: 2.44}
与之前的指标类似,这个指标与您最初所描述的一致,因为选民永远不会同意高于他们的投票。
def d(x, y, n=1):
return 1 / (1 + abs(x - y)) ** n if x >= y else 0
l = [2, 0, 1, 0, 1, 0, 1, 0, 1]
votes = {y: sum(d(x, y, n=2) for x in l) for y in range(min(l), max(l) + 1)}
# {0: 5.11, 1: 4.25, 2: 1.0}
答案 1 :(得分:0)
虽然另一个答案提供了对可能的指标和方法的全面审查,但您正在寻找的是找到最接近的聚类数量! 所以简单如下:
cluster_num=int(np.round(np.mean(total_pred)))
对于您的所有案例,它会返回1,如您所愿。