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

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

Есть набор данных, содержащий метаданные 1000 лучших стримеров Twitch за 2020 год. Подробности можно найти здесь.

В настоящее время я участвую в конкурсе на прогнозирование значений Полученных подписчиков, создавая и обучая модель, используя оставшиеся характеристики из набора данных. Цель моей работы — достичь наименьшего значения метрики RMSE (Корень из средней квадратической ошибки) от предсказаний модели.

До сих пор я предпринял множество попыток максимально снизить значение потерь RMSE. Мое текущее наименьшее достижение составляет около 101 000, которое я получил, увеличив набор данных и обучив модель DNN с 7 скрытыми слоями.

Тем не менее, я стараюсь снизить значение ошибки RMSE с 6 до 5-ти значений. Я пытался удалить выбросы, увеличить данные, применять инженерные приемы с признаками, проводить полиномиальную регрессию, обучать модели DNN с более чем 5 скрытыми слоями в среднем; создать и обучить несколько моделей и объединить их для окончательного предсказания (я слышал от сообщества, что использование комбинированной модели — один из ключей к достижению прогнозов регрессии с низкими метриками ошибки).

Все результаты моих моделей не превысили порог 6-значной ошибки RMSE. Проведено инженерное проектирование признаков, чтобы в модели остались только новые переменные с высокой корреляцией с целевым значением предсказания. Почти все гиперпараметры моделей, созданных с использованием библиотеки Tensorflow, были настроены для достижения наилучшей производительности. И все же значения RMSE не показывают снижения.

Вот некоторые из кодов, которые я написал, объясняя процесс создания и обучения моделей. Они не привели к более низкому значению RMSE, чем около 101 000. Вместо этого получилось более высокое значение, около 110 000.

[Модель DNN]

inputs = Input(shape=(7))

x1 = Dense(430, activation='selu', kernel_initializer=keras.initializers.RandomUniform())(inputs)
d1 = Dropout(0.9)(x1)

x2 = Dense(430, activation='selu', kernel_initializer=keras.initializers.RandomUniform())(d1)
d2 = Dropout(0.8)(x2)

x3 = Dense(256, activation='selu', kernel_initializer=keras.initializers.RandomUniform())(d2)
d3 = Dropout(0.7)(x3)

x4 = Dense(256, activation='selu', kernel_initializer=keras.initializers.RandomUniform())(d3)
d4 = Dropout(0.6)(x4)

x5 = Dense(128, activation='selu', kernel_initializer=keras.initializers.RandomUniform())(d4)
d5 = Dropout(0.7)(x5)

x6 = Dense(128, activation='selu', kernel_initializer=keras.initializers.RandomUniform())(d5)
d6 = Dropout(0.9)(x6)

x7 = Dense(32, activation='selu', kernel_initializer=keras.initializers.RandomUniform())(d6)
d7 = Dropout(0.9)(x7)

x8 = Dense(32, activation='selu', kernel_initializer=keras.initializers.RandomUniform())(d7)
d8 = Dropout(0.9)(x8)

outputs = Dense(1)(d8)

model = keras.Model(inputs=inputs, outputs=outputs)

def rmse(y_true, y_pred):
    return K.sqrt(mse(y_true, y_pred))

model.compile(
    loss=rmse, optimizer=keras.optimizers.Adam(learning_rate=0.001)
)

[XGBRegressor]

from xgboost import XGBRegressor

# Создание и обучение модели
xgb_model = XGBRegressor(objective="reg:linear", 
                         n_estimators=5000, 
                         max_depth=15, 
                         eta=0.001, 
                         subsample=0.8, 
                         colsample_bytree=0.8, 
                         eval_metric="rmse")

xgb_model.fit(X_train, y_train, eval_set=[(X_val, y_val)], verbose=0)

# Предсказания
train_pred = xgb_model.predict(X_train)
test_pred = xgb_model.predict(X_test)

# Производительность на обучающей выборке
xgb_train_evs = explained_variance_score(y_train, train_pred)
xgb_train_rmse = rmse(y_train, train_pred)

# Производительность на тестовой выборке
xgb_test_evs = explained_variance_score(y_test, test_pred)
xgb_test_rmse = rmse(y_test, test_pred)

# Вывод результатов
xgb_results = f"""
XGBoost Train EVS: {xgb_train_evs}
XGBoost Train RMSE: {xgb_train_rmse}

XGBoost Test EVS: {xgb_test_evs}
XGBoost Test RMSE: {xgb_test_rmse}
"""

print(xgb_results)

[LGBRegressor]

from lightgbm import LGBMRegressor as lgb

# Создание и обучение модели
lgb_model = lgb(boosting_type="gbdt", objective="regression",
                num_leaves=150, learning_rate=0.001, n_estimators=10**4)
lgb_model.fit(X_train, y_train)

# Предсказания
train_pred = lgb_model.predict(X_train)
test_pred = lgb_model.predict(X_test)

# Производительность на обучающей выборке
lgb_train_evs = explained_variance_score(y_train, train_pred)
lgb_train_rmse = rmse(y_train, train_pred)

# Производительность на тестовой выборке
lgb_test_evs = explained_variance_score(y_test, test_pred)
lgb_test_rmse = rmse(y_test, test_pred)

# Вывод результатов
lgb_results = f"""
LightGBM Train EVS: {lgb_train_evs}
LightGBM Train RMSE: {lgb_train_rmse}

LightGBM Test EVS: {lgb_test_evs}
LightGBM Test RMSE: {lgb_test_rmse}
"""

print(lgb_results)

[RandomForestRegressor]

from sklearn.ensemble import RandomForestRegressor

# Создание и обучение модели
forest = RandomForestRegressor(n_estimators=350, verbose=1)
forest.fit(X_train, y_train)

# Предсказания
train_pred = forest.predict(X_train)
test_pred = forest.predict(X_test)

# Производительность на обучающей выборке
rf_train_evs = explained_variance_score(y_train, train_pred)
rf_train_rmse = rmse(y_train, train_pred)

# Производительность на тестовой выборке
rf_test_evs = explained_variance_score(y_test, test_pred)
rf_test_rmse = rmse(y_test, test_pred)

# Вывод результатов
rf_results = f"""
Random Forests Train EVS: {rf_train_evs}
Random Forests Train RMSE: {rf_train_rmse}

Random Forests Test EVS: {rf_test_evs}
Random Forests Test RMSE: {rf_test_rmse}
"""

print(rf_results)

[Сложенные модели]

from sklearn.ensemble import StackingRegressor
from sklearn.linear_model import LinearRegression

# Используемые модели
estimators = [
    ('XGBRegressor', xgb_model),
    ('LGBMRegressor', lgb_model),
    ('RFRegressor', forest)
]

# Создание сложенной модели
stack_model = StackingRegressor(
    estimators=estimators, final_estimator=LinearRegression()
)

# Обучение сложенной модели
stack_model.fit(X_train, y_train)

# Предсказания
sm_train_pred = stack_model.predict(X_train) 
sm_test_pred = stack_model.predict(X_test)

# Производительность на обучающей выборке
sm_train_evs = explained_variance_score(y_train, sm_train_pred)
sm_train_rmse = rmse(y_train, sm_train_pred)

# Производительность на тестовой выборке
sm_test_evs = explained_variance_score(y_test, sm_test_pred)
sm_test_rmse = rmse(y_test, sm_test_pred)

# Вывод результатов
sm_results = f"""
Stacked Model Train EVS: {sm_train_evs}
Stacked Model Train RMSE: {sm_train_rmse}

Stacked Model Test EVS: {sm_test_evs}
Stacked Model Test RMSE: {sm_test_rmse}
"""

print(sm_results)

[Предсказания модели — в этом случае окончательное предсказание вычисляется как среднее значение между предсказаниями модели DNN и Сложенной модели.]

dnn_predictions = model.predict(test.values)
dnn_predictions = dnn_predictions.transpose()[0]

stacked_predictions = model.predict(test.values)
stacked_predictions = stacked_predictions.transpose()[0]

predictions = np.divide(np.add(dnn_predictions, stacked_predictions), 2)

Очевидно, что использование набора данных, созданного после инженерии признаков, приводит к предсказаниям с более высоким значением ошибки. Я ищу причину этого и возможности для улучшения. Как оптимально провести инженерные работы с признаками в случае этого набора данных? Вы можете получить доступ к файлу .csv оригинального набора данных по указанной выше ссылке. Также, какая структура модели рекомендуется для регрессионных задач, подобных этой? Я считаю, что чем сложнее становится модель, тем сложнее делать предсказания из-за переобучения.

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

Вот некоторые вещи, которые вы можете попробовать, чтобы улучшить результат (учтите, что это общие советы для тех, кто хочет улучшить свою модель):-

1.) Прежде всего, очистите данные, т.е. обработайте значения nan и выбросы. Вы можете либо удалить значения nan, либо заполнить их статистическим значением. Что касается выбросов, вам нужно быть осторожным, так как не все выбросы являются ненужными. Попробуйте выяснить, имеют ли они смысл, и если да, оставьте их. В противном случае удалите их. Также удалите дублирующиеся значения из вашего набора данных.

2.) Следующим шагом будет инженерия признаков. Попробуйте выяснить, можно ли объединить 2 или более признака в один. Это поможет снизить размерность (хотя вы говорите, что это приводит к снижению производительности).

3.) Выбор признаков, где вы оставляете только полезные признаки и удаляете лишние. Лучший инструмент, который вы можете использовать для этой цели — это знание предметной области. Используйте свои знания, чтобы выяснить, стоит ли удалять какой-либо признак. Если у вас недостаточно знаний, тогда следует обратиться к техникам отбора признаков, таким как фильтрующий, упаковочный, гибридный и т.д. (RFECV и BorutaShap на мой взгляд одни из лучших)

4.) Гиперпараметрическая настройка! Вы можете использовать любую из существующих техник для этой цели (если вы спросите меня, выберите Optuna!).

5.) Попробуйте больше моделей! Я не знаю, сколько моделей вы пытались, но здесь вы упоминаете только несколько. Существует более 36 моделей регрессии, поэтому попробуйте как можно больше, чтобы выяснить, какая из них дает лучшие результаты. Здесь приведен обширный список!

6.) Просто получите больше данных. В вашем случае это, вероятно, не будет особенно полезно, так как вы взяли набор данных с Kaggle!

.

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

Оптимизация модели для снижения значения RMSE (Корень среднеквадратичной ошибки) при регрессионном анализе может быть достаточно сложной задачей, особенно при работе с реальными наборами данных, такими как метаданные топ-1000 стримеров Twitch за 2020 год. Ваше стремление снизить ошибку RMSE с шести до пяти цифр требует комплексного подхода, включающего улучшение инженерии признаков, выбор моделей и иную оптимизацию. Рассмотрим основные стратегии для достижения этой цели.

Теория

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

  2. Инженерия признаков и отбор признаков: Инженерия признаков включает в себя создание новых переменных на основе существующих данных, что может привести к улучшению качества модели. Это может быть автоматическая генерация полиномов или взаимодействие признаков. Важен и отбор признаков, который позволяет оставить только значимые переменные. Здесь может быть полезна экспертиза в домене; в противном случае используются методы автоматического отбора, такие как Filter/Wrapper методы, RFECV, BorutaShap и другие.

  3. Гиперпараметрическая оптимизация: Этот аспект часто упускают из виду, но он существенно влияет на результаты. Методы гиперпараметрической оптимизации, такие как Grid Search, Random Search или новейшие алгоритмы, такие как Optuna, позволяют точнее настроить модели, что может существенно улучшить качество прогнозов.

  4. Выбор моделей: Существует много типов регрессионных моделей, и стоит исследовать разнообразные подходы. Помимо глубоких нейронных сетей, хорошо было бы использовать алгоритмы ансамблирования (к примеру, Bagging, Boosting), которые включают в себя XGBoost, LightGBM, и другие. Использование ансамблей моделей может дать дополнительные преимущества за счет объединения сильных сторон разных методов.

  5. Объем данных: Количество данных, с которым вы работаете, также может ограничивать возможности вашей модели. В контексте Kaggle получение дополнительных данных может быть сложным, но различные техники аугментации могут дать позитивные результаты.

Пример

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

  • Вы интегрировали удаление выбросов и преобразование переменных, чтобы улучшить качество данных.
  • Вы использовали Boruta для отбора значимых признаков, что позволило сократить количество ненужных данных, улучшая интерпретируемость и простоту модели.
  • Оптимизация гиперпараметров проводилась с помощью Optuna, что значительно улучшило настройки моделей, таких как XGBoost и LightGBM.
  • Ансамблирование моделей посредством стохастического градиентного бустинга и стекинга позволило объединить преимущества разных методов, давая более точные прогнозы.

Применение

Теперь, перейдя к практической части, давайте рассмотрим, как вы можете применить перечисленные выше идеи для уменьшения ошибки RMSE в вашем конкретном случае.

  1. Подготовка данных: Начните с первичной очистки данных, включая проверку выбросов и обработку пропущенных значений. Используйте визуализационные инструменты для анализа распределения данных. Оцените, какие показатели могут быть шумом, и удалите их, если они не имеют логического обоснования.

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

  3. Гиперпараметрицеская оптимизация: Воспользуйтесь библиотеками, такими как Optuna, которые предоставляют мощные средства для тонкой настройки моделей. Это позволит вам найти наилучшие параметры для таких моделей, как XGBoost или LightGBM, которые часто проявляют хорошие результаты в задачах регрессии.

  4. Модели и ансамбли: Попробуйте использовать более разнообразные модели. Например, ансасмблирование позволяет вам улучшать точность за счет симбиоза нескольких алгоритмов. Рассмотрите стекинг, где модели работают в связке, чтобы учитывать их преимущества и нивелировать слабые стороны.

Ваше стремление снизить RMSE до пяти цифр – достойная цель, которая является достижимой при правильном подходе. Улучшение качества данных, тонкая настройка моделей и их гибкая комбинация позволят вам разработать решение, максимально приближенное к вашим ожиданиям. Удачи в конкурсе на Kaggle, и пусть ваши усилия увенчаются успехом!

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

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