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

Сколько автообучались модели на твоём проекте?

1.0 Junior🔥 202 комментариев
#Опыт и проекты#Машинное обучение

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

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

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

Автоматическое переобучение моделей

Автоматическое переобучение (retraining) - это критический аспект ML в production. Без него модели деградируют со временем.

Проблема: Model Drift

Модель, обученная на старых данных, теряет точность когда распределение меняется:

from datetime import datetime
from sklearn.metrics import accuracy_score

accuracy_by_date = {
    "2024-01-01": 0.87,
    "2024-02-01": 0.82,
    "2024-03-01": 0.75,
    "2024-04-01": 0.68,
}

# Видим деградацию - нужно переобучение

1. Когда срабатывает переобучение

Вариант 1: По времени (Schedule-based)

Переобучаем каждый день/неделю/месяц:

from apscheduler.schedulers.background import BackgroundScheduler
import logging

scheduler = BackgroundScheduler()

def retrain_model():
    logging.info("Starting scheduled retraining...")
    X_new, y_new = load_production_data()
    model = train_model(X_new, y_new)
    save_model(model, "model_latest.pkl")
    logging.info("Retraining complete")

scheduler.add_job(retrain_model, 'cron', hour=2, minute=0)
scheduler.start()

Плюсы: простая реализация Минусы: может быть избыточным

Вариант 2: По метрикам (Metric-based)

Переобучаем когда точность упала ниже порога:

from sklearn.metrics import accuracy_score

class ModelMonitor:
    def __init__(self, baseline_accuracy=0.87, drop_threshold=0.05):
        self.baseline = baseline_accuracy
        self.threshold = drop_threshold
    
    def check_and_retrain(self, y_true, y_pred):
        current_accuracy = accuracy_score(y_true, y_pred)
        
        if current_accuracy < self.baseline - self.threshold:
            logging.info(f"Alert! Accuracy dropped to {current_accuracy:.3f}")
            self.retrain()
        
        return current_accuracy
    
    def retrain(self):
        logging.info("Triggering retraining...")
        X_new, y_new = load_recent_data(days=30)
        model = train_model(X_new, y_new)
        save_model(model)

monitor = ModelMonitor(baseline_accuracy=0.87)
accuracy = monitor.check_and_retrain(y_true, y_pred)

Плюсы: срабатывает когда нужно Минусы: нужен хороший мониторинг

Вариант 3: По дрейфу данных (Data Drift Detection)

from scipy.stats import ks_2samp

class DataDriftDetector:
    def __init__(self, reference_data):
        self.reference = reference_data
    
    def detect_drift(self, new_data, p_threshold=0.05):
        drifts = {}
        for col in self.reference.columns:
            statistic, p_value = ks_2samp(
                self.reference[col],
                new_data[col]
            )
            
            if p_value < p_threshold:
                drifts[col] = p_value
                logging.info(f"Drift detected in {col}")
        
        return drifts

detector = DataDriftDetector(X_train)
drifts = detector.detect_drift(X_production)

if drifts:
    logging.info("Data drift detected! Retraining...")
    retrain_model()

2. Полный pipeline автоматического переобучения

import logging
from datetime import datetime
import joblib
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score

logging.basicConfig(level=logging.INFO)

class AutoRetrainingPipeline:
    def __init__(self, model_path="model.pkl", threshold=0.05):
        self.model_path = model_path
        self.threshold = threshold
        self.model = joblib.load(model_path)
        self.baseline_accuracy = self.get_baseline()
        self.last_retrain = datetime.now()
    
    def get_baseline(self):
        X_val, y_val = load_validation_data()
        y_pred = self.model.predict(X_val)
        return accuracy_score(y_val, y_pred)
    
    def predict(self, X):
        y_pred = self.model.predict(X)
        self._check_performance_async(X, y_pred)
        return y_pred
    
    def _check_performance_async(self, X, y_pred):
        if (datetime.now() - self.last_retrain).seconds < 3600:
            return
        
        y_true = get_ground_truth(X)
        if y_true is not None:
            current_accuracy = accuracy_score(y_true, y_pred)
            
            if current_accuracy < self.baseline_accuracy - self.threshold:
                logging.warning(f"Accuracy drop: {current_accuracy:.3f}")
                self._trigger_retraining()
    
    def _trigger_retraining(self):
        logging.info("Starting automated retraining...")
        
        try:
            X_new, y_new = self._collect_new_data()
            
            if len(X_new) < 1000:
                logging.warning("Not enough data for retraining")
                return
            
            new_model = self._train_new_model(X_new, y_new)
            X_val, y_val = load_validation_data()
            
            new_accuracy = accuracy_score(y_val, new_model.predict(X_val))
            old_accuracy = accuracy_score(y_val, self.model.predict(X_val))
            
            if new_accuracy > old_accuracy:
                logging.info(f"New model better: {new_accuracy:.3f} > {old_accuracy:.3f}")
                self._deploy_new_model(new_model)
            else:
                logging.info(f"New model worse: {new_accuracy:.3f} < {old_accuracy:.3f}")
        
        except Exception as e:
            logging.error(f"Retraining failed: {e}")
        
        finally:
            self.last_retrain = datetime.now()
    
    def _collect_new_data(self):
        df = load_recent_data(days=30)
        X = df.drop(columns=["target"])
        y = df["target"]
        return X, y
    
    def _train_new_model(self, X, y):
        logging.info(f"Training on {len(X)} new samples...")
        model = RandomForestClassifier(n_estimators=100, n_jobs=-1, random_state=42)
        model.fit(X, y)
        return model
    
    def _deploy_new_model(self, new_model):
        timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
        backup_path = f"models/model_backup_{timestamp}.pkl"
        joblib.dump(self.model, backup_path)
        joblib.dump(new_model, self.model_path)
        self.model = new_model

pipeline = AutoRetrainingPipeline(model_path="models/current_model.pkl", threshold=0.05)
y_pred = pipeline.predict(X_production)

3. Incremental Learning

from sklearn.linear_model import SGDClassifier

class IncrementalLearningModel:
    def __init__(self):
        self.model = SGDClassifier(loss="log_loss", warm_start=True)
    
    def partial_fit(self, X_batch, y_batch):
        self.model.partial_fit(X_batch, y_batch, classes=[0, 1])
    
    def predict(self, X):
        return self.model.predict(X)

incremental_model = IncrementalLearningModel()
X_hour, y_hour = load_data(hours=1)
incremental_model.partial_fit(X_hour, y_hour)

4. Ключевые стратегии

  • Schedule-based: Переобучаем по расписанию (простой)
  • Metric-based: Переобучаем когда метрики падают
  • Data drift detection: Переобучаем когда распределение меняется
  • Incremental learning: Обновляем модель постепенно
  • Ensemble retraining: Держим несколько моделей, выбираем лучшую

5. Best Practices

  • Комбинируй schedule + metric-based подход
  • Всегда делай A/B тестирование новой модели
  • Бэкапируй старые версии
  • Мониторь дрейф данных
  • Логируй все переобучения
  • Имей возможность откатиться на предыдущую версию

Итог

Автоматическое переобучение критично для production ML потому что данные меняются, модели деградируют. Лучший подход - комбинация мониторинга метрик, детекции дрейфа и регулярного переобучения.