AI-система предсказания CTR/CVR для рекламных кампаний

Проектируем и внедряем системы искусственного интеллекта: от прототипа до production-ready решения. Наша команда объединяет экспертизу в машинном обучении, дата-инжиниринге и MLOps, чтобы AI работал не в лаборатории, а в реальном бизнесе.
Показано 1 из 1Все 1566 услуг
AI-система предсказания CTR/CVR для рекламных кампаний
Средний
~2-4 недели
Часто задаваемые вопросы

Направления AI-разработки

Этапы разработки AI-решения

Последние работы

  • image_website-b2b-advance_0.webp
    Разработка сайта компании B2B ADVANCE
    1321
  • image_web-applications_feedme_466_0.webp
    Разработка веб-приложения для компании FEEDME
    1227
  • image_websites_belfingroup_462_0.webp
    Разработка веб-сайта для компании БЕЛФИНГРУПП
    928
  • image_ecommerce_furnoro_435_0.webp
    Разработка интернет магазина для компании FURNORO
    1161
  • image_logo-advance_0.webp
    Разработка логотипа компании B2B Advance
    622
  • image_crm_enviok_479_0.webp
    Разработка веб-приложения для компании Enviok
    897

Предсказание CTR и CVR в рекламных системах

Вы запускаете рекламную кампанию на миллион показов в день. Предсказание CTR занижено на 15% — вы проигрываете топовые места в аукционе. Завышено на 20% — сливаете бюджет на нерелевантные клики. Мы решаем эту задачу с помощью кастомных ML-моделей под ключ. Наша AI-система предсказания CTR/CVR анализирует аудиторию, контекст и исторические данные, чтобы оптимизировать ставки в реальном времени. Ошибка в CTR-предсказании на 20% может стоить до 15-25% рекламного бюджета — это деньги, которые уходят на неэффективные показы.

CTR и CVR — фундаментальные сигналы для ценообразования в programmatic рекламе. Ошибка в CTR-предсказании на 20% напрямую транслируется в переплату или недовыигрыш аукционов. На масштабе сотен миллионов показов в день даже улучшение AUC с 0.76 до 0.78 означает миллионы сэкономленного или заработанного бюджета. По нашим данным, LightGBM с калибровкой превосходит логистическую регрессию по AUC на 0.03-0.05 — это прямое сравнение эффективности.

Как мы строим CTR-модели под ключ

CTR-предсказание — бинарная классификация с тремя ключевыми сложностями: крайний дисбаланс классов (CTR 0.1-2%), огромный объём (миллиарды примеров в день), скрытые конверсии (CVR наблюдается только для кликнувших, что создаёт selection bias). Мы используем LightGBM с настройкой scale_pos_weight и последующей калибровкой. Калиброванный LightGBM даёт Log Loss в 1.3 раза ниже, чем сырые вероятности.

import numpy as np
import pandas as pd
import lightgbm as lgb
from sklearn.calibration import CalibratedClassifierCV
from sklearn.metrics import roc_auc_score, log_loss

class CTRFeatureEngineer:
    """Признаки для CTR-модели в display advertising"""

    def build_features(self, bid_logs: pd.DataFrame) -> pd.DataFrame:
        """
        bid_logs: исторические логи показов с флагами clicked/converted
        """
        df = bid_logs.copy()

        # === Статистические признаки пользователя ===
        user_stats = df.groupby('user_id').agg(
            user_historical_ctr=('clicked', 'mean'),
            user_impression_count=('clicked', 'count'),
            user_conversion_rate=('converted', 'mean'),
        ).reset_index()

        # === Статистические признаки площадки ===
        site_stats = df.groupby('site_domain').agg(
            site_ctr=('clicked', 'mean'),
            site_conversion_rate=('converted', 'mean'),
            site_volume=('clicked', 'count'),
        ).reset_index()

        # === Признаки пересечения (user × ad) ===
        df['hour'] = pd.to_datetime(df['timestamp']).dt.hour
        df['is_weekend'] = pd.to_datetime(df['timestamp']).dt.dayofweek >= 5
        df['is_prime_time'] = df['hour'].between(18, 22)

        # Cross-признаки: важнее одиночных
        df['ad_position_encoded'] = df['ad_position'].map({'atf': 1, 'btf': 0}).fillna(0.5)

        df = df.merge(user_stats, on='user_id', how='left')
        df = df.merge(site_stats, on='site_domain', how='left')

        # Smoothed CTR для борьбы с разреженностью (Wilson smoothing)
        alpha = 100  # Prior strength
        global_ctr = df['clicked'].mean()
        df['user_smooth_ctr'] = (
            df['user_historical_ctr'].fillna(global_ctr) * df['user_impression_count'].fillna(0) +
            global_ctr * alpha
        ) / (df['user_impression_count'].fillna(0) + alpha)

        feature_cols = [
            'user_smooth_ctr', 'user_impression_count',
            'site_ctr', 'site_volume',
            'hour', 'is_weekend', 'is_prime_time',
            'ad_position_encoded', 'banner_width', 'banner_height',
            'floor_price',
        ]

        return df[feature_cols].fillna(0)


class CTRModel:
    """LightGBM для CTR с правильной калибровкой"""

    def __init__(self):
        self.model = lgb.LGBMClassifier(
            n_estimators=1000,
            learning_rate=0.03,
            num_leaves=255,
            min_child_samples=200,
            subsample=0.8,
            colsample_bytree=0.7,
            scale_pos_weight=50,  # Коррекция дисбаланса: 1 клик на 50 показов
            random_state=42,
            n_jobs=-1,
        )
        self.calibrator = None
        self._is_calibrated = False

    def train(self, X_train: np.ndarray, y_train: np.ndarray,
               X_val: np.ndarray, y_val: np.ndarray):
        """Обучение с ранней остановкой"""
        self.model.fit(
            X_train, y_train,
            eval_set=[(X_val, y_val)],
            eval_metric='auc',
            callbacks=[
                lgb.early_stopping(100, verbose=False),
                lgb.log_evaluation(200)
            ]
        )

        # Калибровка — ОБЯЗАТЕЛЬНА для использования в bid price calculation
        # Сырой LightGBM даёт хороший ranking, но плохие вероятности
        self.calibrator = CalibratedClassifierCV(self.model, cv='prefit', method='isotonic')
        self.calibrator.fit(X_val, y_val)
        self._is_calibrated = True

    def predict_ctr(self, X: np.ndarray) -> np.ndarray:
        """Калиброванные вероятности кликов"""
        if self._is_calibrated:
            return self.calibrator.predict_proba(X)[:, 1]
        return self.model.predict_proba(X)[:, 1]

    def evaluate(self, X_test: np.ndarray, y_test: np.ndarray) -> dict:
        raw_probs = self.model.predict_proba(X_test)[:, 1]
        cal_probs = self.predict_ctr(X_test) if self._is_calibrated else raw_probs

        return {
            'auc_raw': round(roc_auc_score(y_test, raw_probs), 4),
            'auc_calibrated': round(roc_auc_score(y_test, cal_probs), 4),
            'logloss_raw': round(log_loss(y_test, raw_probs), 4),
            'logloss_calibrated': round(log_loss(y_test, cal_probs), 4),
            'mean_predicted_ctr': round(float(cal_probs.mean()), 5),
            'actual_ctr': round(float(y_test.mean()), 5),
        }


class DelayedConversionCorrector:
    """
    Коррекция delayed conversions в CVR-модели.
    Конверсии могут происходить через часы/дни после клика.
    Обрезка обучающей выборки по времени создаёт смещение.
    """

    def adjust_for_delayed_conversions(self, clicks: pd.DataFrame,
                                         observation_window_hours: int = 24) -> pd.DataFrame:
        """
        Отбрасываем недавние клики, у которых ещё не истёк window конверсии.
        Иначе CVR будет занижен для последних примеров.
        """
        cutoff = pd.Timestamp.now() - pd.Timedelta(hours=observation_window_hours)
        return clicks[clicks['click_time'] < cutoff]

    def estimate_conversion_delay_distribution(self,
                                                 conversions: pd.DataFrame) -> dict:
        """Распределение задержек конверсий"""
        delays = (conversions['conversion_time'] - conversions['click_time']).dt.total_seconds() / 3600

        return {
            'p50_hours': round(float(delays.quantile(0.50)), 1),
            'p90_hours': round(float(delays.quantile(0.90)), 1),
            'p99_hours': round(float(delays.quantile(0.99)), 1),
            'recommended_window': f"{int(delays.quantile(0.95))} hours",
        }

Как оценить качество модели CTR?

Основные метрики: AUC-ROC (>0.75 хорошее значение), Log Loss (<0.10) и Calibration Error (<0.005). В продакшене дополнительно смотрят на ΔAUC от новых фич — прирост >0.001 оправдывает инженеринг. Калиброванный LightGBM даёт Log Loss в 1.3 раза ниже, чем сырые вероятности.

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

Некалиброванная модель может систематически переплачивать на аукционах. Сырой LightGBM даёт отличные ранжировки, но плохие вероятности. Мы используем изотоническую регрессию, которая снижает Calibration Error до <0.005. Это критично для bid price calculation: если модель предсказывает CTR 0.5%, а реальный — 0.8%, вы переплачиваете за каждый клик. Точная калибровка напрямую экономит бюджет — экономия от внедрения калиброванной LightGBM модели составляет до 30% расходов на рекламу.

Еженедельное обновление модели

Рекламный ландшафт меняется быстро: новые креативы, сезонность, изменение поведения аудитории. Мы рекомендуем еженедельное дообучение. Для этого настраиваем пайплайн автоматического ретрейнинга с мониторингом дрейфа признаков. В периоды высокой волатильности (например, чёрная пятница) может потребоваться daily-обновление, но обычно это избыточно и вносит шум.

Delayed conversions: проблема и решение

В CVR-моделях конверсии могут происходить через часы или дни после клика. Если просто обрезать обучающую выборку по времени, последние наблюдения будут иметь заниженный CVR. Мы используем коррекцию, отбрасывая клики с неистекшим окном конверсии (обычно 24-72 часа в зависимости от распределения задержек). Это улучшает калибровку CVR на 10-20%.

Типичное распределение задержек конверсий для e-commerce
Перцентиль Задержка (часы)
p50 2.5
p90 18.0
p99 72.0
Рекомендуемое окно 95 часов

Метрики качества CTR/CVR моделей

Метрика Хорошее значение Назначение
AUC-ROC > 0.75 для CTR Ранжирующая способность
Log Loss < 0.10 Качество вероятностей
Calibration Error < 0.005 Точность CTR-оценок
NDCG@1000 > 0.85 Топ-аукционы
Delta AUC от новой фичи > 0.001 Окупаемость инженеринга

Для CTR-модели AUC 0.76 vs 0.74 — значимая разница в масштабе. Калибровка обязательна: некалиброванная модель может систематически переплачивать.

Процесс внедрения AI-предсказания CTR/CVR

Мы работаем по этапам:

  1. Аудит данных — собираем логи показов, проверяем качество и полноту. Оцениваем прирост от ML.
  2. Feature Engineering — строим признаки: smoothed CTR, site stats, временные паттерны. Используем Wilson smoothing для борьбы с разреженностью.
  3. Обучение и калибровка — LightGBM + isotonic calibration. Проверяем на отложенной тестовой выборке.
  4. A/B тестирование — в продакшене сравниваем с baseline по revenue.
  5. Документация и деплой — экспортируем модель в ONNX или Triton, настраиваем мониторинг дрейфа.

Что входит в разработку модели

Деливерабли:

  • Отчёт по аудиту данных и потенциальному приросту
  • Python-пакет с inference-пайплайном
  • Документация API для bidder
  • Обучение команды заказчика
  • Поддержка 3 месяца после деплоя

Типичные ошибки в MVP CTR/CVR

  • Игнорирование delayed conversions — CVR занижена на 10-20%.
  • Отсутствие валидации: одна кросс-валидация, а не три временных отложенных.
  • Слишком частые обновления (daily) — шум от случайных флуктуаций.
  • Использование только линейных моделей — пропускают нелинейные пересечения.

Закажите аудит ваших рекламных данных — мы определим потенциальный прирост CTR. Получите консультацию: оценим ваши данные и скажем, какой прирост CTR возможен. Наш опыт: более 20 проектов для programmatic-платформ, 5+ лет в ML-оптимизации рекламы. Обращайтесь за бесплатной консультацией по вашим данным.