חיזוי CTR/CVR מונחה בינה מלאכותית לקמפיינים פרסומיים

אתם משיקים קמפיינים פרסומיים, אך תחזיות קליקים והמרות לא מדויקות מובילות לחריגות תקציב ולאובדן עמדות במכרזים. אנחנו בונים מערכות AI לחיזוי CTR ו-CVR שמנתחות נתוני קהל ונתונים היסטוריים כדי לבצע אופטימיזציה של הצעות מחיר בזמן אמת. הצוות שלנו מספק את הפרויקט במפתח מלא—מהמודל ועד לכיול הסתברויות—ומבטיח פעילות אמינה ותמיכה מתמשכת.

תחומי פיתוח AI

שאלות נפוצות

העבודות האחרונות

  • פיתוח אפליקציית ווב עבור FEEDME
    פיתוח אפליקציית ווב עבור FEEDME
    1365
  • פיתוח חנות מקוונת לחברת FURNORO
    פיתוח חנות מקוונת לחברת FURNORO
    1330
  • עיצוב לוגו לחברת B2B Advance
    עיצוב לוגו לחברת B2B Advance
    776
  • פיתוח אפליקציית ווב עבור Enviok
    פיתוח אפליקציית ווב עבור Enviok
    1077
  • פיתוח לוגו חברת AIDER
    פיתוח לוגו חברת AIDER
    1022
  • פיתוח CRM עבור Chasseurs
    פיתוח CRM עבור Chasseurs
    1113

חיזוי CTR/CVR מבוסס בינה מלאכותית לקמפיינים פרסומיים

אתם משיקים קמפיין פרסומי עם מיליון חשיפות ביום. חיזוי CTR מוערך בחסר ב-15% — אתם מפסידים עמדות מכירה פומבית מובילות. מוערך ביתר ב-20% — אתם מבזבזים תקציב על קליקים לא רלוונטיים. אנו פותרים זאת עם מודלי ML מותאמים אישית מקצה לקצה. מערכת הבינה המלאכותית שלנו לחיזוי CTR/CVR מנתחת קהל, הקשר ונתונים היסטוריים כדי לבצע אופטימיזציה של הצעות מחיר בזמן אמת. שגיאה של 20% בחיזוי CTR יכולה לעלות 15-25% מתקציב הפרסום — כסף שאבד על חשיפות לא אפקטיביות.

CTR ו-CVR הם אותות יסודיים לתמחור בפרסום תוכנתי. שגיאה של 20% בחיזוי CTR מתורגמת ישירות לתשלום יתר או להפסד במכירות פומביות. בקנה מידה של מאות מיליוני חשיפות יומיות, אפילו שיפור AUC מ-0.76 ל-0.78 משמעותו מיליונים שנחסכים או נצברו. לפי הנתונים שלנו, LightGBM עם כיול עולה על רגרסיה לוגיסטית ב-0.03-0.05 AUC — השוואה ישירה של יעילות.

כיצד אנו בונים מודלי CTR מקצה לקצה

חיזוי CTR הוא סיווג בינארי עם שלושה אתגרים מרכזיים: חוסר איזון קיצוני בין מחלקות (CTR 0.1-2%), נפח עצום (מיליארדי דוגמאות יומיות), והמרות נסתרות (CVR נצפה רק עבור קליקים, מה שיוצר הטיית בחירה). אנו משתמשים ב-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), ושגיאת כיול (<0.005). בסביבת ייצור, יש לבדוק גם ΔAUC מתכונות חדשות — עלייה של >0.001 מצדיקה מאמץ הנדסי. LightGBM מכויל מניב Log Loss נמוך פי 1.3 מהסתברויות גולמיות.

מדוע כיול הסתברויות הוא קריטי?

מודל לא מכויל יכול לשלם יתר באופן שיטתי במכירות פומביות. LightGBM גולמי נותן דירוגים מצוינים אך הסתברויות חלשות. אנו משתמשים ברגרסיה איזוטונית, שמפחיתה את שגיאת הכיול ל-<0.005. זה קריטי לחישוב מחיר הצעה: אם המודל חוזה CTR של 0.5% אך בפועל הוא 0.8%, אתם משלמים יתר על כל קליק. כיול מדויק חוסך תקציב ישירות — החיסכון מהפעלת מודל LightGBM מכויל יכול להגיע עד 30% מהוצאות הפרסום.

עדכוני מודל שבועיים

הנוף הפרסומי משתנה במהירות: קריאייטיבים חדשים, עונתיות, שינויים בהתנהגות קהל. אנו ממליצים על אימון מחדש שבועי. לשם כך, אנו מקימים צינור אימון מחדש אוטומטי עם ניטור סחיפת תכונות. בתקופות תנודתיות גבוהה (למשל, Black Friday), ייתכן שיידרשו עדכונים יומיים, אך בדרך כלל זה מוגזם ומכניס רעש.

המרות מושהות: בעיה ופתרון

במודלי CVR, המרות יכולות להתרחש שעות או ימים לאחר קליק. אם פשוט חותכים את קבוצת האימון לפי זמן, תצפיות אחרונות יקבלו הערכת CVR נמוכה מדי. אנו משתמשים בתיקון על ידי השלכת קליקים עם חלון המרה שלא פג (בדרך כלל 24-72 שעות בהתאם להתפלגות העיכוב). זה משפר את כיול CVR ב-10-20%.

התפלגות עיכוב המרה אופיינית למסחר אלקטרוני
אחוזון עיכוב (שעות)
p50 2.5
p90 18.0
p99 72.0
חלון מומלץ 95 שעות

מדדי איכות למודל CTR/CVR

מדד ערך טוב מטרה
AUC-ROC > 0.75 עבור CTR יכולת דירוג
Log Loss < 0.10 איכות הסתברויות
שגיאת כיול < 0.005 דיוק הערכות CTR
NDCG@1000 > 0.85 מכירות פומביות מובילות
Delta AUC מתכונה חדשה > 0.001 החזר הנדסי

עבור מודלי CTR, AUC 0.76 לעומת 0.74 הוא הבדל משמעותי בקנה מידה. כיול הוא חובה: מודל לא מכויל יכול לשלם יתר באופן שיטתי.

תהליך יישום חיזוי CTR/CVR מבוסס בינה מלאכותית

אנו עובדים בשלבים:

  1. ביקורת נתונים — איסוף לוגי חשיפות, בדיקת איכות ושלמות. הערכת פוטנציאל שיפור ML.
  2. הנדסת תכונות — בניית תכונות: CTR מחליק, סטטיסטיקות אתר, דפוסי זמן. שימוש בהחלקת Wilson לטיפול בדלילות.
  3. אימון וכיול — LightGBM + כיול איזוטוני. אימות על קבוצת בדיקה מופרדת.
  4. בדיקות A/B — השוואה עם קו בסיס על הכנסות בסביבת ייצור.
  5. תיעוד ופריסה — ייצוא המודל ל-ONNX או Triton, הקמת ניטור סחיפה.

מה כלול בפיתוח מודל

תוצרים:

  • דוח ביקורת נתונים עם הערכת פוטנציאל שיפור
  • חבילת Python עם צינור חיזוי
  • תיעוד API עבור מערכת הצעות המחיר
  • הכשרה לצוות הלקוח
  • תמיכה ל-3 חודשים לאחר הפריסה

טעויות אופייניות ב-CTR/CVR MVP

  • התעלמות מהמרות מושהות — CVR מוערך בחסר ב-10-20%.
  • חוסר אימות: שימוש ב-cross-validation יחיד במקום בשלושה holdouts מבוססי זמן.
  • עדכונים תכופים מדי (יומיים) — רעש מתנודות אקראיות.
  • שימוש במודלים ליניאריים בלבד — הם מפספסים אינטראקציות לא ליניאריות.

הזמינו ביקורת נתונים על נתוני הפרסום שלכם — נקבע את פוטנציאל שיפור ה-CTR. קבלו ייעוץ: נעריך את הנתונים שלכם ונספר לכם איזה שיפור CTR אפשרי. הניסיון שלנו: למעלה מ-20 פרויקטים לפלטפורמות תוכנתיות, 5+ שנים באופטימיזציית ML לפרסום. צרו קשר לייעוץ על הנתונים שלכם.