Почему модель для набора данных может давать разные результаты среднеквадратичной ошибки?

Вопрос или проблема

Я пытаюсь получить сертификат Data Scientist Associate от DataCamp. У меня возникла проблема с пробным экзаменом, предоставленным для практики перед Практическим Экзаменом. Я предоставил детали ниже. Буду очень признателен за вашу помощь.


Цель проекта – предсказать потребительские привычки клиентов из DataFrame одной франшизы супермаркета.
Колонки в DataFrame:

  • customer_id: Уникальный идентификатор клиента.
    Отсутствующие значения невозможны из-за структуры базы данных.
  • spend: Непрерывный.
    Общая сумма затрат клиента за последний полный год. Это может быть любое положительное значение с точностью до двух десятичных знаков.
    Отсутствующие значения следует заменять на 0.
  • first_month: Непрерывный.
    Сумма, потраченная клиентом в первый месяц года. Это может быть любое положительное значение, округленное до двух десятичных знаков.
    Отсутствующие значения следует заменять на 0.
  • items_in_first_month: Дискретный.
    Количество товаров, купленных в первый месяц. Любое целое значение, большее либо равное нулю.
    Отсутствующие значения следует заменять на 0.
  • region: Номинальный.
    Географический регион, в котором находится клиент. Одно из четырех значений: Америки, Азия/Тихоокеанский регион, Европа, Ближний Восток/Африка.
    Отсутствующие значения следует заменять на “Неизвестно”.
  • joining_month: Номинальный.
    Месяц, в котором клиент присоединился к программе лояльности. Одно из 12 значений: “Янв”, “Фев”, “Март”, “Апр” и т.д.
    Отсутствующие значения следует заменять на “Неизвестно”.
  • promotion: Номинальный.
    Вступил ли клиент в программу лояльности в рамках акции? Либо ‘Да’, либо ‘Нет’.
    Отсутствующие значения следует заменять на ‘Нет’.
  • loyalty_year: Порядковый.
    Количество лет, которое клиент участвует в программе лояльности. Одна из пяти упорядоченных категорий: ‘0-1’, ‘1-3’, ‘3-5’, ‘5-10′, ’10+’.
    Отсутствующие значения следует заменять на ‘0-1’.

В задаче 3 и 4 мне нужно было использовать предоставленные обучающую и тестовую выборки для предсказания столбца spend с помощью модели. Мне нужно было выбрать лучшую модель, и лучшая модель должна была давать среднеквадратичную ошибку (RMSE) ниже 0.35.

Однако тестовые данные не включают столбец spend в проекте. Поэтому я использовал исходные данные (набор данных по лояльности), которые были предоставлены для задачи “очистка данных” (Задача 1) проекта, чтобы проверить, какая модель будет лучшей.


Я использовал цикл для тестирования нескольких моделей (LinearRegression, Ridge, KNeighborsRegressor, DecisionTreeRegressor, RandomForestRegressor и GradientBoostingRegressor) и выяснил, что ни одна из моделей не дала RMSE ниже 0.35. RandomForestRegressor показал наименьший результат (0.59), но независимо от того, что я делал, я не мог получить более низкий результат.

Я смог получить решение от кого-то из DataCamp, но в предоставленном решении использовалась только LinearRegression или Ridge как модели. Они не проводили масштабирование или преобразование. Я не понимаю, как это возможно. Я снова поместил эти модели в цикл без какого-либо масштабирования или преобразования, но результаты все равно не были достаточно низкими. LinearRegression показала 1.05, а Ridge — 1.77.

Я не понимаю, почему это решение сработало в системе и все равно не показало хороших результатов в лучшем из циклов моделей. Я понимаю, что наборы данных на самом деле разные, но на самом деле они оба из этого воображаемого супермаркета. Я бы не подумал, что они настолько по-разному реагируют на модели. Если кто-то это понимает, я бы очень оценил ваш взгляд.


Пример моего лучшего цикла моделей представлен ниже:

# Сначала создайте словарь моделей и их распределений параметров
models = {
    'LinearRegression': {
        'model': LinearRegression(),
        'params': {
            'fit_intercept': [True, False],
            'copy_X': [True, False]
        }
    },
    "Ridge": {
        "model": Ridge(),
        "params": {
            'fit_intercept': [True, False],
            'copy_X': [True, False],
            "alpha": [float(x) for x in np.linspace(start=10, stop=2000, num=10)],
            "max_iter": [None] + list(range(3, 20)),
            "solver": ['auto', 'svd', 'cholesky', 'lsqr', 'sparse_cg', 'sag', 'saga'],
            "tol": [1e-4, 1e-3, 1e-2, 1e-1, 1.0],
            "positive": [True, False]
        }
    },
    'KNeighborsRegressor': {
        'model': KNeighborsRegressor(),
        'params': {
            'n_neighbors': list(range(1, 31)),
            'weights': ['uniform', 'distance'],
            'algorithm': ['auto', 'ball_tree', 'kd_tree', 'brute']
        }
    },
    'DecisionTreeRegressor': {
        'model': DecisionTreeRegressor(),
        'params': {
            'max_depth': [None] + list(range(3, 20)),
            'min_samples_split': range(2, 11),
            'min_samples_leaf': range(1, 11)
        }
    },
    'RandomForestRegressor': {
        'model': RandomForestRegressor(),
        'params': {
            'n_estimators': [int(x) for x in np.linspace(start=200, stop=2000, num=10)],
            'max_features': ['auto', 'sqrt'],
            'max_depth': [int(x) for x in np.linspace(10, 110, num=11)],
            'min_samples_split': [2, 5, 10],
            'min_samples_leaf': [1, 2, 4]
        }
    },
    "GradientBoostingRegressor": {
        "model": GradientBoostingRegressor(),
        "params": {
            "n_estimators": [int(x) for x in np.linspace(start=200, stop=2000, num=10)], 
            "max_depth": [int(x) for x in np.linspace(10, 110, num=11)], 
            "random_state": [42]
        }
    }
}

# Инициализация переменных для хранения лучшей модели и оценки
best_score = float('inf')
best_model = None
best_model_name = None
scores = {}

# Предположим, что X_train, X_test, y_train, y_test - ваши данные
for model_name, model_info in models.items():
    # Создание и обучение модели с использованием RandomizedSearchCV
    random_search = RandomizedSearchCV(
        estimator = model_info['model'],
        param_distributions = model_info['params'],
        n_iter = 100,  # количество выборок конфигураций параметров
        cv = 5,        # количество фолдов
        verbose = 1,
        random_state = 42
    )
    
    
    try:
        # Обучение модели
        random_search.fit(X_train, y_train)
        
        # Прогнозирование
        y_pred = random_search.predict(X_test)
        
        # Вычисление оценки (используйте соответствующую метрику в зависимости от задачи)
        score = np.sqrt(mean_squared_error(y_test, 
                                           y_pred))
        
        
        print(f"{model_name} - Лучшая оценка: {score}")
        
        scores[model_name] = score
        
        
        
        # Обновление лучшей модели, если текущая модель лучше
        if score < best_score:
            best_score = score
            best_model = random_search.best_estimator_
            best_model_name = model_name
            
    except Exception as e:
        print(f"Ошибка с {model_name}: {str(e)}")
        continue

print(f"\nЛучшая модель: {best_model_name}")
print(f"Лучшая оценка: {best_score}")
print(f"Лучшие параметры: {best_model.get_params()}")

Ответ или решение

Когда модель для набора данных выдает различные результаты RMSE (корневую среднеквадратичную ошибку), это может быть связано с несколькими факторами. Давайте рассмотрим их подробно в контексте вашей задачи предсказания "траты клиентов" на основе предоставленного DataFrame.

  1. Различия в тренировочных и тестовых данных: Отсутствие spend в тестовых данных вынуждает вас использовать другой набор данных для тестирования. Даже если данные исходят из одной и той же базы, их структура и распределение могут различаться, что напрямую влияет на производительность моделей.

  2. Разное распределение данных: В реальных проектах рабочий и тестовый наборы могут иметь разные распределения данных. Это может вызвать обучающийся сдвиг, когда модель обучена на одном распределении и тестируется на другом, что также может повлиять на RMSE.

  3. Параметры моделей и гиперпараметрическая настройка: Вы используете RandomizedSearchCV для поиска лучших гиперпараметров моделей. Однако, 100 итераций может быть недостаточно для больших наборов параметров, как в случае с Ridge и RandomForestRegressor. Ваша модель может не достигнуть оптимальных параметров за отведенное количество итераций.

  4. Отсутствие предварительной обработки данных: Ваша проблема упоминает, что модели от DataCamp не проходили этапов масштабирования и трансформации и давали более точные результаты. Это необычно, но может указывать на то, что данные уже были предварительно обработаны, или на то, что используемые в обучении данные были ложно идентифицированы как очищенные.

  5. Качество данных и заполнение пропусков: Способы заполнения пропусков в данных могут существенно влиять на эффективность моделей. Например, установка значений "спенда" в 0 для пропущенных входов может создать смещения в данных и нарушить предсказания.

  6. Сложность модели: Более сложные модели, такие как RandomForest и GradientBoosting, могут страдать от переобучения, если данных недостаточно для их адекватного обучения, в отличие от более простых моделей, таких как LinearRegression.

Для улучшения результатов рекомендую следующие шаги:

  • Анализировать данные: Поймите распределение и корреляции данных, чтобы откорректировать подходы к их заполнению и обработке.

  • Больше внимания к предварительной обработке: Исследуйте возможность масштабирования и нормализации данных, если они еще не были включены.

  • Конфигурация гиперпараметров: Увеличьте количество итераций и учтите другие параметры, которые вы могли бы тестировать.

  • Разбиение данных: Убедитесь, что данные равномерно распределены по наборам тренировки и тестирования для лучшего обобщения модели.

Такая мульти-факторная диагностика и потенциальная коррекция способна улучшить ваши RMSE результаты, приблизив их к требуемым нормативам.

Оцените материал
Добавить комментарий

Капча загружается...