Сравнение двух словарей списков кортежей для расчета F-показателя - PullRequest
0 голосов
/ 25 августа 2018

Python noob здесь.

У меня есть два словаря списков кортежей: my_gold_mentions, который включает в себя мои золотые данные, и my_coref, который включает в себя автоматически генерируемые данные.

Оба словаря выглядят так:

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

Я пытаюсь вычислить F балл , сравнивая кортежи автоматически сгенерированного словаря с золотыми данными.

Если для кортежа есть совпадение, то я хотел бы проверить, имеют ли оба этих совпадающих кортежа одинаковый ключ, в данном случае: имя общего персонажа, например, 'Anakin'.

Если это так, то добавьте 1 к счету True Positives .

Если ключи не похожи, автоматически генерируемый ключ существует в словаре данных золота какв общем случае (в данном случае: другой символ, чем 'Anakin'), тогда я должен считать его оба a ложное отрицательное и ложное положительное .

Наконец, если ключ вообще отсутствует в словаре данных gold, тогда рассмотрите его только как 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).

Я не уверен, как сравнить два словаря списков кортежей.

Любые идеи о том, как улучшить код выше для достижения этой цели?

Помощь очень ценится!

Ответы [ 2 ]

0 голосов
/ 25 августа 2018

Измените my_gold_mentions и my_coref на my_gold_mentions.items() и my_coref.items(), это позволит вам получить доступ к keys и values, которые вы пытаетесь сравнить

for gold_key, gold_value in my_gold_mentions.items():
    for auto_key, auto_value in my_coref.items():
0 голосов
/ 25 августа 2018

Наивным, O(n^2) решением было бы перебрать все кортежи во всех списках (значениях словаря) случайно сгенерированных данных и проверить, соответствуют ли эти кортежи любому из кортежей в любом из списков золота. данные. Это было бы неэффективно для большого набора данных, так как в худшем случае, когда нет совпадений, вам нужно перебрать все наборы данных золотых данных для каждого набора в рандомизированных наборах.

Более быстрый метод - использовать структуру данных, которая позволяет искать в среднем регистре O(1) (в отличие от поиска O(n) в списке). Python поддерживает следующие типы: dictionary и set.

A 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...