Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Когда использовать F-меру (F1-score)
F-мера (обычно F1-score) — это гармоническое среднее precision и recall. Это одна из самых популярных метрик в ML, но важно понимать когда она действительно полезна.
Определение F1-score
F1 = 2 * (Precision * Recall) / (Precision + Recall)
Почему гармоническое среднее, а не обычное?
import numpy as np
# Гармоническое среднее
p, r = 0.9, 0.1
f1_harmonic = 2 * (p * r) / (p + r) # 0.18 (наказывает дисбаланс)
f1_arithmetic = (p + r) / 2 # 0.5 (игнорирует дисбаланс)
print(f"Harmonic: {f1_harmonic:.3f}")
print(f"Arithmetic: {f1_arithmetic:.3f}")
Гармоническое среднее нельзя игнорировать одну из метрик. Если одна плохая, F1 плохой.
1. Когда F1 полезна: несбалансированные классы
Это главный сценарий использования F1:
from sklearn.metrics import accuracy_score, f1_score
y_true = [0]*95 + [1]*5 # 95% vs 5%, очень несбалансировано
y_pred = [0]*100 # модель всегда говорит 0
acc = accuracy_score(y_true, y_pred) # 0.95 (очень высокая!)
f1 = f1_score(y_true, y_pred) # 0.0 (модель не работает)
Accuracy вводит в заблуждение, F1 показывает истину.
2. Когда F1 НЕ лучший выбор
Когда FP и FN стоят по-разному:
Пример 1: Детекция рака
- Пропустить рак (FN) — пациент может умереть
- Ложный alarm (FP) — ненужное обследование
- FN намного дороже FP
- Нужен высокий recall, даже за счет precision
from sklearn.metrics import precision_recall_fscore_support
p, r, f1, _ = precision_recall_fscore_support(y_true, y_pred, average="binary")
# Если recall > 0.95, но precision = 0.5 → нормально!
# F1 не покажет эту важность recall
Пример 2: Спам-фильтр
- False Positive (письмо в спам) — потеря важного письма
- False Negative (спам в inbox) — раздражение
- FP дороже FN
- Нужна высокая precision
# F1 = гармоническое среднее, но нам нужна precision!
# Можно использовать weighted F-beta
3. F-beta score для разных приоритетов
Если нужно дать разный вес precision и recall:
from sklearn.metrics import fbeta_score
# F2 score — двойной вес recall (важнее не пропустить)
f2 = fbeta_score(y_true, y_pred, beta=2)
# F0.5 score — двойной вес precision (важнее точность)
f05 = fbeta_score(y_true, y_pred, beta=0.5)
# F1 score — равный вес
f1 = fbeta_score(y_true, y_pred, beta=1)
Формула:
F-beta = (1 + beta^2) * (Precision * Recall) / (beta^2 * Precision + Recall)
Интерпретация beta:
- beta > 1: recall важнее (F2, F3 для medical diagnostic)
- beta = 1: равно важны (F1 — стандарт)
- beta < 1: precision важнее (F0.5 для spam filter)
Пример: медицинская диагностика
# Рак: хотим поймать максимум случаев, можем терпеть false alarms
f2_score = fbeta_score(y_true, y_pred, beta=2)
print(f"F2 (recall важнее): {f2_score:.3f}")
# Vs спам-фильтр: точность важнее
f05_score = fbeta_score(y_true, y_pred, beta=0.5)
print(f"F0.5 (precision важнее): {f05_score:.3f}")
4. F1 для классификации с более чем 2 классами
Weighted Average F1 — самая популярная для мультиклассовой классификации:
from sklearn.metrics import f1_score
# Макро F1 — среднее по классам (все классы одинаково важны)
f1_macro = f1_score(y_true, y_pred, average="macro")
# Взвешенный F1 — средневзвешенное по размеру класса
f1_weighted = f1_score(y_true, y_pred, average="weighted")
# Микро F1 — глобальный подсчет TP, FP, FN
f1_micro = f1_score(y_true, y_pred, average="micro")
Когда какой использовать:
# Данные сбалансированы → macro F1
f1_macro = f1_score(y_true, y_pred, average="macro")
# Данные несбалансированы → weighted F1
f1_weighted = f1_score(y_true, y_pred, average="weighted")
# Хочу отражать класс 1 → binary F1
f1_binary = f1_score(y_true, y_pred, average="binary")
5. Практические сценарии для F1
Идеален для:
-
Несбалансированная классификация (fraud, disease, редкие события)
- Accuracy не работает
- ROC-AUC иногда высокий даже для плохых моделей
- F1 показывает реальную производительность
-
Когда не знаем стоимость ошибок
- Если точно не известно, FP vs FN что дороже
- F1 — reasonable default
-
Research и benchmarking
- Стандартная метрика для сравнения с другими работами
- Все используют F1, легко сравнивать
-
Быстрый прототип
- Когда нет time на детальный анализ
- F1 дает неплохое представление о качестве
НЕ идеален для:
- Сбалансированные данные → использовать accuracy
- Асимметричная стоимость ошибок → F-beta или custom метрика
- Ranking задачи → ROC-AUC или PR-AUC
- Мультилейбловая классификация → другие метрики
6. F1 vs ROC-AUC vs PR-AUC
| Метрика | F1 | ROC-AUC | PR-AUC |
|---|---|---|---|
| Что измеряет | Баланс P и R | Ранжирование | Точность vs полнота |
| Работает с несбалансом | Хорошо | Может обманывать | Отлично |
| Зависит от порога | Да (0.5) | Нет | Нет |
| Интуитивность | Высокая | Средняя | Высокая |
| Когда использовать | Binary общий случай | Ranking | Несбаланс + FP дорого |
7. Когда выбрать F1 — чеклист
Вопросы:
□ Классы несбалансированы?
□ Accuracy не работает как метрика?
□ Нет информации о стоимости FP vs FN?
□ Нужен single number для сравнения моделей?
□ Это binary classification?
Если да на 3+ вопроса → используй F1
Если нужен разный вес P и R → используй F-beta
Если нужна точность выше → используй PR-AUC
Если нужна асимметричная стоимость → используй custom метрику
Практический пример: ML в реальности
from sklearn.metrics import (
accuracy_score, precision_score, recall_score,
f1_score, roc_auc_score, fbeta_score
)
y_true = [0, 0, 0, 0, 1, 1, 1, 1, 1, 0]
y_pred = [0, 0, 0, 1, 1, 1, 0, 1, 1, 0]
print(f"Accuracy: {accuracy_score(y_true, y_pred):.3f}")
print(f"Precision: {precision_score(y_true, y_pred):.3f}")
print(f"Recall: {recall_score(y_true, y_pred):.3f}")
print(f"F1: {f1_score(y_true, y_pred):.3f}")
print(f"F2 (recall важнее): {fbeta_score(y_true, y_pred, beta=2):.3f}")
print(f"ROC-AUC: {roc_auc_score(y_true, y_pred):.3f}")
Итог
F1-score — best practice для несбалансированных классов. Используй его как default для:
- Fraud detection
- Medical diagnosis
- Spam detection
- Любой имбалансированной классификации
Но помни: F1 не универсален. Анализируй precision и recall отдельно, понимай стоимость ошибок, используй F-beta если нужны разные веса.