Что такое data drift и concept drift?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Что такое data drift и concept drift?
Data drift и concept drift — это два критических явления в machine learning, которые приводят к деградации качества моделей в production. Несмотря на похожесть названий, это разные проблемы с разными причинами и решениями.
Data Drift (дрейф данных)
Data drift — это изменение распределения признаков (features) входных данных со временем, при этом зависимость между признаками и целевой переменной остаётся прежней.
Другими словами: P(X) изменяется, но P(Y|X) остаётся неизменным.
Примеры data drift
-
Модель для прогноза цен на недвижимость
- Обучена на данных 2020 года, когда средняя цена = $300k
- В 2024 году средняя цена = $500k
- Распределение признаков (размер дома, местоположение) изменилось
- Но связь "большой дом -> дорогой дом" всё ещё верна
-
Модель для детектирования спама
- Распределение слов в спаме изменилось (новые spam techniques)
- Но принцип остаётся: определённые паттерны = спам
import numpy as np
from scipy import stats
# Симуляция data drift
np.random.seed(42)
# Обучающие данные (2020)
X_train = np.random.normal(loc=100, scale=15, size=1000)
# Production данные (2024) - сместился центр распределения
X_prod = np.random.normal(loc=130, scale=15, size=1000)
# Тест Колмогорова-Смирнова для обнаружения дрейфа
statistic, p_value = stats.ks_2samp(X_train, X_prod)
print(f'KS statistic: {statistic:.4f}, p-value: {p_value:.4f}')
if p_value < 0.05:
print("Data drift обнаружен!")
else:
print("Дрейфа не обнаружено")
Обнаружение data drift
from scipy.stats import ks_2samp, anderson_ksamp
import pandas as pd
def detect_data_drift(X_train, X_prod, threshold=0.05):
"""
Обнаруживает data drift используя KS тест
"""
drifted_features = []
for feature in X_train.columns:
statistic, p_value = ks_2samp(X_train[feature], X_prod[feature])
if p_value < threshold:
drifted_features.append({
'feature': feature,
'ks_statistic': statistic,
'p_value': p_value,
'train_mean': X_train[feature].mean(),
'prod_mean': X_prod[feature].mean(),
'train_std': X_train[feature].std(),
'prod_std': X_prod[feature].std()
})
return pd.DataFrame(drifted_features)
# Использование
X_train = pd.DataFrame({'age': np.random.normal(40, 10, 1000),
'income': np.random.normal(50000, 15000, 1000)})
X_prod = pd.DataFrame({'age': np.random.normal(42, 10, 1000),
'income': np.random.normal(55000, 15000, 1000)})
result = detect_data_drift(X_train, X_prod)
print(result)
Решение для data drift
- Retraining: переобучение модели на свежих данных
- Continuous monitoring: постоянный мониторинг метрик качества
- Domain adaptation: использование techniques для адаптации к новому распределению
- Feature engineering: создание более стабильных признаков
Concept Drift (дрейф концепций)
Concept drift — это изменение целевого функционала (взаимосвязь между входными данными и целевой переменной) со временем.
Другими словами: P(X) может оставаться прежним, но P(Y|X) изменяется.
Примеры concept drift
-
Система для предсказания спама
- Раньше: письма со словом "VIAGRA" = 90% спам
- Теперь: письма со словом "VIAGRA" = 30% спам (из-за новых spam techniques)
- Распределение слов не изменилось, но их значение изменилось
-
Модель для предсказания кредитного риска
- До коронавируса: высокие доходы -> низкий риск
- Во время коронавируса: экономический паттерн изменился
- Зависимость Y|X изменилась
import matplotlib.pyplot as plt
# Симуляция concept drift
np.random.seed(42)
# Период 1: классный паттерн (X -> Y линейная зависимость)
X_period1 = np.linspace(0, 10, 100)
Y_period1 = 2 * X_period1 + np.random.normal(0, 2, 100) # Y = 2*X
# Период 2: паттерн изменился (новая зависимость)
X_period2 = np.linspace(0, 10, 100)
Y_period2 = -1 * X_period2 + 15 + np.random.normal(0, 2, 100) # Y = -X + 15
# Визуализация
plt.figure(figsize=(12, 5))
plt.subplot(1, 2, 1)
plt.scatter(X_period1, Y_period1, alpha=0.5, label='Period 1: Y=2X')
plt.plot(X_period1, 2*X_period1, 'r-', linewidth=2)
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Обучающие данные (Period 1)')
plt.legend()
plt.subplot(1, 2, 2)
plt.scatter(X_period2, Y_period2, alpha=0.5, label='Period 2: Y=-X+15')
plt.plot(X_period2, -1*X_period2 + 15, 'r-', linewidth=2)
plt.xlabel('X')
plt.ylabel('Y')
plt.title('Production данные (Period 2) - Concept Drift!')
plt.legend()
plt.tight_layout()
plt.show()
Обнаружение concept drift
from sklearn.metrics import accuracy_score
import pandas as pd
def detect_concept_drift(y_true, y_pred, window_size=100):
"""
Обнаруживает concept drift через скользящее окно точности
"""
accuracies = []
windows = []
for i in range(0, len(y_true) - window_size, window_size // 2):
window_accuracy = accuracy_score(
y_true[i:i+window_size],
y_pred[i:i+window_size]
)
accuracies.append(window_accuracy)
windows.append(i)
# Обнаруживаем статистически значимое падение точности
baseline_accuracy = np.mean(accuracies[:3]) # среднее по первым окнам
drift_threshold = baseline_accuracy - 0.05 # 5% падение
drift_detected = any(acc < drift_threshold for acc in accuracies[3:])
return drift_detected, accuracies, windows
# Использование
accuracy_over_time = [0.92, 0.91, 0.90, 0.88, 0.85, 0.80, 0.78] # точность упала
trend = np.polyfit(range(len(accuracy_over_time)), accuracy_over_time, 1)
if trend[0] < -0.01: # отрицательный тренд
print("Concept drift обнаружен! Точность модели падает.")
Сравнение Data Drift и Concept Drift
| Аспект | Data Drift | Concept Drift |
|---|---|---|
| Что изменяется | P(X) - распределение признаков | P(Y|X) - зависимость X->Y |
| Связь признаков и целевой переменной | Сохраняется | Изменяется |
| Пример | Средняя цена недвижимости выросла | Требование к кредитоспособности изменилось |
| Обнаружение | Статистические тесты (KS, Wasserstein) | Мониторинг метрик качества (accuracy, AUC) |
| Решение | Retraining на свежих данных | Переобучение + пересмотр признаков |
| Влияние на модель | Может быть коварным | Явное падение качества |
Интегрированный мониторинг
import pandas as pd
from scipy.stats import ks_2samp
from sklearn.metrics import accuracy_score
class DriftMonitor:
def __init__(self, X_train, y_train, model, window_size=100):
self.X_train = X_train
self.y_train = y_train
self.model = model
self.window_size = window_size
self.baseline_accuracy = model.score(X_train, y_train)
def check_drifts(self, X_new, y_new):
"""
Проверяет оба типа дрейфа
"""
# Data drift
data_drift_detected = False
for col in self.X_train.columns:
stat, p_val = ks_2samp(self.X_train[col], X_new[col])
if p_val < 0.05:
data_drift_detected = True
print(f"Data drift в колонке '{col}'")
# Concept drift
y_pred = self.model.predict(X_new)
new_accuracy = accuracy_score(y_new, y_pred)
if new_accuracy < self.baseline_accuracy - 0.05:
print(f"Concept drift обнаружен!")
print(f"Baseline accuracy: {self.baseline_accuracy:.3f}")
print(f"Current accuracy: {new_accuracy:.3f}")
return True
return data_drift_detected
Практические рекомендации
- Регулярный мониторинг: проверяй качество модели в production постоянно
- Pipeline для переобучения: автоматизируй процесс retraining
- Версионирование моделей: храни историю изменений моделей
- A/B тестирование: при обновлении модели проверяй на подмножестве пользователей
- Feature monitoring: отслеживай изменения в распределении признаков
Вывод: data drift и concept drift — это неизбежные явления в production ML systems. Важно иметь системы мониторинга и быть готовым к быстрому переобучению моделей.