计算列表中重复元素的数量,考虑大于它们的元素

时间:2018-06-15 13:03:07

标签: python-3.x list numpy

我正在尝试对数据集进行一些聚类分析。我使用了许多不同的方法来估计簇的数量,然后我将每个方法给出的内容(簇的数量)放在列表​​中,如下所示:

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个群集)。

2 个答案:

答案 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投票的数量。在01的范围内。

请注意,这种方法可以让选民同意一个不在列表中的数字。

我们需要更新我们的代码以应用该伪测量。

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}

nth 距离

的反转

这是前一个概括。随着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}

正态分布

另一个明智的选择是normal distributionskewed normal distribution

答案 1 :(得分:0)

虽然另一个答案提供了对可能的指标和方法的全面审查,但您正在寻找的是找到最接近的聚类数量! 所以简单如下:

cluster_num=int(np.round(np.mean(total_pred)))

对于您的所有案例,它会返回1,如您所愿。

相关问题