← Назад к вопросам
Зачем нужно F1?
1.3 Junior🔥 261 комментариев
#Машинное обучение#Метрики и оценка моделей
Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
F1-мера: зачем нужна и когда её использовать
F1-мера — это гармоническое среднее precision и recall, один из самых важных метрик оценки качества классификационных моделей. Она решает критическую проблему: как оценить модель, когда важны оба типа ошибок.
1. Проблема: Accuracy недостаточна
Основная метрика accuracy часто обманчива при дисбалансе классов:
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import numpy as np
# Дисбалансированный датасет: 99% одного класса
y_true = [0] * 990 + [1] * 10 # 990 негативов, 10 позитивов
y_pred_lazy = [0] * 1000 # Модель просто всегда предсказывает 0
acc = accuracy_score(y_true, y_pred_lazy)
print(f"Accuracy: {acc:.1%}") # 99.0% — звучит отлично!
# Но на самом деле модель бесполезна:
precision = precision_score(y_true, y_pred_lazy, zero_division=0)
recall = recall_score(y_true, y_pred_lazy, zero_division=0)
f1 = f1_score(y_true, y_pred_lazy, zero_division=0)
print(f"Precision: {precision:.1%}")
print(f"Recall: {recall:.1%}")
print(f"F1: {f1:.2f}")
# Результат:
# Accuracy: 99.0%
# Precision: 0%
# Recall: 0%
# F1: 0.00
Accuracy врёт, F1 говорит правду.
2. Определение F1
F1-мера — гармоническое среднее precision и recall:
F1 = 2 * (Precision * Recall) / (Precision + Recall)
Gде:
- Precision = TP / (TP + FP) — из предсказанных как 1, сколько на самом деле 1
- Recall = TP / (TP + FN) — из всех реальных 1, сколько мы нашли
TP (True Positive) — верно предсказали 1
FP (False Positive) — неверно предсказали 1
FN (False Negative) — неверно предсказали 0
TN (True Negative) — верно предсказали 0
3. Когда нужна F1
Дисбалансированные классы
from sklearn.datasets import make_classification
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import f1_score, recall_score, precision_score
# Создаём дисбалансированный датасет
X, y = make_classification(
n_samples=10000,
n_features=20,
weights=[0.9, 0.1], # 90% класс 0, 10% класс 1
random_state=42
)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
# Обучить модель
model = RandomForestClassifier(random_state=42)
model.fit(X_train, y_train)
y_pred = model.predict(X_test)
# Сравнить метрики
print(f"Precision: {precision_score(y_test, y_pred):.3f}")
print(f"Recall: {recall_score(y_test, y_pred):.3f}")
print(f"F1: {f1_score(y_test, y_pred):.3f}")
# F1 учитывает обе ошибки одновременно
Медицинская диагностика
Оба типа ошибок критичны:
- False Positive (FP) — сказали болен, но здоров → ненужное лечение
- False Negative (FN) — сказали здоров, но болен → упущенная болезнь
F1 балансирует между этими рисками.
Информационный поиск (IR)
# Пример: поиск релевантных документов
y_true = [1, 1, 1, 0, 0, 1, 1, 0, 0, 1] # Истинно релевантные
y_pred = [1, 1, 0, 0, 1, 1, 0, 0, 1, 1] # Предсказанные моделью
# Важны оба:
# Precision: не выдавать нерелевантные документы
# Recall: не пропустить релевантные документы
precision = 5 / 7 # 5 из 7 предсказанных были верны
recall = 5 / 6 # 5 из 6 истинных нашли
f1 = 2 * (precision * recall) / (precision + recall)
print(f"Precision: {precision:.3f}")
print(f"Recall: {recall:.3f}")
print(f"F1: {f1:.3f}")
Spam Detection
# Важно минимизировать оба:
# FP: спам отфильтровать → потеря легитимных писем
# FN: легитимное письмо → попало в спам
# Модель со слабым recall (пропускает спам)
y_test = [0, 0, 0, 1, 1, 1] # 0=spam, 1=legit
y_pred = [0, 0, 0, 1, 1, 0] # Пропустили одно письмо
print(f"F1: {f1_score(y_test, y_pred):.3f}")
4. Взвешенная F1 (Weighted F1) для мультикласса
from sklearn.metrics import f1_score
# Мультиклассовая классификация
y_true = [0, 0, 1, 1, 2, 2, 2]
y_pred = [0, 0, 1, 2, 2, 2, 1]
# Невзвешенная (micro, macro, weighted)
f1_micro = f1_score(y_true, y_pred, average='micro') # По всем TP/FP/FN
f1_macro = f1_score(y_true, y_pred, average='macro') # Среднее по классам
f1_weighted = f1_score(y_true, y_pred, average='weighted') # Взвешено по размеру класса
print(f"F1 micro: {f1_micro:.3f}")
print(f"F1 macro: {f1_macro:.3f}")
print(f"F1 weighted: {f1_weighted:.3f}")
5. F1 vs другие метрики
| Метрика | Когда использовать | Проблемы |
|---|---|---|
| Accuracy | Сбалансированные классы | Не видит ошибки при дисбалансе |
| Precision | Важно минимизировать FP | Не учитывает FN |
| Recall | Важно минимизировать FN | Не учитывает FP |
| F1 | Нужен баланс Precision/Recall | Не учитывает TN |
| AUC-ROC | Вероятностные предсказания | Сложнее интерпретировать |
| Specificity | Минимизировать FP | Дополнение Recall |
6. Практический пример: выбор порога классификации
from sklearn.metrics import f1_score
import numpy as np
# Вероятностные предсказания
y_true = np.array([0, 0, 1, 1, 1, 0, 1, 0])
y_proba = np.array([0.1, 0.2, 0.7, 0.8, 0.9, 0.3, 0.6, 0.4])
# Найти оптимальный порог по F1
best_f1 = 0
best_threshold = 0
for threshold in np.arange(0, 1, 0.01):
y_pred = (y_proba >= threshold).astype(int)
f1 = f1_score(y_true, y_pred)
if f1 > best_f1:
best_f1 = f1
best_threshold = threshold
print(f"Оптимальный порог: {best_threshold:.2f}")
print(f"Лучший F1: {best_f1:.3f}")
7. Beta-взвешенная F-мера
Если важнее recall, можно использовать F-beta мору:
from sklearn.metrics import fbeta_score
# F2 (重点放在recall)
y_true = [0, 0, 1, 1, 1]
y_pred = [0, 0, 1, 1, 0]
f1 = f1_score(y_true, y_pred) # Баланс
f2 = fbeta_score(y_true, y_pred, beta=2) # Recall важнее
f0_5 = fbeta_score(y_true, y_pred, beta=0.5) # Precision важнее
print(f"F1: {f1:.3f}")
print(f"F2 (recall重视): {f2:.3f}")
print(f"F0.5 (precision重视): {f0_5:.3f}")
Выводы
F1-мера нужна потому что:
- Дисбалансированные классы — accuracy врёт, F1 объективна
- Баланс Precision-Recall — гармоническое среднее учитывает обе ошибки
- Production требование — во многих задачах нужен баланс:
- Медицина: не пропустить болезнь (recall) и не лечить здоровых (precision)
- Поиск: найти все релевантные (recall) и не выдать мусор (precision)
- Spam: минимизировать оба типа ошибок
- Интерпретируемость — даёт единую оценку от 0 до 1
Всегда смотрите на confusion matrix и F1 вместе с precision/recall, чтобы понять, где ошибается модель.