← Назад к вопросам

Зачем нужно 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-мера нужна потому что:

  1. Дисбалансированные классы — accuracy врёт, F1 объективна
  2. Баланс Precision-Recall — гармоническое среднее учитывает обе ошибки
  3. Production требование — во многих задачах нужен баланс:
    • Медицина: не пропустить болезнь (recall) и не лечить здоровых (precision)
    • Поиск: найти все релевантные (recall) и не выдать мусор (precision)
    • Spam: минимизировать оба типа ошибок
  4. Интерпретируемость — даёт единую оценку от 0 до 1

Всегда смотрите на confusion matrix и F1 вместе с precision/recall, чтобы понять, где ошибается модель.