Какой будет precision для алгоритма, который всегда прогнозирует 1?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
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 очень низкая, потому что класс редкий.
Практический совет
Этот пример демонстрирует важное правило:
Никогда не выбирай метрику на основе её значения, выбирай на основе задачи:
- Fraud detection: Важен Recall (не пропустить обман), Precision вторичен
- Spam detection: Важна Precision (не отправить спам), Recall менее критичен
- Medical diagnosis: Важен Recall (не пропустить болезнь), Precision может быть ниже
- Общий случай: Используй 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) в датасете.
Этот пример показывает, что:
- Precision зависит от дисбаланса класса, не от качества алгоритма
- Recall всегда = 1.0 для алгоритма "всегда 1"
- F1-score больше отражает реальное качество
- Важен контекст: выбирай метрику согласно задаче, а не её значению
Это фундаментальное понимание критично при работе с несбалансированными датасетами и выборе метрик оценки.