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
    1317
  • image_web-applications_feedme_466_0.webp
    Розробка веб-додатків для компанії FEEDME
    1226
  • image_websites_belfingroup_462_0.webp
    Розробка веб-сайту для компанії БЕЛФІНГРУП
    925
  • image_ecommerce_furnoro_435_0.webp
    Розробка інтернет магазину для компанії FURNORO
    1156
  • image_logo-advance_0.webp
    Розробка логотипу компанії B2B Advance
    620
  • image_crm_enviok_479_0.webp
    Розробка веб-додатків для компанії Enviok
    894

Передбачення 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-оптимізації реклами. Звертайтеся за безкоштовною консультацією щодо ваших даних.