Оценка вероятности захода пользователя в приложение — это задача классификации или регрессии?

Ответ

Это задача бинарной классификации, но с важным нюансом: мы часто хотим получить не просто класс (зашел/не зашел), а вероятность принадлежности к классу.

Почему классификация? Целевая переменная — дискретная (бинарная): 1 (пользователь зашел) или 0 (не зашел). Почему важна вероятность? Для бизнеса часто критично ранжировать пользователей по этой вероятности, чтобы, например, показывать таргетированные предложения самым "горячим" из них.

Практический пример из моего опыта (прогноз клика по рекламе):

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.calibration import CalibratedClassifierCV
from sklearn.metrics import roc_auc_score, log_loss

# Допустим, у нас есть лог действий пользователей
# Цель — predict_proba для события 'app_launch'
df['target'] = (df['event'] == 'app_launch').astype(int)
features = df[['session_count', 'time_since_last_visit', 'os', 'campaign_id']]
# ... (кодирование категориальных признаков)

X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, stratify=target)

# Используем алгоритм, который дает хорошо калиброванные вероятности
model = GradientBoostingClassifier(n_estimators=200, learning_rate=0.05)
# Иногда применяю калибровку, особенно для SVM или нейросетей
calibrated_model = CalibratedClassifierCV(model, method='isotonic', cv=5)
calibrated_model.fit(X_train, y_train)

# Получаем вероятности
probabilities = calibrated_model.predict_proba(X_test)[:, 1]

# Оцениваем качество вероятностных предсказаний
print(f"ROC-AUC: {roc_auc_score(y_test, probabilities):.4f}")  # Оценивает ранжирование
print(f"Log Loss: {log_loss(y_test, probabilities):.4f}")      # Оценивает "уверенность" модели

# Бизнес-метрика: доля пользователей в топ-10% по предсказанной вероятности, которые действительно зашли
top_10_idx = probabilities.argsort()[-len(probabilities)//10:]
conversion_in_top_10 = y_test.iloc[top_10_idx].mean()
print(f"Conversion in top-10%: {conversion_in_top_10:.1%}")

Таким образом, мы решаем задачу классификации, но используем метрики и подходы, ориентированные на работу с вероятностями.

Ответ 18+ 🔞

Давай разберём эту штуку, а то тут, бля, классификация, но с подвохом. Ну, классификация — это понятно, ебушки-воробушки, у нас два варианта: либо пользователь зашёл (1), либо нет (0). Всё просто, как три копейки.

Но фишка в чём, ёпта? Часто бизнесу похуй на сам факт, он хочет знать вероятность. Потому что если ты просто скажешь "да, этот чувак зайдёт", а он нихуя не зайдёт — тебе потом объясняй, почему бюджет просран. А если ты дашь вероятность, типа "с вероятностью 87% этот клиент ляжет", то можно уже ранжировать этих самых клиентов. Самых горячих — под самый соус, им самые жирные предложения. А тех, у кого вероятность 5% — ну, нахуй их, не трать время. Это же логично, да?

Вот, к примеру, из моего опыта. Делали прогноз, кликнет ли пользователь по рекламе или нет. И главное — не просто "кликнет/не кликнет", а насколько вероятно, что он это сделает. Чтобы показывать рекламу только тем, кто реально готов в неё тыкнуть, а не всем подряд, распыляя бабки.

Смотри, как код выглядит. Тут всё по-взрослому, с калибровкой и прочей хуйней, чтобы вероятности были адекватные, а не просто цифры с потолка.

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingClassifier
from sklearn.calibration import CalibratedClassifierCV
from sklearn.metrics import roc_auc_score, log_loss

# Допустим, у нас есть лог действий пользователей
# Цель — predict_proba для события 'app_launch'
df['target'] = (df['event'] == 'app_launch').astype(int)
features = df[['session_count', 'time_since_last_visit', 'os', 'campaign_id']]
# ... (кодирование категориальных признаков)

X_train, X_test, y_train, y_test = train_test_split(features, target, test_size=0.2, stratify=target)

# Используем алгоритм, который дает хорошо калиброванные вероятности
model = GradientBoostingClassifier(n_estimators=200, learning_rate=0.05)
# Иногда применяю калибровку, особенно для SVM или нейросетей
calibrated_model = CalibratedClassifierCV(model, method='isotonic', cv=5)
calibrated_model.fit(X_train, y_train)

# Получаем вероятности
probabilities = calibrated_model.predict_proba(X_test)[:, 1]

# Оцениваем качество вероятностных предсказаний
print(f"ROC-AUC: {roc_auc_score(y_test, probabilities):.4f}")  # Оценивает ранжирование
print(f"Log Loss: {log_loss(y_test, probabilities):.4f}")      # Оценивает "уверенность" модели

# Бизнес-метрика: доля пользователей в топ-10% по предсказанной вероятности, которые действительно зашли
top_10_idx = probabilities.argsort()[-len(probabilities)//10:]
conversion_in_top_10 = y_test.iloc[top_10_idx].mean()
print(f"Conversion in top-10%: {conversion_in_top_10:.1%}")

Видишь, в чём прикол? Мы формально решаем задачу классификации, но смотрим на неё через призму вероятностей. ROC-AUC показывает, насколько хорошо модель отделяет зашедших от незашедших, а Log Loss — насколько она в своих предсказаниях уверена. Если модель тупо всем ставит вероятность 0.5, то Log Loss будет овердохуища, и всем станет ясно, что модель — пиздопроебибна.

И самое главное — бизнес-метрика в конце. Мы берём топ-10% пользователей, которым модель понаставила самых высоких вероятностей, и смотрим, какой процент из них реально зашёл. Если, например, из этой отборной десятки зашло 80%, а в среднем по больнице — 2%, то всё, бля, модель работает, можно нести её заказчику и говорить: "Вот, сука, инструмент готов, давайте бабки". А если в топе конверсия 3%, то это просто хуй с горы, и модель можно смело выкидывать в окно.

Вот и вся философия. Классификация — это просто форма, а суть — в вероятностях и в том, как ты их используешь.