Модульный ноутбук для настройки и сравнения 11 алгоритмов прогнозирования с минимальным кодированием в модной панели управления.

В этой статье суммируются и объясняются ключевые модули моего блока регрессии (один из простых модульных блокнотов, которые я разрабатываю для выполнения общих задач анализа). Записная книжка предназначена для облегчения более быстрых экспериментов для пользователей со средним пониманием регрессионных моделей и программирования на Python. Ссылка на блокнот GitHub находится внизу статьи!

Введение

Работая над одним из моих любимых проектов, я понял, что иногда лучше протестировать различные формы моделей, чтобы определить наиболее подходящую модель, которая обеспечивает хороший баланс точности, сложности и эффективности выполнения в зависимости от решаемой проблемы. Некоторые программы, например RapidMiner, предоставляют эту функцию. Однако использование программного продукта для этой цели приводит к подходу «черного ящика» с точки зрения настройки модели и изучения некоторых тонкостей. Поэтому я решил создать простой скрипт Python с модуляризацией и параметризацией, достаточной для тестирования и настройки многих широко используемых алгоритмов прогнозирования с минимальными изменениями в коде.
Краткое содержание этой записной книжки выглядит следующим образом:

Цель:

Для тестирования, настройки и сравнения различных регрессионных моделей с минимальным вмешательством вручную в Python.
В этот модуль включены следующие модели:

* Линейная регрессия
* Регрессия гребня
* Регрессия Лассо
* K ближайших соседей
* Байесовский гребень
* Регрессия дерева решений
* Случайный лес
* Пакетирование (по умолчанию используется дерево решений)
* Повышение градиента
* XGBoost
* Поддержка векторных машин

Уровень владения пользователем:

Пользователь должен интуитивно понимать, как работает каждый из этих алгоритмов, а также хорошо понимать, как изменение конкретного гиперпараметра может повлиять на результат. Для эффективного использования кода и дальнейшей настройки его в соответствии с требованиями требуется базовое понимание Python.

Ключевые изменяемые входы:

Ниже приведены основные входные данные (более подробная информация по каждому входу представлена ​​во встроенных комментариях). Эти разделы были выделены в коде пометкой «ВНЕСТИ ИЗМЕНЕНИЯ ЗДЕСЬ»:

* Входной набор данных для регрессионного анализа: в этом примере я использовал набор данных «диабет» из наборов данных по умолчанию pandas
* Соотношение тестовых данных: от 0 до 1, по умолчанию 0,3 (или 30%)
* Нормализация: 0 - без нормализации, 1 - минимальное-максимальное масштабирование, 2 - масштабирование Z-оценки
* Список объектов модели для тестирования
* Количество складок для поиска по сетке (настройка гиперпараметров)
* Критерии оценки для определения наилучшей модели (например, среднеквадратичная ошибка) - более подробная информация представлена ​​в комментариях к коду
* Отметьте, чтобы увидеть уровень детализации терминала во время подбора модели: 0 - нет вывода, 1 - Все подробности, 2 - Индикатор выполнения
* Библиотека гиперпараметров: глобальный словарь в коде, который предоставляет набор гиперпараметров для каждой формы модели для настройки.

Общие шаги выполнения:

После ввода этих данных для каждой модельной формы выполняются следующие действия:

* Прямой выбор функции
* Нормализация
* Поиск по сетке для настройки гиперпараметров
* Расчет метрики для лучшей модели

Вывод:

Создается фрейм данных pandas «результаты», который предоставляет следующие показатели для каждой модели, которую вы тестируете.

* Детали модели с наиболее оптимальными гиперпараметрами
* Среднеквадратичные ошибки обучения и проверки
* Средние абсолютные ошибки в процентах при обучении и тестировании

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

Важная заметка:

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

Сценарий:

Модули для различных задач

Первая функция создает конвейер для нормализации и поиска по сетке на основе условий, заданных пользователем в панели управления.

def create_pipeline(norm, model):
    if norm == 1:
        scale = StandardScaler()
        pipe = Pipeline([('norm', scale), ('reg', model)])
    elif norm == 2:
        scale = MinMaxScaler()
        pipe = Pipeline([('norm', scale), ('reg', model)])
    else:
        pipe = Pipeline([('reg', model)])
    return pipe

Вторая функция выполняет прямой выбор характеристик и возвращает индексы лучших характеристик.

def select_features(model, X_train, Y_train, selection,
                    score_criteria, see_details, norm=0):
    pipe = create_pipeline(norm, model)
    sfs = SequentialFeatureSelector(pipe,
                                    forward=selection,
                                    k_features='best',
                                    scoring=score_criteria,
                                    verbose=see_details)
    sfs = sfs.fit(X_train, Y_train)
    return list(sfs.k_feature_idx_)

Эта функция выполняет поиск по сетке для заданной сетки параметров и возвращает лучший объект модели.

def run_model(model, param_grid, X_train, Y_train,
              X, Y, score_criteria, folds,
              see_details, norm=0):
    pipe = create_pipeline(norm, model)
    model_grid = GridSearchCV(pipe,
                              param_grid,
                              cv=folds,
                              scoring=score_criteria,
                              verbose=see_details)
    model_grid.fit(X_train, Y_train)
return model_grid.best_estimator_

Последняя функция вычисляет все соответствующие метрики для лучшей комбинации гиперпараметров и возвращает серию панд этих метрик.

def get_model_eval(model, X_train, Y_train, X_test, Y_test):
    return pd.Series([model, mean_squared_error(Y_train, model.predict(X_train)),
                      mean_squared_error(Y_test, model.predict(X_test)),
                      (abs(model.predict(X_train) - Y_train) / Y_train).mean(),
                      (abs(model.predict(X_test) - Y_test) / Y_test).mean()])

Глобальный словарь гиперпараметров (ВНЕСТИ ИЗМЕНЕНИЯ ЗДЕСЬ)

Это глобальный словарь для различных параметров модели для всех моделей в этом модуле. Некоторый набор значений по умолчанию был заполнен в коде для типичных диапазонов на основе набора данных диабета. Этот словарь содержит некоторые ключевые гиперпараметры для каждой модели и не является исчерпывающим. Пользователям рекомендуется посетить документацию scikit-learn, чтобы получить список всех параметров и добавить в приведенный ниже словарь в соответствии со своими требованиями.

PARAM_DICT = {
              LinearRegression: {'reg__copy_X': [True, False],
                                 'reg__fit_intercept': [True, False],
                                 'reg__n_jobs': [10, 20]},
              Ridge: {'reg__alpha': [0.1, 1, 100],
                      'reg__copy_X': [True, False],
                      'reg__fit_intercept': [True, False],
                      'reg__tol': [0.1, 1],
                      'reg__solver': ['auto', 'svd', 'cholesky', 'lsqr',
                                      'sparse_cg', 'sag', 'saga']},
              Lasso: {'reg__alpha': [0.1, 1, 100],
                      'reg__copy_X': [True, False],
                      'reg__fit_intercept': [True, False],
                      'reg__tol': [0.1, 1]},
KNeighborsRegressor: {'reg__n_neighbors': [5, 30, 100]},
              BayesianRidge: {'reg__alpha_1': [10**-6, 10**-3],
                              'reg__alpha_2': [10**-6, 10**-3],
                              'reg__copy_X': [True, False],
                              'reg__fit_intercept': [True, False],
                              'reg__lambda_1': [10**-6, 10**-3],
                              'reg__lambda_2': [10**-6, 10**-3],
                              'reg__n_iter': [300, 500, 1000],
                              'reg__tol': [0.001, 0.01, 0.1]},
DecisionTreeRegressor: {'reg__max_depth': [5, 10, 20],
                                      'reg__max_features': [0.3, 0.7, 1.0],
                                      'reg__max_leaf_nodes': [10, 50, 100],
                                      'reg__splitter': ['best', 'random']},
BaggingRegressor: {
                                 'reg__bootstrap': [True, False],
                                 'reg__bootstrap_features': [True, False],
                                 'reg__max_features': [0.3, 0.7, 1.0],
                                 'reg__max_samples': [0.3, 0.7, 1.0],
                                 'reg__n_estimators': [10, 50, 100]},
              RandomForestRegressor: {'reg__bootstrap': [True, False],
                                      'reg__max_depth': [5, 10, 20],
                                      'reg__max_features': [0.3, 0.7, 1.0],
                                      'reg__max_leaf_nodes': [10, 50, 100],
                                      'reg__min_impurity_decrease': [0, 0.1, 0.2],
                                      'reg__n_estimators': [10, 50, 100]},
SVR: {'reg__C': [10**-3, 1, 1000],
                    'reg__kernel': ['linear', 'poly', 'rbf'],
                    'reg__shrinking': [True, False]},
GradientBoostingRegressor: {'reg__learning_rate': [0.1, 0.2, 0.5],
                                          'reg__loss': ['ls', 'lad', 'huber', 'quantile'],
                                          'reg__max_depth': [10, 20, 50],
                                          'reg__max_features': [0.5, 0.8, 1.0],
                                          'reg__max_leaf_nodes': [10, 50, 100],
                                          'reg__min_impurity_decrease': [0, 0.1, 0.2],
                                          'reg__min_samples_leaf': [5, 10, 20],
                                          'reg__min_samples_split': [5, 10, 20],
                                          'reg__n_estimators': [10, 50, 100]},
              XGBRegressor: {'reg__booster': ['gbtree', 'gblinear', 'dart'],
                             'reg__learning_rate': [0.2, 0.5, 0.8],
                             'reg__max_depth': [5, 10, 20],
                             'reg__n_estimators': [10, 50, 100],
                             'reg__reg_alpha': [0.1, 1, 10],
                             'reg__reg_lambda': [0.1, 1, 10],
                             'reg__subsample': [0.3, 0.5, 0.8]},
}

Панель управления пользователя для клавишных вводов (ВНЕСТИ ИЗМЕНЕНИЯ ЗДЕСЬ)

Здесь можно изменить входы модулей. Это панель управления для этого сценария, где все переменные, упомянутые во введении, могут быть изменены для тестирования различных сценариев. Пожалуйста, обратитесь к комментариям, чтобы понять переменные.

# --------------------------------------------------------------------------
# USER CONTROL PANEL, CHANGE THE VARIABLES, MODEL FORMS ETC. HERE
# Read data here, define X (features) and Y (Target variable)
data = datasets.load_diabetes()
X = pd.DataFrame(data['data'])
X.columns = data['feature_names']
Y = data['target']
# Specify size of test data (%)
size = 0.3
# Set random seed for sampling consistency
random.seed(100)
# Set type of normalization you want to perform
# 0 - No Normalization, 1 - Min-max scaling, 2 - Zscore scaling
norm = 0
# Mention all model forms you want to run - Model Objects
to_run = [LinearRegression,
          Ridge,
          Lasso,
          KNeighborsRegressor,
          DecisionTreeRegressor,
          BaggingRegressor,
          SVR,
          XGBRegressor]
# Specify number of crossvalidation folds
folds = 5
# Specify model selection criteria
# Possible values are:
# ‘explained_variance’
# ‘neg_mean_absolute_error’
# ‘neg_mean_squared_error’
# ‘neg_mean_squared_log_error’
# ‘neg_median_absolute_error’
# ‘r2’
score_criteria = 'neg_mean_absolute_error'
# Specify details of terminal output you'd like to see
# 0 - No output, 1 - All details, 2 - Progress bar
# Outputs might vary based on individual functions
see_details = 1
# --------------------------------------------------------------------------

Исполнение модели

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

# Model execution part, resuts will be stored in the dataframe 'results'
# Best model can be selected based on these criteria
results = pd.DataFrame(columns=['ModelForm', 'TrainRMSE', 'TestRMSE',
                                'TrainMAPE', 'TestMAPE'])
X_train, X_test, Y_train, Y_test = train_test_split(X, Y, test_size=size)
for model in to_run:
    with warnings.catch_warnings():
        warnings.simplefilter('ignore')
        best_feat = select_features(model(), X_train, Y_train, True,
                                    score_criteria, see_details, norm)
        model = run_model(model(), PARAM_DICT[model],
                          X_train.iloc[:, best_feat],
                          Y_train,
                          X.iloc[:, best_feat], Y,
                          score_criteria, folds, see_details, norm)
        stats = get_model_eval(model, X_train.iloc[:, best_feat], Y_train,
                               X_test.iloc[:, best_feat], Y_test)
        stats.index = results.columns
        results = results.append(stats, ignore_index=True)
print(results)

Вывод

Из таблицы результатов видно, что самая базовая модель линейной регрессии обеспечивает лучшую и стабильную производительность среди всех форм модели, протестированных в этом сценарии. Это подчеркивает важность проектирования функций, поскольку мы ожидаем, что ансамблевые модели в целом будут демонстрировать лучшую производительность. С другой стороны, XGB Regressor показывает признаки переобучения на основе показателей обучения и тестирования. Все остальные модели обеспечивают сопоставимые характеристики. Это также указывает на необходимость тестирования другого диапазона гиперпараметров.
Я надеюсь, что этот модуль позволяет быстрее экспериментировать и дает возможность создавать дополнительные настройки, исходя из ваших потребностей!

Получите доступ к полной записной книжке здесь:



Не стесняйтесь присылать любые предложения и отзывы!