Cafe Sales Trend Prediction with Polynomial Regression in ML

FREE Online Courses: Knowledge Awaits – Click for Free Access!

Café managers and regional directors need to forecast the week‑over‑week percentage change in daily sales revenue—using only early‑week indicators such as prior‑week average sales, transaction volume, promotional events, and day‑of‑week mix—before finalising staffing and inventory decisions. Historical café sales exhibit nonlinear behaviour: small increases in promotion yield large sales lifts at low base levels, but plateau beyond a threshold; weekend vs. weekday mixes interact with events; and weather and holidays create synergistic effects. A simple linear model underfits these curvatures, while an unrestricted high‑degree polynomial overfits noise in week‑to‑week fluctuations. By fitting a Polynomial Regression model on engineered features with Ridge (ℓ²) regularisation, we capture smooth, interpretable sales‑trend curves and deliver accurate growth forecasts for proactive café operations planning.

Dataset

Rossmann Store Sales

Step-by-Step Code Implementation

1. Libraries Required

import pandas as pd                             # data loading & handling  
import numpy as np                              # numerical operations  

import matplotlib.pyplot as plt                 # plotting  
import seaborn as sns                           # visualization  

from sklearn.model_selection import train_test_split, GridSearchCV  
from sklearn.preprocessing import StandardScaler, PolynomialFeatures  
from sklearn.linear_model import Ridge  
from sklearn.pipeline import Pipeline  
from sklearn.metrics import mean_squared_error, r2_score

2. Load Data & Compute Weekly Metrics

import pandas as pd

# Load sales and store info
sales = pd.read_csv("data/train.csv", parse_dates=["Date"])
stores = pd.read_csv("data/store.csv")

# Filter to active days
sales = sales[sales["Open"] == 1]

# Merge store metadata
df = sales.merge(stores, on="Store", how="left")

# Compute week start
df["Week"] = df["Date"].dt.to_period("W").apply(lambda r: r.start_time)

# Aggregate to weekly level
weekly = df.groupby("Week").agg({
    "Sales": "mean",                # average daily sales
    "Customers": "mean",            # avg daily customers
    "Promo": "sum",                 # total promo days
    "StateHoliday": lambda x: (x != '0').sum()
}).rename(columns={
    "Sales": "avg_sales",
    "Customers": "avg_customers",
    "Promo": "promo_days",
    "StateHoliday": "holiday_days"
}).reset_index()

3. Feature Engineering & Target

  • Lag features (sales_prev, cust_prev, promo_prev, holiday_prev) capture momentum, customer base, promotion saturation, and holiday carryover effects.
# Sort chronologically and create lag features
weekly = weekly.sort_values("Week")
weekly["sales_prev"]     = weekly["avg_sales"].shift(1)
weekly["cust_prev"]      = weekly["avg_customers"].shift(1)
weekly["promo_prev"]     = weekly["promo_days"].shift(1)
weekly["holiday_prev"]   = weekly["holiday_days"].shift(1)
weekly.dropna(subset=["sales_prev"], inplace=True)

# Compute week‑over‑week sales growth (%)
weekly["sales_growth_pct"] = (
    (weekly["avg_sales"] - weekly["sales_prev"])
    / weekly["sales_prev"] * 100
)

# Define features and target
feature_cols = [
    "sales_prev","cust_prev","promo_prev","holiday_prev"
]
X = weekly[feature_cols]
y = weekly["sales_growth_pct"]

4. Build Polynomial Regression Pipeline

  • StandardScaler normalises each predictor, so Ridge’s ℓ² penalty treats all terms uniformly.
  • PolynomialFeatures expands inputs into squares and interactions (e.g., sales_prev², sales_prev×cust_prev, promo_prev×holiday_prev) to model nonlinear plateau and synergy effects
  • Ridge Regression (ℓ²) with hyperparameter alpha shrinks noisy high-order coefficients, controlling overfitting in the expanded feature space.
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, PolynomialFeatures
from sklearn.linear_model import Ridge

pipe = Pipeline([
    ("scale", StandardScaler()),  
    ("poly", PolynomialFeatures(include_bias=False)),  
    ("ridge", Ridge(random_state=42))  
])

5. Train/Test Split & Hyperparameter Search

GridSearchCV tunes polynomial degree (1–3) and regularisation strength α (10⁻³…10³) using 5‑fold CV, optimising RMSE on held‑out weeks.

from sklearn.model_selection import GridSearchCV

# Time‑aware split (no shuffle)
split = int(len(X) * 0.8)
X_train, X_test = X[:split], X[split:]
y_train, y_test = y[:split], y[split:]

param_grid = {
    "poly__degree": [1, 2, 3],
    "ridge__alpha": np.logspace(-3, 3, 7)
}

gs = GridSearchCV(
    pipe, param_grid,
    cv=5,
    scoring="neg_root_mean_squared_error",
    n_jobs=-1, verbose=1
)
gs.fit(X_train, y_train)

print("Best params:", gs.best_params_)

6. Evaluate Model

y_pred = gs.predict(X_test)
rmse = mean_squared_error(y_test, y_pred, squared=False)
r2   = r2_score(y_test, y_pred)

print(f"Test RMSE : {rmse:.2f}% growth")
print(f"Test R²   : {r2:.3f}")

7. Inspect Top Polynomial Coefficients

Coefficient inspection surfaces the most influential polynomial and interaction terms—providing interpretable levers (e.g., squared effect of prior sales or interaction of promotions with holidays) for strategic café operations.

poly       = gs.best_estimator_.named_steps["poly"]
feat_names = poly.get_feature_names_out(input_features=feature_cols)
coefs      = gs.best_estimator_.named_steps["ridge"].coef_

import pandas as pd
import matplotlib.pyplot as plt

coef_series = pd.Series(coefs, index=feat_names).abs().sort_values(ascending=False).head(10)

plt.figure(figsize=(8,5))
coef_series.plot(kind="barh")
plt.gca().invert_yaxis()
plt.title("Top Polynomial Features Driving Sales Growth")
plt.xlabel("Coefficient Magnitude")
plt.tight_layout()
plt.show()

Summary

This Polynomial Regression pipeline with Ridge regularisation delivers café managers:

  1. Accurate nonlinear forecasts of sales growth, capturing diminishing returns and synergy effects (low RMSE, high R²).
  2. Balanced complexity, avoiding overfitting through hyperparameter tuning.
  3. Actionable insights, with interpretable polynomial features that guide dynamic pricing, promotional timing, and staffing decisions.

Did you like our efforts? If Yes, please give ProjectGurukul 5 Stars on Google | Facebook

ProjectGurukul Team

ProjectGurukul Team specializes in creating project-based learning resources for programming, Java, Python, Android, AI, Webdevelopment and machine learning. Our mission is to help learners build practical skills through engaging, hands-on projects. We also offer free major and minor projects with source code for engineering students

Leave a Reply

Your email address will not be published. Required fields are marked *