Бөлісу құралы:


Разработка, оценка и присвоение оценки модели прогнозирования по продажам супермаркета

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

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

В этом руководстве рассматриваются следующие действия.

  • Загрузка данных
  • Использование анализа аналитических данных для понимания и обработки данных
  • Обучение модели машинного обучения с помощью пакета программного обеспечения с открытым исходным кодом и отслеживание экспериментов с помощью MLflow и функции автологирования Fabric
  • Сохранение конечной модели машинного обучения и прогнозирование
  • Отображение производительности модели с помощью визуализаций Power BI

Необходимые условия

  • Получите подписку Microsoft Fabric. Или зарегистрируйте бесплатную пробную Microsoft Fabric.

  • Войдите в Microsoft Fabric.

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

    снимок экрана меню переключателя режимов, в котором показано, где выбрать Data Science.

Следуйте инструкциям в записной книжке

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

  • Откройте и запустите встроенную записную книжку в интерфейсе Обработки и анализа данных Synapse
  • Отправка записной книжки из GitHub в интерфейс Обработки и анализа данных Synapse

Открытие встроенной записной книжки

Пример записной книжки для прогнозирования продаж сопровождает это руководство.

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

  2. Перед началом выполнения кода обязательно подключите lakehouse к записной книжке.

Импорт записной книжки из GitHub

Записная книжка AIsample — Superstore Forecast.ipynb идет в комплекте с этим руководством.

Шаг 1. Загрузка данных

Набор данных содержит 9995 экземпляров продаж различных продуктов. Он также включает 21 атрибутов. Эта таблица находится в файле Superstore.xlsx, используемом в этой записной книжке:

Идентификатор строки Идентификатор заказа Дата заказа Дата отправки Режим доставки Идентификатор клиента Имя клиента Сегмент Страна Город Государство Почтовый индекс Область Идентификатор продукта Категория Sub-Category Название продукта Продажи Количество Скидка Прибыль
4 US-2015-108966 2015-10-11 2015-10-18 Стандартный класс SO-20335 Шон О'Доннелл Потребитель США Форт Лодердейл Флорида 33311 Юг FUR-TA-10000577 Мебель Таблицы Стол серии Bretford CR4500, тонкий прямоугольный стол. 957,5775 5 0.45 -383.0310
11 CA-2014-115812 2014-06-09 2014-06-09 Стандартный класс Стандартный класс Brosina Хоффман Потребитель США Лос-Анджелес Калифорния 90032 Запад FUR-TA-10001539 Мебель Таблицы Столы для конференций Chromcraft прямоугольной формы 1706.184 9 0.2 85.3092
31 US-2015-150630 2015-09-17 2015-09-21 Стандартный класс ТБ-21520 Трейси Блюмштейн Потребитель США Филадельфия Пенсильвания 19140 Восток OFF-EN-10001509 Канцелярские товары Конверты Пластиковые конверты с завязками на веревочках 3,264 2 0.2 1.1016

Определите эти параметры, чтобы использовать эту записную книжку с различными наборами данных:

IS_CUSTOM_DATA = False  # If TRUE, the dataset has to be uploaded manually

IS_SAMPLE = False  # If TRUE, use only rows of data for training; otherwise, use all data
SAMPLE_ROWS = 5000  # If IS_SAMPLE is True, use only this number of rows for training

DATA_ROOT = "/lakehouse/default"
DATA_FOLDER = "Files/salesforecast"  # Folder with data files
DATA_FILE = "Superstore.xlsx"  # Data file name

EXPERIMENT_NAME = "aisample-superstore-forecast"  # MLflow experiment name

Скачайте набор данных и отправьте его в lakehouse

Этот код загружает общедоступную версию набора данных, а затем сохраняет ее в озере данных Fabric.

Важный

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

import os, requests
if not IS_CUSTOM_DATA:
    # Download data files into the lakehouse if they're not already there
    remote_url = "https://synapseaisolutionsa.blob.core.windows.net/public/Forecast_Superstore_Sales"
    file_list = ["Superstore.xlsx"]
    download_path = "/lakehouse/default/Files/salesforecast/raw"

    if not os.path.exists("/lakehouse/default"):
        raise FileNotFoundError(
            "Default lakehouse not found, please add a lakehouse and restart the session."
        )
    os.makedirs(download_path, exist_ok=True)
    for fname in file_list:
        if not os.path.exists(f"{download_path}/{fname}"):
            r = requests.get(f"{remote_url}/{fname}", timeout=30)
            with open(f"{download_path}/{fname}", "wb") as f:
                f.write(r.content)
    print("Downloaded demo data files into lakehouse.")

Настройка отслеживания экспериментов MLflow

Microsoft Fabric автоматически фиксирует значения входных параметров и выходных метрик модели машинного обучения при обучении. Это расширяет возможности автологирования MLflow. Затем данные записываются в рабочую область, где можно получить доступ и визуализировать его с помощью API MLflow или соответствующего эксперимента в рабочей области. Дополнительные сведения об автологировании см. в статье Автологирование в Microsoft Fabric.

Чтобы отключить автоматическую запись Microsoft Fabric в сеансе записной книжки, вызовите mlflow.autolog() и задайте disable=True:

# Set up MLflow for experiment tracking
import mlflow

mlflow.set_experiment(EXPERIMENT_NAME)
mlflow.autolog(disable=True)  # Turn off MLflow autologging

Чтение необработанных данных из lakehouse

Чтение необработанных данных из раздела "Файлы " хранилища. Добавьте дополнительные столбцы для разных частей дат. Те же сведения используются для создания секционированных разностных таблиц. Так как необработанные данные хранятся в виде файла Excel, необходимо использовать pandas для его чтения:

import pandas as pd
df = pd.read_excel("/lakehouse/default/Files/salesforecast/raw/Superstore.xlsx")

Шаг 2. Выполнение анализа аналитических данных

Импорт библиотек

Перед любым анализом импортируйте необходимые библиотеки:

# Importing required libraries
import warnings
import itertools
import numpy as np
import matplotlib.pyplot as plt
warnings.filterwarnings("ignore")
plt.style.use('fivethirtyeight')
import pandas as pd
import statsmodels.api as sm
import matplotlib
matplotlib.rcParams['axes.labelsize'] = 14
matplotlib.rcParams['xtick.labelsize'] = 12
matplotlib.rcParams['ytick.labelsize'] = 12
matplotlib.rcParams['text.color'] = 'k'
from sklearn.metrics import mean_squared_error,mean_absolute_percentage_error

Отображение необработанных данных

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

display(df)

В этом документе основная задача заключается в прогнозировании продаж категории Furniture. Это ускоряет вычисление и помогает показать производительность модели. Однако эта записная книжка использует адаптируемые методы. Эти методы можно расширить для прогнозирования продаж других категорий продуктов.

# Select "Furniture" as the product category
furniture = df.loc[df['Category'] == 'Furniture']
print(furniture['Order Date'].min(), furniture['Order Date'].max())

Предварительная обработка данных

Реальные бизнес-сценарии часто требуют прогнозирования продаж в трех разных категориях:

  • Определенная категория продукта
  • Определенная категория клиента
  • Определенная комбинация категории продуктов и категории клиентов

Сначала удалите ненужные столбцы для предварительной обработки данных. Некоторые столбцы (Row ID, Order ID,Customer IDи Customer Name) являются ненужными, так как они не влияют. Мы хотим прогнозировать общий объем продаж по всему штату и региону для определенной категории продуктов (Furniture), чтобы мы могли удалить столбцы State, Region, Country, Cityи Postal Code. Чтобы прогнозировать продажи для определенного расположения или категории, может потребоваться соответствующим образом настроить этап предварительной обработки.

# Data preprocessing
cols = ['Row ID', 'Order ID', 'Ship Date', 'Ship Mode', 'Customer ID', 'Customer Name', 
'Segment', 'Country', 'City', 'State', 'Postal Code', 'Region', 'Product ID', 'Category', 
'Sub-Category', 'Product Name', 'Quantity', 'Discount', 'Profit']
# Drop unnecessary columns
furniture.drop(cols, axis=1, inplace=True)
furniture = furniture.sort_values('Order Date')
furniture.isnull().sum()

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

Сначала сгруппируйте категорию Furniture по Order Date. Затем вычислите сумму столбца Sales для каждой группы, чтобы определить общее количество продаж для каждого уникального значения Order Date. Переобразуйте столбец Sales с частотой MS для агрегации данных по месяцам. Наконец, вычислите среднее значение продаж за каждый месяц.

# Data preparation
furniture = furniture.groupby('Order Date')['Sales'].sum().reset_index()
furniture = furniture.set_index('Order Date')
furniture.index
y = furniture['Sales'].resample('MS').mean()
y = y.reset_index()
y['Order Date'] = pd.to_datetime(y['Order Date'])
y['Order Date'] = [i+pd.DateOffset(months=67) for i in y['Order Date']]
y = y.set_index(['Order Date'])
maximim_date = y.reset_index()['Order Date'].max()

Продемонстрировать влияние Order Date на Sales для категории Furniture:

# Impact of order date on the sales
y.plot(figsize=(12, 3))
plt.show()

Перед любым статистическим анализом необходимо импортировать модуль Python statsmodels. Он предоставляет классы и функции для оценки многих статистических моделей. Он также предоставляет классы и функции для проведения статистических тестов и статистического исследования данных.

import statsmodels.api as sm

Выполнение статистического анализа

Временный ряд отслеживает эти элементы данных с заданными интервалами, чтобы определить вариант этих элементов в шаблоне временных рядов:

  • уровень: фундаментальный компонент, представляющий среднее значение для определенного периода времени

  • тренд: описывает, уменьшается ли временный ряд, остается ли константой или увеличивается с течением времени.

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

  • шум/остаточный: относится к случайным колебаниям и изменчивости в данных временных рядов, которые модель не может объяснить.

В этом коде вы увидите эти элементы для набора данных после предварительной обработки:

# Decompose the time series into its components by using statsmodels
result = sm.tsa.seasonal_decompose(y, model='additive')

# Labels and corresponding data for plotting
components = [('Seasonality', result.seasonal),
              ('Trend', result.trend),
              ('Residual', result.resid),
              ('Observed Data', y)]

# Create subplots in a grid
fig, axes = plt.subplots(nrows=4, ncols=1, figsize=(12, 7))
plt.subplots_adjust(hspace=0.8)  # Adjust vertical space
axes = axes.ravel()

# Plot the components
for ax, (label, data) in zip(axes, components):
    ax.plot(data, label=label, color='blue' if label != 'Observed Data' else 'purple')
    ax.set_xlabel('Time')
    ax.set_ylabel(label)
    ax.set_xlabel('Time', fontsize=10)
    ax.set_ylabel(label, fontsize=10)
    ax.legend(fontsize=10)

plt.show()

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

Шаг 3. Обучение и отслеживание модели

Теперь, когда у вас есть доступные данные, определите модель прогнозирования. В этом ноутбуке примените модель прогнозирования, называемую сезонной авторегрессионной интегрированной скользящей среднею с экзогенными факторами (SARIMAX). SARIMAX объединяет авторегрессионные (AR) и скользящее среднее (MA) компоненты, сезонное дифференцирование и внешние предикторы, чтобы сделать точные и гибкие прогнозы для временных рядов.

Для отслеживания экспериментов также используется автологирование MLflow и Fabric. Здесь загрузите дельта-таблицу из lakehouse. Вы можете использовать другие разностные таблицы, которые рассматривают lakehouse в качестве источника.

# Import required libraries for model evaluation
from sklearn.metrics import mean_squared_error, mean_absolute_percentage_error

Настройка гиперпараметров

SARIMAX учитывает параметры, используемые в регулярной авторегрессионной интегрированной модели скользящего среднего (ARIMA) (p, d, q), и добавляет параметры сезонности (P, D, Q, s). Эти аргументы модели SARIMAX называются порядка (p, d, q) и сезонных (P, D, Q, sсоответственно). Поэтому для обучения модели необходимо сначала настроить семь параметров.

Параметры заказа:

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

    Как правило, этот параметр должен быть неотрицательное целое число. Общие значения находятся в диапазоне 0 до 3, хотя более высокие значения возможны в зависимости от конкретных характеристик данных. Более высокое значение p указывает на длинную память прошлых значений в модели.

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

    Этот параметр должен быть неотрицательное целое число. Общие значения находятся в диапазоне 0 до 2. Значение d0 означает, что временной ряд уже является стационарным. Более высокие значения указывают количество разных операций, необходимых для того, чтобы сделать его стационарным.

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

    Этот параметр должен быть неотрицательное целое число. Общие значения находятся в диапазоне 0 до 3, но для определенных временных рядов могут потребоваться более высокие значения. Более высокое значение q указывает на более сильную зависимость от прошлых ошибок для прогнозирования.

Параметры сезонного заказа:

  • P: сезонный порядок компонента AR, аналогичный p, но для сезонной части
  • D: сезонный порядок дифференцирования, аналогичный d, но применяемый для сезонной части
  • Q: сезонный порядок компонента MA, аналогичный q, но для сезонной части
  • s: количество шагов времени на сезонный цикл (например, 12 для ежемесячных данных с ежегодной сезонностью)
# Hyperparameter tuning
p = d = q = range(0, 2)
pdq = list(itertools.product(p, d, q))
seasonal_pdq = [(x[0], x[1], x[2], 12) for x in list(itertools.product(p, d, q))]
print('Examples of parameter combinations for Seasonal ARIMA...')
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[1]))
print('SARIMAX: {} x {}'.format(pdq[1], seasonal_pdq[2]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[3]))
print('SARIMAX: {} x {}'.format(pdq[2], seasonal_pdq[4]))

SARIMAX имеет другие параметры:

  • enforce_stationarity: Нужно ли применять стационарность к данным временных рядов, прежде чем использовать модель SARIMAX.

    Если для enforce_stationarity задано значение True (по умолчанию), это указывает, что модель SARIMAX должна применять стационарность к данным временных рядов. Затем модель SARIMAX автоматически применяет разности к данным, чтобы сделать их стационарными, как указано в порядках d и D, до подгонки модели. Это распространенная практика, так как многие модели временных рядов, включая SARIMAX, предполагают, что данные являются стационарными.

    Для нестационарных временных рядов (например, если они демонстрируют тенденции или сезонность), рекомендуется установить enforce_stationarity в Trueи позволить модели SARIMAX выполнять дифференцирование для достижения стационарности. Для стационных временных рядов (например, один без тенденций или сезонности), задайте enforce_stationarityFalse, чтобы избежать ненужных отличий.

  • enforce_invertibility: определяет, должна ли модель применять обратимость для оцененных параметров во время процесса оптимизации.

    Если для enforce_invertibility задано значение True (по умолчанию), это означает, что модель SARIMAX должна принудительно применять обратимость для предполагаемых параметров. Инвертируемость гарантирует, что модель хорошо определена, и что оцененные коэффициенты AR и MA находятся в пределах диапазона стационарности.

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

По умолчанию используется модель AR(1). Это относится к (1, 0, 0). Обычной практикой является пробовать различные сочетания параметров порядка и сезонных параметров порядка и оценивать производительность модели для набора данных. Соответствующие значения могут отличаться от одного временных рядов к другому.

Определение оптимальных значений часто включает анализ функции автозамены (ACF) и частичной функции автозамены (PACF) данных временных рядов. Он также часто включает в себя использование критериев выбора модели, например критерия информации Akaike (AIC) или критерия информации Байеса (BIC).

Настройте гиперпараметры:

# Tune the hyperparameters to determine the best model
for param in pdq:
    for param_seasonal in seasonal_pdq:
        try:
            mod = sm.tsa.statespace.SARIMAX(y,
                                            order=param,
                                            seasonal_order=param_seasonal,
                                            enforce_stationarity=False,
                                            enforce_invertibility=False)
            results = mod.fit(disp=False)
            print('ARIMA{}x{}12 - AIC:{}'.format(param, param_seasonal, results.aic))
        except:
            continue

После оценки предыдущих результатов можно определить значения для параметров заказа и сезонных параметров заказа. Выбор — это order=(0, 1, 1) и seasonal_order=(0, 1, 1, 12), которые предлагают самый низкий AIC (например, 279,58). Используйте эти значения для обучения модели.

Обучение модели

# Model training 
mod = sm.tsa.statespace.SARIMAX(y,
                                order=(0, 1, 1),
                                seasonal_order=(0, 1, 1, 12),
                                enforce_stationarity=False,
                                enforce_invertibility=False)
results = mod.fit(disp=False)
print(results.summary().tables[1])

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

# Plot the forecasting results
pred = results.get_prediction(start=maximim_date, end=maximim_date+pd.DateOffset(months=6), dynamic=False) # Forecast for the next 6 months (months=6)
pred_ci = pred.conf_int() # Extract the confidence intervals for the predictions
ax = y['2019':].plot(label='observed')
pred.predicted_mean.plot(ax=ax, label='One-step ahead forecast', alpha=.7, figsize=(12, 7))
ax.fill_between(pred_ci.index,
                pred_ci.iloc[:, 0],
                pred_ci.iloc[:, 1], color='k', alpha=.2)
ax.set_xlabel('Date')
ax.set_ylabel('Furniture Sales')
plt.legend()
plt.show()
# Validate the forecasted result
predictions = results.get_prediction(start=maximim_date-pd.DateOffset(months=6-1), dynamic=False)
# Forecast on the unseen future data
predictions_future = results.get_prediction(start=maximim_date+ pd.DateOffset(months=1),end=maximim_date+ pd.DateOffset(months=6),dynamic=False)

Используйте predictions для оценки производительности модели, сравнивая с фактическими значениями. Значение predictions_future указывает на будущее прогнозирование.

# Log the model and parameters
model_name = f"{EXPERIMENT_NAME}-Sarimax"
with mlflow.start_run(run_name="Sarimax") as run:
    mlflow.statsmodels.log_model(results,model_name,registered_model_name=model_name)
    mlflow.log_params({"order":(0,1,1),"seasonal_order":(0, 1, 1, 12),'enforce_stationarity':False,'enforce_invertibility':False})
    model_uri = f"runs:/{run.info.run_id}/{model_name}"
    print("Model saved in run %s" % run.info.run_id)
    print(f"Model URI: {model_uri}")
mlflow.end_run()
# Load the saved model
loaded_model = mlflow.statsmodels.load_model(model_uri)

Шаг 4. Оценка модели и сохранение прогнозов

Интеграция фактических значений с прогнозируемыми значениями для создания отчета Power BI. Сохраните эти результаты в таблице в лейкхаусе.

# Data preparation for Power BI visualization
Future = pd.DataFrame(predictions_future.predicted_mean).reset_index()
Future.columns = ['Date','Forecasted_Sales']
Future['Actual_Sales'] = np.NAN
Actual = pd.DataFrame(predictions.predicted_mean).reset_index()
Actual.columns = ['Date','Forecasted_Sales']
y_truth = y['2023-02-01':]
Actual['Actual_Sales'] = y_truth.values
final_data = pd.concat([Actual,Future])
# Calculate the mean absolute percentage error (MAPE) between 'Actual_Sales' and 'Forecasted_Sales' 
final_data['MAPE'] = mean_absolute_percentage_error(Actual['Actual_Sales'], Actual['Forecasted_Sales']) * 100
final_data['Category'] = "Furniture"
final_data[final_data['Actual_Sales'].isnull()]
input_df = y.reset_index()
input_df.rename(columns = {'Order Date':'Date','Sales':'Actual_Sales'}, inplace=True)
input_df['Category'] = 'Furniture'
input_df['MAPE'] = np.NAN
input_df['Forecasted_Sales'] = np.NAN
# Write back the results into the lakehouse
final_data_2 = pd.concat([input_df,final_data[final_data['Actual_Sales'].isnull()]])
table_name = "Demand_Forecast_New_1"
spark.createDataFrame(final_data_2).write.mode("overwrite").format("delta").save(f"Tables/{table_name}")
print(f"Spark DataFrame saved to delta table: {table_name}")

Шаг 5. Визуализация в Power BI

В отчете Power BI показана средняя абсолютная процентная ошибка (MAPE) 16,58. Метрика MAPE определяет точность метода прогнозирования. Он представляет точность прогнозируемых значений в сравнении с фактическими значениями.

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

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

снимок экрана отчета Power BI.

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