【问题标题】:Comparing two dictionaries of lists of tuples in order to calculate F-score比较两个元组列表字典以计算 F 分数
【发布时间】:2018-08-25 17:04:21
【问题描述】:

这里是 Python 菜鸟。

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

这两个字典看起来像这样:

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

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

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

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

如果键不相似,但自动生成的键通常作为键存在于黄金数据字典中(在这种情况下:除'Anakin'之外的另一个字符),那么我应该认为它是两者 假阴性假阳性

最后,如果该键在黄金数据字典中根本不存在,则认为它只是一个假阴性

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

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)

我不知道如何比较两个元组列表字典。

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

非常感谢您的帮助!

【问题讨论】:

  • 迭代键:值,你想要dict.items()
  • 这是你应该学会调试自己的东西。几乎所有的问题都与问题无关,它是一个纯 Python 问题。尝试做for x, y in {"a": 1, "b": 2}: pass,你会遇到同样的问题。要了解原因,请运行 for thing in {"a": 1, "b": 2}: print(thing)

标签: python list dictionary tuples


【解决方案1】:

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

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

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

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

{(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'}

现在您已经创建了一个更好的数据结构(我们称之为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_coref 为:

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

给出正确的结果:

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

【讨论】:

  • 感谢您的详细解答!它非常有用且内容丰富。可悲的是,我收到了AttributeError: 'tuple' object has no attribute 'items'for name, tups in my_coref.items(): 行。
  • 您是否将my_coref 定义为我在代码下方显示的格式的字典?
  • 啊,抱歉 - 我在某个地方出了点小错误,我没有注意到。效果很好,谢谢!
  • @Waldkamel 没问题。那就请采纳吧! (灰色--> 此答案旁边的绿色勾号)
【解决方案2】:

my_gold_mentionsmy_coref 更改为my_gold_mentions.items()my_coref.items() 这将允许您访问您正在尝试比较的keysvalues

for gold_key, gold_value in my_gold_mentions.items():
    for auto_key, auto_value in my_coref.items():

【讨论】:

    猜你喜欢
    • 2017-08-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多