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

Какой будет precision для алгоритма, который всегда прогнозирует 1?

2.0 Middle🔥 171 комментариев
#Метрики и оценка моделей

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI30 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Precision для алгоритма, который всегда прогнозирует 1

Краткий ответ

Precision будет равен доле положительных примеров в датасете (другими словами, базовой частоте класса 1).

Формула: Precision = TP / (TP + FP) = P(y=1) = примеры с y=1 / всего примеров

Математическое объяснение

DealerI define confusion matrix для бинарной классификации:

                Predicted
              0    1
Actual  0    TN   FP
        1    FN   TP

Если алгоритм всегда предсказывает 1:

  • TP (True Positive): примеры где y=1 и предсказал 1 — это ВСЕ положительные примеры
  • FP (False Positive): примеры где y=0 и предсказал 1 — это ВСЕ отрицательные примеры
  • TN (True Negative) = 0 (никогда не предсказываем 0)
  • FN (False Negative) = 0 (никогда не предсказываем 0)

Пример

Предположим, у нас датасет с 70 примеров класса 1 и 30 примеров класса 0 (всего 100):

import numpy as np
from sklearn.metrics import precision_score, recall_score, f1_score, confusion_matrix

# Реальные метки
y_true = np.array([1]*70 + [0]*30)  # 70 примеров класса 1, 30 класса 0

# Алгоритм, который ВСЕГДА прогнозирует 1
y_pred_always_one = np.ones(100)  # [1, 1, 1, ..., 1]

# Confusion matrix
cm = confusion_matrix(y_true, y_pred_always_one)
print("Confusion Matrix:")
print(cm)
# Output:
# [[0, 30],   <- класс 0: 0 TN, 30 FP
#  [0, 70]]   <- класс 1: 0 FN, 70 TP

tp = cm[1, 1]  # 70
fp = cm[0, 1]  # 30

precision = tp / (tp + fp)
print(f"Precision = {tp} / ({tp} + {fp}) = {precision}")
print(f"Precision = 70 / 100 = 0.70")

# Проверим со sklearn
precision_sklearn = precision_score(y_true, y_pred_always_one)
print(f"Precision (sklearn): {precision_sklearn}")

Результат: Precision = 0.70 (или 70%)

Почему именно базовая частота класса?

Precision = TP / (TP + FP)
         = (все положительные примеры) / (все примеры)
         = количество примеров с y=1 / общее количество примеров
         = доля класса 1 в датасете

Это очень важный вывод!

Практическое значение

На сбалансированном датасете (50% класс 0, 50% класс 1):

y_true = [1]*50 + [0]*50
y_pred = [1]*100

precision = 50 / 100 = 0.50  # Даже хуже, чем бросить монету!

На несбалансированном датасете (90% класс 1, 10% класс 0):

y_true = [1]*90 + [0]*10
y_pred = [1]*100

precision = 90 / 100 = 0.90  # Кажется неплохо, но это обман!

Важный вывод: это НЕ показатель качества!

Высокая precision в этом случае НЕ означает хороший алгоритм. Это значит, что в датасете много примеров класса 1.

# Посмотрим на другие метрики
recall = precision_score(y_true, y_pred_always_one)
recall_score(y_true, y_pred_always_one)

print(f"Precision: {precision_sklearn}")
print(f"Recall: {recall_score(y_true, y_pred_always_one)}")
print(f"F1-score: {f1_score(y_true, y_pred_always_one)}")

# Output для датасета 70/30:
# Precision: 0.70
# Recall: 1.00  <- мы ловим ВСЕ положительные примеры
# F1-score: 0.82

Интерпретация метрик

Для алгоритма "всегда 1" на датасете 70% класс 1, 30% класс 0:

  • Precision = 0.70: Из всех примеров, которые мы классифицировали как 1, 70% действительно класс 1
  • Recall = 1.00: Мы поймали ВСЕ положительные примеры (не пропустили ни одного)
  • F1-score = 0.82: Гармоническое среднее precision и recall

Это объясняет, почему precision равна доле класса 1!

Когда это может быть проблемой?

# Датасет с редким классом (fraud detection)
y_true = [1]*5 + [0]*995  # 0.5% мошенничества
y_pred = [1]*1000  # Всегда предсказываем fraud

precision = 5 / 1000 = 0.005  # Очень низкая!
recall = 5 / 5 = 1.0  # Но ловим все обманы

В этом случае precision очень низкая, потому что класс редкий.

Практический совет

Этот пример демонстрирует важное правило:

Никогда не выбирай метрику на основе её значения, выбирай на основе задачи:

  1. Fraud detection: Важен Recall (не пропустить обман), Precision вторичен
  2. Spam detection: Важна Precision (не отправить спам), Recall менее критичен
  3. Medical diagnosis: Важен Recall (не пропустить болезнь), Precision может быть ниже
  4. Общий случай: Используй F1-score или ROC-AUC

Полный пример с различными датасетами

def analyze_always_one(p_positive):
    """Анализ алгоритма 'всегда 1' для разных долей класса 1"""
    n = 1000
    n_pos = int(n * p_positive)
    n_neg = n - n_pos
    
    y_true = np.array([1]*n_pos + [0]*n_neg)
    y_pred = np.ones(n)
    
    precision = precision_score(y_true, y_pred)
    recall = recall_score(y_true, y_pred)
    
    print(f"Доля класса 1: {p_positive*100:.1f}%")
    print(f"  Precision: {precision:.3f}")
    print(f"  Recall: {recall:.3f}")
    print()

# Тестируем
for p in [0.1, 0.3, 0.5, 0.7, 0.9]:
    analyze_always_one(p)

# Output:
# Доля класса 1: 10.0%
#   Precision: 0.100
#   Recall: 1.000
#
# Доля класса 1: 30.0%
#   Precision: 0.300
#   Recall: 1.000
#
# Доля класса 1: 50.0%
#   Precision: 0.500
#   Recall: 1.000
#
# Доля класса 1: 70.0%
#   Precision: 0.700
#   Recall: 1.000
#
# Доля класса 1: 90.0%
#   Precision: 0.900
#   Recall: 1.000

Заключение

Ответ: Precision = доля положительных примеров (класса 1) в датасете.

Этот пример показывает, что:

  1. Precision зависит от дисбаланса класса, не от качества алгоритма
  2. Recall всегда = 1.0 для алгоритма "всегда 1"
  3. F1-score больше отражает реальное качество
  4. Важен контекст: выбирай метрику согласно задаче, а не её значению

Это фундаментальное понимание критично при работе с несбалансированными датасетами и выборе метрик оценки.