Как получить вероятность предсказания для каждой сущности из модели Spacy NER?

Я использовал этот официальный пример кода для обучения NER моделировать с нуля на собственных обучающих образцах.

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

    # test the saved model
    print("Loading from", output_dir)
    nlp2 = spacy.load(output_dir)
    for text, _ in TRAIN_DATA:
        doc = nlp2(text)
        print("Entities", [(ent.text, ent.label_) for ent in doc.ents])
        print("Tokens", [(t.text, t.ent_type_, t.ent_iob) for t in doc])

Я не могу найти в Spacy метод, позволяющий получить вероятность предсказания каждой сущности.

Как мне получить эту вероятность от Спейси? Он мне нужен, чтобы наложить на него обрезку.


person GeorgeOfTheRF    schedule 23.01.2020    source источник
comment
Подход с балкой у вас сработал?   -  person DBaker    schedule 28.01.2020


Ответы (2)


Получение вероятностей предсказания для каждой сущности из модели Spacy NER нетривиально. Вот решение, адаптированное из здесь:


import spacy
from collections import defaultdict

texts = ['John works at Microsoft.']

# Number of alternate analyses to consider. More is slower, and not necessarily better -- you need to experiment on your problem.
beam_width = 16
# This clips solutions at each step. We multiply the score of the top-ranked action by this value, and use the result as a threshold. This prevents the parser from exploring options that look very unlikely, saving a bit of efficiency. Accuracy may also improve, because we've trained on greedy objective.
beam_density = 0.0001 
nlp = spacy.load('en_core_web_md')


docs = list(nlp.pipe(texts, disable=['ner']))
beams = nlp.entity.beam_parse(docs, beam_width=beam_width, beam_density=beam_density)

for doc, beam in zip(docs, beams):
    entity_scores = defaultdict(float)
    for score, ents in nlp.entity.moves.get_beam_parses(beam):
        for start, end, label in ents:
            entity_scores[(start, end, label)] += score

l= []
for k, v in entity_scores.items():
    l.append({'start': k[0], 'end': k[1], 'label': k[2], 'prob' : v} )

for a in sorted(l, key= lambda x: x['start']):
    print(a)

### Output: ####

{'start': 0, 'end': 1, 'label': 'PERSON', 'prob': 0.4054479906820232}
{'start': 0, 'end': 1, 'label': 'ORG', 'prob': 0.01002015005487447}
{'start': 0, 'end': 1, 'label': 'PRODUCT', 'prob': 0.0008592912552754791}
{'start': 0, 'end': 1, 'label': 'WORK_OF_ART', 'prob': 0.0007666755792166002}
{'start': 0, 'end': 1, 'label': 'NORP', 'prob': 0.00034931990870877333}
{'start': 0, 'end': 1, 'label': 'TIME', 'prob': 0.0002786051849320804}
{'start': 3, 'end': 4, 'label': 'ORG', 'prob': 0.9990115861687987}
{'start': 3, 'end': 4, 'label': 'PRODUCT', 'prob': 0.0003378157477046507}
{'start': 3, 'end': 4, 'label': 'FAC', 'prob': 8.249734411749544e-05}

person DBaker    schedule 24.01.2020
comment
Я не понимаю - start и end этих оценок сущностей не соответствуют самим сущностям ... это говорит о том, что сущность PERSON начинается с 0, но заканчивается на 1 ... но то же самое делают ORG, PRODUCT, WORK_OF_ART и другие сущности. Как мы должны использовать этот результат / оценки? - person zelusp; 19.11.2020
comment
в spacy 3.0.6 мне пришлось заменить nlp.entity на nlp.get_pipe('ner'), или как там называется канал ner. - person Thomas Luechtefeld; 28.04.2021

Извините, у меня нет лучшего ответа - я могу только подтвердить, что решение 'луча' действительно обеспечивает некоторые 'вероятности', хотя в моем случае я получаю слишком много сущностей с prob = 1.0, даже в тех случаях, когда я могу только встряхнуть мою голову и виню в этом слишком мало тренировочных данных.

Мне кажется довольно странным, что Спейси сообщает о «сущности», не имея к ней никакой уверенности. Я предполагаю, что есть некоторый порог, чтобы решить, КОГДА Spacy сообщает о сущности, а когда - НЕТ (возможно, я это пропустил). В моем случае я вижу, что степень достоверности 0,6 сообщается как «это объект», в то время как объект с достоверностью 0,001 НЕ сообщается.

В моем случае уверенность важна. Для данного текста Spacy (и, например, Google ML) сообщают о нескольких экземплярах "MY_ENTITY". Мой код должен решить, каким из них «доверять», а каким - ложноположительным. Мне еще предстоит увидеть, имеет ли «вероятность», возвращаемая приведенным выше кодом, какое-либо практическое значение.

person mbrunecky    schedule 26.05.2020