Как вы оцениваете качество модели NER? Почему micro-F1 и macro-F1 могут давать разную картину?
Краткий тезис
Оценка качества NER строится на строгом совпадении границ и типа сущности (строгий match). Основная метрика — F1, но способ её усреднения кардинально меняет интерпретацию: Micro-F1 суммирует ошибки по всем классам, давая взвешенную оценку по частоте сущностей; Macro-F1 усредняет F1 по каждому классу, делая редкие типы равноправными. Разница в значениях сигнализирует о дисбалансе классов и скрытых проблемах модели.
--------|---------------------------| | TP | Предсказанный span и тип полностью совпали с эталоном. | | FP | Предсказана сущность, которой нет в эталоне, либо неверные границы/тип. | | FN | Эталонная сущность не предсказана (пропущена) или предсказана неверно. |
Такое строгое определение делает NER-метрики чувствительными к точности границ — модель может «угадать» тип, но ошибиться на один токен, и это будет засчитано как ошибка.
2. Micro-F1: усреднение по всем токенам
Часто встречающееся заблуждение — что micro-F1 в NER считается по токенам. На практике micro-F1 обычно вычисляется на уровне сущностей (entity-level), но принцип тот же: все ошибки TP/FP/FN суммируются по всем классам, затем рассчитываются precision, recall и F1.
Формула (entity-level micro):
- Суммарные TP = Σ TP_класс_i
- Суммарные FP = Σ FP_класс_i
- Суммарные FN = Σ FN_класс_i
- Micro-Precision = TP / (TP + FP)
- Micro-Recall = TP / (TP + FN)
- Micro-F1 = 2 * (Micro-P * Micro-R) / (Micro-P + Micro-R)
Поскольку частые классы вносят больший вклад в сумму, micro-F1 отражает общую производительность на наиболее распространённых сущностях. Если в тексте 95% сущностей — это «Person», то micro-F1 будет почти полностью определяться качеством распознавания именно этого типа. Модель может полностью игнорировать редкий класс, но micro-F1 останется высоким.
Когда micro-F1 обманчив: при сильном дисбалансе классов, когда редкие типы критичны для бизнес-задачи (например, распознавание химических соединений в медицинских текстах). Micro-F1 не покажет проблему, если частый класс распознаётся отлично.
3. Macro-F1: усреднение по типам сущностей
Macro-F1 вычисляется в два этапа:
- Для каждого класса i отдельно считаем F1_i.
- Берём среднее арифметическое: Macro-F1 = (1/N) * Σ F1_i, где N — число классов.
Таким образом, каждый класс имеет равный вес независимо от числа его вхождений в корпус. Если редкий класс имеет F1=0.0, а частый — 0.98, то macro-F1 будет (0.0 + 0.98)/2 = 0.49, что сигнализирует о серьёзной проблеме.
Чувствительность macro-F1 полезна для:
- Поиска узких мест модели;
- Формальной оценки, когда каждый тип сущности одинаково важен для пользователя;
- Сравнения моделей на несбалансированных датасетах.
Если micro-F1 и macro-F1 близки — дисбаланс классов невелик или модель работает равномерно. Если macro-F1 значительно ниже — один или несколько редких классов проигрывают.
4. Пример: редкий тип важнее → macro-F1 чувствительнее
Рассмотрим вымышленный датасет с двумя типами сущностей:
- Person — 1000 вхождений (частый)
- Chemical — 10 вхождений (редкий)
Модель показывает:
- Суммарные TP = 950
- Суммарные FP = 50
- Суммарные FN = 60
- Precision = 950/1000 = 0.950
- Recall = 950/1010 ≈ 0.9406
- Micro-F1 ≈ 0.9453
- F1_Person = 0.950
- F1_Chemical = 0.000
- Macro-F1 = (0.950 + 0.000) / 2 = 0.475
Разница колоссальная: 0.945 vs 0.475. Micro-F1 убаюкивает — кажется, модель отличная. Macro-F1 же чётко указывает, что редкий класс полностью провален. Если задача требует распознавания химических веществ, такая модель бесполезна, и macro-F1 правильнее отражает реальное качество.
Дополнительные метрики для NER: помимо F1, можно измерять точность границ (boundary similarity), но стандарт в академических бенчмарках (CoNLL-2003, OntoNotes) — строгий entity-level F1 с макро-усреднением по классам.
5. Пет-проект для закрепления
Задача: самостоятельно вычислить micro- и macro-F1 для предсказаний NER-модели на несбалансированном датасете и проанализировать разницу.
Инструменты:
- Python 3.x, библиотеки
transformers,seqeval(entity-level метрики),pandas,matplotlib. - Готовая NER-модель, например
dslim/bert-base-NER(для английского) илиDeepPavlov/bert-base-cased-conversational(для русского). Для простоты можно взять датасет CoNLL-2003 или его русский аналог (Wikiner, FactRuEval).
Шаги:
- Загрузить датасет с размеченными сущностями, привести его к формату BIO-тегов.
- Разделить на train/test. Для эксперимента с дисбалансом можно взять только несколько классов, один из которых сделать редким (например, оставить всех «Person» и лишь 10-20 вхождений «Product»).
- Дообучить или применить предобученную модель (inference) на тестовом наборе.
- Получить предсказания в формате списка сущностей (start, end, type).
- Использовать библиотеку
seqeval:from seqeval.metrics import classification_report, f1_score # true_entities: list of lists of labels (token-level) – seqeval ждёт # можно перевести span-level в token-level report = classification_report(y_true, y_pred, digits=4) print(report) # Micro-F1: f1_score(y_true, y_pred, average='micro') # Macro-F1: f1_score(y_true, y_pred, average='macro') - Сравнить значения. Построить столбчатую диаграмму F1 по каждому классу.
Ожидаемый результат:
- Вы увидите, что micro-F1 близок к F1 частого класса, а macro-F1 усредняет все F1, давая заниженную оценку при плохом качестве на редком классе.
- Научитесь интерпретировать разницу и делать выводы о сбалансированности обучения модели.
Связь с другими вопросами
| Вопрос | Тема |
|---|---|
| 904 | Определение NER и обзор архитектур. Важно для понимания контекста метрик. |
Навигация
- Предыдущий: 904
- Следующий: 906
- Индекс: 00. Индекс разборов