Tidyverse изменил правила игры, когда дело доходит до анализа данных в R. Экосистема Tidyverse также включает аккуратное машинное обучение, которое упрощает изучение, анализ и управление сложными объектами машинного обучения, отчасти благодаря рабочему процессу столбца списка. Я хотел попробовать прогнозирование в Tidyverse, используя пакет modeltime, разработанный Мэттом Данчо, который был создан для аккуратного прогнозирования временных рядов в соответствии с оптимизированным рабочим процессом.

Рабочий процесс машинного обучения Tidyverse использует множество различных моделей машинного обучения, включая пакет Prophet, созданный командой Facebook Core Data Science. Пророк устойчив к тенденциям в данных временных рядов, включая ежедневную, недельную и годовую сезонность. Тенденция в данных временных рядов — это особая закономерность, в которой наблюдения либо увеличиваются, либо уменьшаются с течением времени. Кроме того, тенденции могут постоянно меняться. Пакет Prophet был разработан, чтобы быть устойчивым к изменяющимся тенденциям, отсутствующим данным и выбросам, поэтому мы будем использовать этот пакет для моделирования и прогнозирования наших данных о продажах.

Этот набор данных взят из главы 31 книги Уэйна Л. Уинстона Маркетинговая аналитика: методы, основанные на данных, с Microsoft Excel. У нас есть три (3) года ежедневных продаж стикеров. Эти милые отрывки из заметок, которые висят на вашем столе.

Мы сделаем следующее:

  1. Определите, какие факторы влияют на продажи
  2. Создайте модель для прогнозирования ежедневных продаж

Исследовать набор данных

Давайте импортируем и проверим наши данные. У нас есть 6 переменных:

  1. Месяц (месяц как число)
  2. Номер дня
  3. День (это наша переменная даты, но поскольку мы импортировали из Excel, мы получаем даты в формате Excel)
  4. Цены на этот конкретный день (7 разных цен)
  5. Display (это бинарная переменная. 1 означает, что наш продукт был на витрине в этот день. 0 означает, что его не было на витрине).
  6. Фактические продажи

Нам нужно сделать небольшое преобразование, чтобы получить наши данные в правильном формате. Во-первых, давайте создадим новый отформатированный столбец даты, поскольку наш столбец данных унаследовал форматирование даты Excel.

#Create New Formatted Date Column supplying origin argument
postit$new_date <- as.Date(postit$Day, origin = "1899-12-30")
#Check results
str(postit$new_date)

Давайте факторизуем некоторые переменные.

#Create list of variables that need transformation
fac_vars <- c("Month", "display")
#Factor Month, Display and Price Variables
postit[,fac_vars] <- lapply(postit[,fac_vars], factor)
#Check results
str(postit)

Давайте визуализируем наши продажи во времени с помощью функции plot_time_series() из пакета timetk. Если вы установите аргумент .interactive = TRUE, то ваш график будет интерактивным графиком Plotly.

#From timetk package - visualize sales
postit %>%
  plot_time_series(new_date, actualsales, .interactive = TRUE)

Наш график продаж показывает, что существует положительная тенденция продаж наших стикеров.

Задача 1. Какие факторы влияют на продажи

Во-первых, давайте создадим визуализацию данных о фактических продажах.

Продажи немного смещены вправо, но после преобразования журнала выглядят нормально. Продажи самые низкие в марте. Продажи, как правило, выше в четвертом квартале и максимальны в декабре. Декабрь также, кажется, имеет самый большой разброс продаж. Некоторые выбросы в течение месяцев августа и сентября. График продаж по цене дает довольно интересные результаты. Продажи самые высокие при цене 5,95. Продажи уменьшаются, когда цена увеличивается до 6,1 и так далее, где самые низкие продажи происходят, когда цена достигает своего максимума 7,52. По-видимому, существует связь между ценой и продажами.

Больше продаж, когда есть дисплей. Средний объем продаж составляет 639 против 587.

Теперь, когда у нас есть некоторое представление о факторах, влияющих на продажи, мы можем количественно оценить отношения с помощью модели линейной регрессии.

Первым шагом построения модели линейной регрессии является построение спецификации модели. Мы построим модель, чтобы она соответствовала фактическим продажам, объясненным только месяцем, ценой и отображением.

# Model Spec
model_spec_lm <- linear_reg() %>%
set_engine(“lm”)
# Build Linear Regression Model
model_fit_ln <- model_spec_lm %>%
fit(actualsales ~ Month + Price + display, data = postit)
#Print summary of model in a tidy object
lm_summary <- tidy(model_fit_lm) %>% 
              mutate(significant = p.value <= 0.05)
lm_summary
#If you prefer the classic R-style model output, you can use summary function to print fit to console
summary(model_fit_lm$fit)

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

Большинство месяцев являются значимыми, но декабрь является положительным и наиболее статистически значимым. Время года действительно влияет на продажи.

Все ценовые коэффициенты отрицательные и значимые, что означает, что все уровни цен (не на нашем пересечении) уменьшают продажи.

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

Оцените соответствие модели линейной регрессии

#Use the glance function from the broom package to get additional information from the model (e.g. model statistics like r-squared)
glance(model_fit_lm)

Оценка соответствия модели дает нам информацию о том, что построенная нами модель достаточно разумна, чтобы мы могли получить представление. Что касается статистики модели, у нас очень низкое значение p и r-квадрат 0,795, что говорит нам о том, что 80% вариаций в продажах объясняются нашими независимыми/объясняющими переменными.

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

Задача 2. Создайте модель прогноза продаж

Шаг 1. Разделите набор данных на тестовые и обучающие данные

Мы разделим наш набор данных на тестовые и обучающие данные. Мы будем использовать набор данных за последние 12 месяцев в качестве обучающего набора.

#Step 1: Split data into test and training set
splits <- postit %>%
  time_series_split(date_var = new_date, assess = "12 months", cumulative = TRUE)
#Visualize test train split
splits %>%
  tk_time_series_cv_plan() %>%
  plot_time_series_cv_plan(new_date, actualsales, .interactive = TRUE)

Шаг 2. Мы хотим определить спецификацию нашей модели и подогнать ее под модель. Мы будем использовать пророка.

# Step 2: Model Specification and Model fit
model_spec_prophet <- prophet_reg() %>%
    set_engine("prophet")

Шаг 3. Поместите модель в таблицу modeltime

#Step 3: Put model into a modeltime table
models_tbl <- modeltime_table(model_fit_prophet)
models_tbl

Шаг 4. Калибровка модели

На этапе калибровки вычисляются предсказания прогноза и остатки по тестовому набору.

#Step 4: Calibrate model
calibration_tbl <- models_tbl %>% 
  modeltime_calibrate(new_data = testing(splits))
#Can also print calibration model to console
calibration_tbl

Шаг 5. Получите показатели точности

#Step 5: Get Accuracy Metrics
calibration_tbl %>%
    modeltime_accuracy()

При определении погрешности и точности существует несколько различных показателей для оценки прогнозов, но я сосредоточусь на следующих двух (2):

Средняя абсолютная ошибка (MAE): насколько далеки наши прогнозы от фактического значения в абсолютном выражении и находятся ли они в том же масштабе, что и данные.

Средняя абсолютная погрешность в процентах (MAPE): насколько далеки наши прогнозы от фактического значения в абсолютном процентном выражении, чтобы значения прогнозов не зависели от масштаба.

Я обращаю внимание на MAPE, так как он часто используется в бизнесе для измерения прогнозов. Процентная ошибка = (факт — прогноз) / факт.

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

#Plot the residuals
# Out-of-Sample data (test set)
#Change new_data argument if you want to plot in-sample residuals (training set). Timeplot is the default but can change to acf or seasonality plot.
calibration_tbl %>%
    modeltime_calibrate(new_data = testing(splits)) %>%
    modeltime_residuals() %>%
    plot_modeltime_residuals(.interactive = TRUE, .type = "timeplot")

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

Шаг 6. Создание прогноза на будущее на тестовом наборе

#Step 6: Create future forecast on test data
(forecast_tbl <- calibration_tbl %>%
    modeltime_forecast(
        new_data    = testing(splits),
        actual_data = postit,
        keep_data = TRUE #Includes the new data (and actual data) as extra columns with the results of the model forecasts
    ))

Когда вы открываете таблицу (фрейм данных) для модели прогноза, столбец .key указывает, является ли столбец .value фактическим значением или значением прогноза. Предсказания этой модели начинаются со строки 1097.

Шаг 7. Постройте прогноз времени модели на основе тестовых данных

#Step 7: Plot modeltime forecast - this is the test data
plot_modeltime_forecast(forecast_tbl)

Прогнозируйте продажи в будущем

Если у вас есть данные временного ряда, которые являются одномерными, вы можете просто использовать функцию modeltime_forecast() и указать аргумент горизонта (h), чтобы получить прогноз на будущее, но поскольку наши данные postit имеют xregs (независимые регрессоры), мы должны создайте новый кадр данных с xregs, необходимыми для соответствия будущим значениям.

Здесь я создал новый фрейм данных для хранения наших прогнозов на будущее. Код для создания этого нового фрейма данных довольно длинный, поэтому я его здесь не привожу, но его можно найти на Github. Обратите внимание, что дата начинается с первого января 2014 года.

#Check results
str(explanatory_data)

ВНИМАНИЕ! Очень важно, чтобы данные в новом фрейме данных соответствовали точно такому же форматированию, тем же именам столбцов и относились к тем же типам объектов, что и данные, используемые при построении прогноза. Если ошибки возникают либо на этапе подбора модели, либо на этапе прогнозирования, возможной причиной могут быть данные в другом формате или имена столбцов.

Создайте прогноз на будущее.

#First, refit to the full dataset
refit_tbl <- calibration_tbl %>%
  modeltime_refit(data = postit)
#Specify the H or horizon argument to get a forecast into the future, but if using xregs (independent regressors), you must create a new tibble/data frame with the xregs to be used.
#Forecast on the new tibble data frame
forecast_tbl_future_data <- refit_tbl %>%
    modeltime_forecast(
        new_data    = explanatory_data
    )

Таблица прогнозов дает нам предсказанные значения с доверительными интервалами.

#plot forecast
plot_modeltime_forecast(forecast_tbl_future_data, .interactive = TRUE)

Как узнать, верны ли наши прогнозы?

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

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

Окончательное резюме

1. Какие факторы влияют на продажи

Цена (больше продаж по самой низкой цене. Более высокие цены сокращают продажи.)

Дисплей (больше продаж, когда продукт выставлен на витрине)

Месяц года (декабрь самый высокий. Март самый низкий).

2. Создайте модель прогноза продаж

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

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

Полный код можно найти на Github и Rpubs.

Последние мысли

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

Ссылки:

[1] Уинстон, У.Л. (2014). Маркетинговая аналитика: методы, основанные на данных, в Microsoft Excel. Уайли.

[2] Прогнозирование: принципы и практика (3-е изд.) Роб Дж. Хайндман и Джордж Атанасопулос, Университет Монаш, Австралия. https://otexts.com/fpp3/

[3] https://business-science.github.io/modeltime/

[4] https://facebook.github.io/prophet/