首页 > 解决方案 > 比较两个元组列表字典以计算 F 分数

问题描述

Python 菜鸟在这里。

我有两个元组列表字典:my_gold_mentions,其中包括我的黄金数据,以及my_coref,其中包括自动生成的数据。

两个字典看起来像这样:

{'Anakin': [(6532, 6538),
            (6590, 6592),
            (6673, 6675)],
 'He': [(3600, 3602),
        (3609, 3612)],...}  #  etc.

我试图通过将自动生成的字典的元组与黄金数据的元组进行比较来计算F 分数。

如果元组匹配,那么我想检查这两个匹配的元组是否具有相同的键,在这种情况下:共享字符的名称,例如'Anakin'.

如果是这样:则将 1 添加到True Positives计数。

如果键不相似,但自动生成的键通常作为键存在于黄金数据字典中(在这种情况下:另一个字符而不是'Anakin'),那么我应该认为它既False Negative又是False Positive

最后,如果黄金数据字典中根本不存在该键,则仅将其视为False Negative

到目前为止,我已经尝试过:

TP = 0
FP = 0
FN = 0
for gold_key, gold_value in my_gold_mentions:
    for auto_key, auto_value in my_coref:
        if auto_value == gold_value:
            if auto_key == gold_key:
                TP += 1
            elif auto_key != gold_key and auto_key in my_gold_mentions:
                FN += 1
                FP += 1
        else:
            FN += 1

这看起来不是很有效,因为我得到了一个ValueError: too many values to unpack (expected 2).

我不确定如何比较两个元组列表字典。

关于如何改进上述代码以实现该目标的任何想法?

非常感谢您的帮助!

标签: pythonlistdictionarytuples

解决方案


一个天真的O(n^2)解决方案是遍历随机生成的数据的所有列表(字典值)中的所有元组,并检查这些元组是否与任何黄金数据列表中的任何元组匹配。对于大型数据集,这将是低效的,因为更糟糕的情况是不匹配,您需要遍历随机元组中每个元组的所有黄金数据数据元组。

一种更快的方法是使用允许平均情况O(1)查找的数据结构(与O(n)列表中的查找相反)。Python 支持的类型是dictionaryset

Aset是项目的集合,其中每个项目通常包含一个数据。dictionary当有两个链接的数据时,A更合适。在这里,您确实有两个链接/相关的项目,即名称和元组。

由于您将不断检查字典中是否存在元组,因此只有以以下格式存储它们才会有效,因为您可以非常有效地查询任何元组。此外,当您确实找到一个元组并想知道它的名称时,您也可以立即找到它。

{(123,456):'some_name',
 (234,567):'another_name')}

要将您的my_gold_mentions字典转换为我建议的格式,您可以使用此字典理解:

{tup:name for name, tups in my_gold_mentions.items() for tup in tups}

这使:

{(6532, 6538): 'Anakin',
 (6590, 6592): 'Anakin',
 (6673, 6675): 'Anakin',
 (3600, 3602): 'He',
 (3609, 3612): 'He'}

现在您已经创建了一个更好的数据结构(我们称之为 this tup_gold_mentions),您可以高效地完成任务:

TP = FN = FP = 0
for name, tups in my_coref.items():
    for tup in tups:
        if tup in tup_gold_mentions:
            if name == tup_gold_mentions[tup]:
                TP += 1
            else:
                FN += 1
                FP += 1
        else:
            FN += 1

其中,与my_corefas:

{'Anakin': [(6532, 6538),
            (123, 45)],
 'Bob': [(3600, 3602)],
 'Jim': [(12, 34)]}

给出正确的结果:

>>> TP
1
>>> FP
1
>>> FN
3

推荐阅读