Part 1: The Problem, the Data, and the Features
For the past several posts, we built forecasting models the classical way: exponential smoothing, ARIMA, SARIMA. Each of those methods works on a single time series at a time, trying to model how a variable evolves through trend, seasonality, and noise. That framing is clean, but it has a ceiling: it treats every series as its own isolated problem, never sharing information across different products, stores, or time patterns.
Machine learning approaches the same problem from a completely different angle. Instead of modeling the dynamics of a single series explicitly, you turn the forecasting problem into a supervised regression task. Past values, calendar features, and any other relevant signal become input variables. The model learns, from all 500 store-item combinations at once, which patterns predict future demand. More data, more signal, and a single unified model.
This post walks through the first two steps of that process: understanding the dataset and engineering the features the model will learn from. The modeling itself comes next.
The Problem
The dataset comes from a Kaggle competition: Demand Forecasting; Kernels Only (kaggle.com/c/demand-forecasting-kernels-only). The setup is straightforward. You have five years of daily sales records, 10 stores, and 50 items, and the task is to predict three months of future sales for every store-item pair. That is 500 individual time series to forecast simultaneously.
In practice, this kind of problem shows up constantly in retail and supply chains. Overstocking wastes money on storage; understocking means lost sales and frustrated customers. A model that forecasts demand accurately at the store-item level lets planners order just the right amount. The competition asks, “Can a machine learning model, trained on all pairs together, beat hand-crafted, per-series forecasts?”
The Dataset
The training data spans 2013-01-01 to 2017-12-31, giving 1826 daily observations per store-item pair. Across 10 stores and 50 items, the combined dataset has 913,000 rows and five columns: date, store, item, sales, and id. The test set covers the first three months of 2018 and provides only the date, store, and item identifiers; the sales column is what the model must predict.
The two files, train and test, are concatenated before any processing. This approach avoids shape mismatches when creating new features and ensures that any transformation applied to training data is applied identically to the test data. The risk of data leakage is low here because sales figures from the test period are genuinely absent, not hidden.
date — daily timestamp (no holidays, no closures)
store — integer ID, 1 to 10
item — integer ID, 1 to 50
sales — units sold (train only; NaN in test rows)
id — row identifier (test only; NaN in train rows)
A quick sanity check confirms the structure: 10 unique stores, 50 unique items, and exactly 50 items per store. There are no genuine missing values. The NaN entries in the sales column come entirely from the test rows, and the NaN entries in id come from the train rows. Once that is established, attention turns to the distribution of sales itself.

The distribution is right-skewed but not drastically so. Most observations cluster between 10 and 80 units, the median falls near 47, and the 99th percentile is roughly 135. There are no obvious outliers; the maximum value of 231 is plausible for a high-demand item on a busy day. This means the data is relatively clean, and no aggressive outlier handling is needed before modeling.
Exploratory Data Analysis
Before engineering any features, it helps to look at the data from a few angles: how do sales vary across stores, how does seasonality show up across months, and do some items consistently outsell others?
The heatmap below aggregates average daily sales by store and month across all five years. Two things stand out immediately. First, summer months, particularly June through August, consistently show higher sales in almost every store. Second, stores differ considerably in their volume: Store 8 averages 70+ units per day in peak months, while Stores 1 and 2 rarely exceed 30. Any useful feature will need to capture both of these axes of variation.

Looking within a single store, Store 1 below, reveals substantial variation across items as well. Some items sell three to four times more than others over the full five-year period. A model trained on all items together must therefore be able to distinguish high-volume from low-volume products, which is exactly the kind of information that store and item identifiers, once properly encoded, can provide.

Feature Engineering
Classical time series models encode temporal structure implicitly. AR terms capture autocorrelation; differencing removes trend; and seasonal parameters handle periodicity. Machine learning models, by contrast, know nothing about time unless you tell them explicitly. That is what feature engineering is for.
The raw dataset starts with just four columns: date, store, item, and sales. From the date column alone, nine new features can be extracted. Each one encodes a different temporal rhythm that might influence consumer behavior.
month — which month of the year (1–12)
day_of_month — day within the month (1–31)
day_of_year — day within the year (1–366)
week_of_year — ISO calendar week number
day_of_week — weekday index (0 = Monday, 6 = Sunday)
year — calendar year
is_wknd — 1 if Saturday or Sunday, else 0
is_month_start — 1 on the first day of the month
is_month_end — 1 on the last day of the month

The intuition behind this matters as much as the mechanics. Month captures annual seasonality; summer versus winter, for instance. Day of the week captures weekly rhythms, weekdays versus weekends. The is_wknd flag provides the model with a direct binary signal for that distinction without having to infer it from the raw integer. Meanwhile, is_month_start and is_month_end let the model detect paycheck-cycle effects, if any exist in this data.
A note on domain knowledge: the right set of calendar features depends heavily on the industry. In stationery retail, the weeks before school start matter enormously. In restaurants, Valentine’s Day or Mother’s Day drives spikes that the calendar never explicitly marks. Here, with a clean synthetic dataset and no external holiday effects, the nine date features above are a reasonable starting point, interpretable, computationally free, and directly derived from a single column.
With these features in place, the dataset is ready for modeling. Each row now carries a store identifier, an item identifier, nine temporal signals, and a sales target.

Leave a Reply