Есть ли способ в модели NER в spaCy извлекать метрики (точность, отзыв, оценка f1) для каждого типа объекта?
Что-то вроде этого:
precision recall f1-score support
B-LOC 0.810 0.784 0.797 1084
I-LOC 0.690 0.637 0.662 325
B-MISC 0.731 0.569 0.640 339
I-MISC 0.699 0.589 0.639 557
B-ORG 0.807 0.832 0.820 1400
I-ORG 0.852 0.786 0.818 1104
B-PER 0.850 0.884 0.867 735
I-PER 0.893 0.943 0.917 634
сред / всего 0,809 0,787 0,796 6178
взято из: http://www.davidsbatista.net/blog/2018/05/09/Named_Entity_Evaluation/
Спасибо!






Хороший вопрос.
Во-первых, мы должны уточнить, что spaCy использует схему аннотации BILUO вместо схемы аннотации BIO, о которой вы говорите. Буквы большого документация обозначают следующее:
Затем несколько определений:
Spacy имеет встроенный класс для оценки NER. Он называется бомбардир. Счетчик использует точное соответствие для оценки NER. Оценка точности возвращается как ents_p, отзыв как ents_r и оценка F1 как ents_f.
Единственная проблема заключается в том, что он возвращает оценку для всех тегов в документе. Однако мы можем вызвать функцию только с нужным нам ТЕГОМ и получить желаемый результат.
В целом код должен выглядеть так:
import spacy
from spacy.gold import GoldParse
from spacy.scorer import Scorer
def evaluate(nlp, examples, ent='PERSON'):
scorer = Scorer()
for input_, annot in examples:
text_entities = []
for entity in annot.get('entities'):
if ent in entity:
text_entities.append(entity)
doc_gold_text = nlp.make_doc(input_)
gold = GoldParse(doc_gold_text, entities=text_entities)
pred_value = nlp(input_)
scorer.score(pred_value, gold)
return scorer.scores
examples = [
("Trump says he's answered Mueller's Russia inquiry questions \u2013 live",{"entities":[[0,5,"PERSON"],[25,32,"PERSON"],[35,41,"GPE"]]}),
("Alexander Zverev reaches ATP Finals semis then reminds Lendl who is boss",{"entities":[[0,16,"PERSON"],[55,60,"PERSON"]]}),
("Britain's worst landlord to take nine years to pay off string of fines",{"entities":[[0,7,"GPE"]]}),
("Tom Watson: people's vote more likely given weakness of May's position",{"entities":[[0,10,"PERSON"],[56,59,"PERSON"]]}),
]
nlp = spacy.load('en_core_web_sm')
results = evaluate(nlp, examples)
print(results)
Вызовите функцию оценки с соответствующим параметром ent, чтобы получить результаты для каждого тега.
Надеюсь, это поможет :)
@gdaras Я цитирую вас: «Счетчик использует точное соответствие для оценки NER». Откуда вы это знаете? Вы поможете мне, сообщив мне свой источник :) Спасибо
Ответ @gdaras неверен. Первый комментарий дает представление о том, почему. Вы должны фильтровать объекты
pred_value = nlp(input_)
Я сделал это вот так
pred_value.ents = [e for e in pred_value.ents if e.label_ == ent]
@Ruwan, я не совсем понял вашу точку зрения, где мне это добавить?
Используйте ответ @gdaras в качестве отправной точки. Вы должны добавить мою вторую строку сразу после моей первой (найдите ее в первом ответе). Используйте аналогичную фильтрацию для text_entities перед gold = GoldParse (doc_gold_text, entity = text_entities)
Можете ли вы переписать фрагмент кода в своем ответе, поскольку он сбивает с толку?
Я работал над этим, и теперь он интегрирован в этот Запрос на вытягивание.
Теперь вам просто нужно вызвать Scorer().scores, и он вернет обычный dict с дополнительным ключом ents_per_type, который будет содержать метрики Precision, Recall и F1-Score для каждого объекта.
Надеюсь, это поможет!
@gdaras, можете ли вы взглянуть на мой вопрос здесь: stackoverflow.com/questions/58376213/…
Можете ли вы посмотреть на мой вопрос здесь stackoverflow.com/questions/58376213/…
Из spacy v3,
# Проверяет модель
import spacy
from spacy.training.example import Example
nlp = spacy.load("./model_saved")
examples = []
data = [("Taj mahal is in Agra.", {"entities": [(0, 9, 'name'),
(16, 20, 'place')]})]
for text, annots in data:
doc = nlp.make_doc(text)
examples.append(Example.from_dict(doc, annots))
print(nlp.evaluate(examples)) # This will provide overall and per entity metrics
Да, результаты будут такими:
{'token_acc': 1.0, 'token_p': 1.0, 'token_r': 1.0, 'token_f': 1.0, 'ents_p': 0.8571428571428571, 'ents_r': 0.5454545454545454, 'ents_f': 0.6666666666666665, 'ents_per_type': {'KEY5': {'p': 0.8571428571428571, 'r': 0.5454545454545454, 'f': 0.6666666666666665}}, 'speed': 34577.72779537917}
Я думаю, что с этим что-то не так, когда я запускаю оценку для всех объектов, я получаю очень хорошие результаты (> 90% для P, R и F), однако, когда я фильтрую объекты с помощью вашей функции, R остается высоким, но P и F упадут до крайне низкого уровня (ниже 20%). Поэтому я думаю, что функция неправильно оценивает значение в строке GoldParse (). Может быть, это с учетом всех сущностей в первом параметре?