← Назад к вопросам

Как определить влияют ли офлайн-метрики на онлайн-метрики?

3.0 Senior🔥 151 комментариев
#Метрики и оценка моделей#Статистика и A/B тестирование

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI29 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Определение влияния офлайн-метрик на онлайн-метрики — один из ключевых вызовов в Machine Learning. Офлайн-метрики (например, точность модели) часто не коррелируют с тем, что пользователи на самом деле ценят. Рассмотрим проверенные методы.

Проблема: офлайн vs онлайн метрики

Офлайн-метрики:

  • RMSE, MAE для регрессии
  • Accuracy, Precision, Recall, F1 для классификации
  • NDCG, MAP для ранжирования
  • Вычисляются на фиксированном датасете

Онлайн-метрики:

  • CTR (click-through rate)
  • Конверсия
  • Time on page
  • Revenue per user
  • User retention
  • Вычисляются на живых пользователях

1. Корреляционный анализ

Наиболее простой и популярный метод:

import pandas as pd
import numpy as np
from scipy import stats
import matplotlib.pyplot as plt

# Предположим, у вас есть данные A/B тестов
results = pd.DataFrame({
    "offline_metric": [0.85, 0.87, 0.88, 0.82, 0.90, 0.86, 0.89, 0.83],
    "online_metric_ctr": [0.042, 0.048, 0.051, 0.038, 0.055, 0.045, 0.052, 0.040],
    "online_metric_revenue": [1.2, 1.35, 1.42, 1.1, 1.58, 1.28, 1.48, 1.15]
})

# Корреляция Пирсона
corr_ctr = results["offline_metric"].corr(results["online_metric_ctr"])
corr_revenue = results["offline_metric"].corr(results["online_metric_revenue"])

print(f"Корреляция с CTR: {corr_ctr:.4f}")
print(f"Корреляция с Revenue: {corr_revenue:.4f}")

# Проверка статистической значимости
spearman_corr, p_value = stats.spearmanr(results["offline_metric"], results["online_metric_ctr"])
print(f"Spearman корреляция: {spearman_corr:.4f}, p-value: {p_value:.4f}")

if p_value < 0.05:
    print("Корреляция статистически значима на уровне 5%")
else:
    print("Нет статистической значимости")

# Визуализация
plt.scatter(results["offline_metric"], results["online_metric_ctr"])
plt.xlabel("Офлайн метрика (например, точность)")
plt.ylabel("CTR (онлайн метрика)")
plt.title(f"Корреляция = {corr_ctr:.4f}")
plt.show()

2. A/B тестирование

Золотой стандарт для определения причинно-следственной связи:

from scipy import stats

# Результаты A/B теста
control_group = {
    "offline_auc": 0.82,
    "online_ctr": 0.040,
    "conversion_rate": 0.05,
    "users": 10000
}

treatment_group = {
    "offline_auc": 0.88,
    "online_ctr": 0.048,
    "conversion_rate": 0.058,
    "users": 10000
}

# Chi-square test для бинарной метрики (конверсия)
control_conversions = control_group["conversion_rate"] * control_group["users"]
treatment_conversions = treatment_group["conversion_rate"] * treatment_group["users"]

control_non_conversions = control_group["users"] - control_conversions
treatment_non_conversions = treatment_group["users"] - treatment_conversions

contingency_table = [
    [int(control_conversions), int(control_non_conversions)],
    [int(treatment_conversions), int(treatment_non_conversions)]
]

chi2, p_value, dof, expected = stats.chi2_contingency(contingency_table)
print(f"Chi-square test p-value: {p_value:.4f}")

if p_value < 0.05:
    print("Разница статистически значима!")
else:
    print("Нет статистической значимости")

# Размер эффекта (Cohen's h)
from math import asin, sqrt
cohen_h = 2 * (asin(sqrt(treatment_group["conversion_rate"])) - 
                asin(sqrt(control_group["conversion_rate"])))
print(f"Cohen's h (размер эффекта): {cohen_h:.4f}")

3. Регрессионный анализ

Для контроля за конфаундерами (переменными, влияющими на обе метрики):

from sklearn.linear_model import LinearRegression
import statsmodels.api as sm

# Подготовка данных (из разных экспериментов)
X = results[[
    "offline_metric",
    "model_version",
    "user_segment",
    "time_of_day"
]]

y = results["online_metric_ctr"]

# Добавляем константу
X = sm.add_constant(X)

# Логистическая регрессия
model = sm.OLS(y, X).fit()
print(model.summary())

# Коэффициент при offline_metric показывает влияние
offline_coef = model.params["offline_metric"]
offline_pval = model.pvalues["offline_metric"]

print(f"\nВлияние офлайн-метрики: {offline_coef:.4f}")
print(f"P-value: {offline_pval:.4f}")

if offline_pval < 0.05:
    print("Офлайн-метрика статистически влияет на онлайн-метрику")

4. Анализ временных рядов

Для отслеживания влияния во времени:

import pandas as pd

# Данные за каждый день последние 30 дней
daily_data = pd.DataFrame({
    "date": pd.date_range("2026-02-27", periods=30),
    "offline_metric": np.random.uniform(0.80, 0.92, 30),
    "online_metric": np.random.uniform(0.035, 0.055, 30)
})

# Скользящая корреляция (7 дней)
daily_data["rolling_corr"] = daily_data["offline_metric"].rolling(7).corr(
    daily_data["online_metric"]
)

print(daily_data[["date", "rolling_corr"]].tail(10))

# График
plt.figure(figsize=(12, 4))
plt.plot(daily_data["date"], daily_data["rolling_corr"], marker="o")
plt.axhline(y=0, color="r", linestyle="--", alpha=0.5)
plt.xlabel("Дата")
plt.ylabel("7-дневная скользящая корреляция")
plt.title("Эволюция влияния офлайн-метрики")
plt.grid(True, alpha=0.3)
plt.show()

5. Причинный вывод (Causal Inference)

Для более сложных причинно-следственных связей:

from causalml.inference.tree_based import CausalTreeRegressor
from causalml.inference.meta import BaseTRegressor

# Определяем лечение: использование новой модели (1) vs старой (0)
X = results[[
    "user_segment",
    "time_of_day",
    "device_type"
]]

treatment = (results["offline_metric"] > 0.85).astype(int)
y = results["online_metric_ctr"]

# Оцениваем средний эффект лечения (ATE)
from causalml.inference.meta import XLearner

learner = XLearner()
learner.fit(X, treatment, y)

# Условный средний эффект лечения (CATE) для каждого примера
treatment_effect = learner.predict(X)
print(f"Средний эффект: {treatment_effect.mean():.4f}")
print(f"Доверительный интервал: [{treatment_effect.mean() - 2*treatment_effect.std():.4f}, "
      f"{treatment_effect.mean() + 2*treatment_effect.std():.4f}]")

6. Метрики согласованности (Consistency)

Рейнговая корреляция

Не требует линейности:

from scipy.stats import spearmanr, kendalltau

# Тест Спирмена (более робустен к выбросам)
spearman, p_spearman = spearmanr(results["offline_metric"], results["online_metric_ctr"])
print(f"Spearman rho: {spearman:.4f}, p-value: {p_spearman:.4f}")

# Тест Кендалла Тау (для малых выборок)
kendall, p_kendall = kendalltau(results["offline_metric"], results["online_metric_ctr"])
print(f"Kendall tau: {kendall:.4f}, p-value: {p_kendall:.4f}")

# Если оба теста дают положительный результат — связь устойчива
if p_spearman < 0.05 and p_kendall < 0.05:
    print("Связь между метриками статистически значима")

Практическая стратегия

  1. Начните с корреляционного анализа — быстро и просто
  2. Проведите A/B тест — золотой стандарт
  3. Анализируйте временные ряды — отслеживайте изменения
  4. Используйте причинный вывод — для сложных случаев
  5. Валидируйте в разных сегментах — разные юзеры ведут себя по-разному

Красные флаги

  • Высокая офлайн-метрика, но низкая онлайн-метрика — проблема с моделью
  • Высокая корреляция на исторических данных, но отсутствие в A/B тесте — confounding
  • Разные результаты для разных сегментов — нужна сегментированная оптимизация

Цель — убедиться, что оптимизация офлайн-метрики действительно улучшает бизнес-метрики, которые интересуют компанию.

Как определить влияют ли офлайн-метрики на онлайн-метрики? | PrepBro