Statistical machine learning on the daily sales of a retail chain (750 markets in France, Italy and Spain, 2021–2022). The project (1) quantifies the effect of each market characteristic on sales with a linear model, and (2) compares the regression models of the course (linear, shrinkage, PCR/PLS, polynomial, GAM, trees, random forest, gradient boosting, SVR, neural network) to choose the most profitable MINI, SUPER and HYPER market to open in 2024.
Revisited version (2026). This version of the project was revisited with the help of Claude Opus 5.5 (Anthropic): the notebook was fixed so that it runs again with current libraries, several methodological issues were corrected, the figures and explanations were improved, and a LaTeX report was added. The original university version is kept unchanged in
archive/v1_original/.
- Aurélien Pardo · ORCID 0009-0006-1533-9383 · LinkedIn
- Julien Ducrey · LinkedIn · GitHub
| Path | Description |
|---|---|
Project_Statistical_Machine_Learning.ipynb |
Revisited notebook (v2): cleaning, exploration, Objective 1, Objective 2, decision |
report/report.pdf |
Companion report written in LaTeX (source: report/report.tex) |
report/figures/, report/tables/ |
Figures and tables exported by the notebook and used by the report |
sales.csv |
Daily sales per market (market_id, date, is_open, sales_amount) |
market.csv |
Market characteristics (country, market_type, square_feet, avg_customers, competitor_distance, has_promotions) |
archive/v1_original/ |
Original notebook and README (v1) |
requirements.txt |
Python dependencies |
- Data cleaning. Empty columns, missing rows, a typo in
is_open, sentinel values (-999999,9999999,-9999) and missing market types are detected and fixed. Every action is recorded in a cleaning log. - Temporal dimension. Trend, seasonality and weekday effects are checked before collapsing the dates. The only strong weekly pattern is that markets close on Mondays.
- Datasets.
merged_df(daily rows joined with market characteristics) andmarket_df(one row per market, target = average daily sales on open days). The within-market daily noise sets an irreducible error floor. - Exploration. Distributions, relationships within each market type, country effects, collinearity, outliers.
- Objective 1. OLS with coefficients in original units ("+1 customer → +X sales"), cluster-robust standard errors, VIF, diagnostics, best subset selection, PCR/PLS and Lasso path.
- Objective 2. Nested, repeated cross-validation by market of 14 models. The best model is the simplest one within one standard error of the lowest RMSE. It is then used to rank the 9 candidate markets.
- Irreducible error. Day-to-day fluctuations around each market's average cannot be predicted from market characteristics: on daily rows the MSE cannot go below ≈ 2.45 M (maximum R² = 0.990).
- Objective 1. The additive OLS reaches R² = 0.988. All else being equal, +1 average daily customer adds ≈ 3 to the daily sales and +1 km to the nearest competitor removes ≈ 32; a SUPER sells ≈ 11.5k more than a comparable MINI and a HYPER ≈ 44k more; Italy and Spain sell ≈ 2,000 and ≈ 900 less than France. The effects are in fact multiplicative: a log-linear model gives percentage effects (Italy −9 %, Spain −4.5 %, SUPER ×2, HYPER ×4.5) and is ≈ 6 times more accurate on unseen markets.
- Objective 2. Among 15 models compared by nested cross-validation by market, the best is the log-linear OLS (RMSE ≈ 108 on average daily sales), ahead of SVR, polynomial regression, a neural network and tree ensembles.
- Decision. Open MINI-FR, SUPER-FR and HYPER-FR. All models agree, and the margins are 6 to 35 times the model error.
- The notebook runs again from start to finish (missing
df_encoded.csv, pandas 3 / NumPy 2 / scikit-learn 1.9 compatibility). - Date checks use parsed dates instead of string comparisons; hard-coded row indices are replaced by boolean masks.
- Encoding: reference categories for country and market type (the v1 encoding fell into the dummy variable trap).
- Objective 1: coefficients per unit of each predictor (v1 used MinMax-scaled data), with cluster-robust standard errors.
- Validation by market instead of random daily rows: v1 scores were inflated by leakage, because the same market appeared in both training and validation folds.
- Ridge/Lasso/GAM tuning fixed, SVR now trained, neural network training stabilised (standardised target, shuffled batches, early stopping).
- Candidate markets are preprocessed with the training transformations (v1 refitted a scaler on the 9 candidates).
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt
jupyter nbconvert --to notebook --execute --inplace Project_Statistical_Machine_Learning.ipynb
cd report && latexmk -pdf report.texThe full notebook runs in a few minutes on a laptop.