Unsupervised Machine Learning project that segments retail customers into actionable personas using RFM analysis and clustering (K-Means, Hierarchical, DBSCAN).
An e-commerce company is running the same marketing strategy for every customer β same emails, same discounts, same ads β regardless of whether the customer is a high-spending loyalist or someone who hasn't ordered in months. This is expensive and ineffective.
Goal: Use unsupervised machine learning to segment the customer base into a small number of statistically distinct, business-interpretable groups based on income, spending behavior, purchase frequency, and recency β so marketing can design a tailored strategy per segment instead of one blurry strategy for everyone.
This project covers the full data science lifecycle: data sourcing, cleaning, EDA, feature engineering (RFM), clustering, model comparison, evaluation, business storytelling, and an interactive dashboard.
---
This project uses a hybrid real + engineered dataset, which is disclosed transparently below.
Real data (from Kaggle): Mall Customer Segmentation Data
by vjchoudhary7 β one of the most widely used public customer-segmentation datasets. It provides
200 real customer records with CustomerID, Gender, Age, Annual Income, and Spending Score.
A local copy is stored at data/raw/Mall\_Customers.csv.
Why augment it: The real Kaggle file has no transaction history (no order dates, no region,
no category data), so it cannot support RFM analysis or a richer segmentation on its own, and at
200 rows it's small for a robust clustering demo. src/build\_dataset.py expands the 200 real
rows to 1,200 (resampling + small realistic jitter that preserves the original distribution)
and adds behavioral columns that are simulated conditionally on each customer's real Spending
Score / Income β not independent random noise β so the added behavior stays statistically
consistent with real signal. The full logic is documented in that file.
| Column | Source | Description |
|---|---|---|
CustomerID |
Real (Kaggle) | Unique customer identifier |
Age |
Real (Kaggle, jittered) | Customer age |
Gender |
Real (Kaggle) | Male / Female |
AnnualIncome\_INR\_K |
Real (Kaggle, jittered) | Annual income, thousands |
SpendingScore |
Real (Kaggle, jittered) | Store-assigned spending score (1-100) |
City |
Engineered | Simulated region across 10 major Indian cities |
PurchaseFrequency |
Engineered | Orders/year, conditional on Spending Score |
Recency\_Days |
Engineered | Days since last order, conditional on Spending Score |
Tenure\_Months |
Engineered | Months as a customer, conditional on Spending Score |
ProductCategoryPreference |
Engineered | Preferred product category |
AvgOrderValue\_INR |
Engineered | Derived from income + spending score |
MonetaryValue\_INR |
Engineered | Total spend, used as the "M" in RFM |
SatisfactionScore |
Engineered | 1-5 satisfaction rating, conditional on Spending Score |
Rows: 1,200 Β· Columns: 13 Β· Includes realistic missing values (~2%) and outliers, same as you'd find in a real CRM export.
Want to regenerate it? Run
python src/build\_dataset.py.
---
| Category | Tools |
|---|---|
| Language | Python 3.10+ |
| Data handling | pandas, NumPy |
| Visualization | matplotlib, seaborn, Plotly |
| Machine Learning | scikit-learn (K-Means, Agglomerative Clustering, DBSCAN, PCA) |
| Dashboard | Streamlit |
| Notebook | Jupyter |
| Reporting | Markdown / PDF executive summary |
---
- Data Sourcing β Load real Kaggle base data, expand + enrich into the working dataset (
src/build\_dataset.py). - Data Cleaning β Handle missing values (median/mode imputation), cap outliers (IQR method).
- EDA β Univariate & bivariate visualizations, correlation heatmap, pairplots, insight write-ups.
- Feature Engineering β RFM (Recency, Frequency, Monetary) scoring, categorical encoding,
StandardScalerfeature scaling. - Optimal k Selection β Elbow method (inertia) + Silhouette score across k=2 to 10.
- Clustering β K-Means, Hierarchical (Ward linkage), and DBSCAN, compared head-to-head.
- Dimensionality Reduction β PCA to 2D/3D for visualization.
- Cluster Profiling β Named, business-interpretable personas with average-behavior tables.
- Model Evaluation β Silhouette Score, Davies-Bouldin Index, cluster stability check across resamples.
- Dashboard β Interactive Streamlit app with filters, KPIs, and segment visualizations.
---
---
- 4 clean, stable customer segments were found: Premium Spenders (21%), Steady Mature Regulars (24%), New Bargain Hunters (28%), and At-Risk Customers (27%).
- K-Means (k=4) was selected as the production model β it matched Hierarchical clustering's structure closely (validating the segments are real) and produced clean, balanced, business-usable groups, unlike DBSCAN, which fragmented the data into one dominant cluster plus many tiny outlier groups despite a higher raw silhouette score.
- At-Risk Customers have relatively high income but the lowest spending score and highest recency (~120 days since last order) β a high-value win-back opportunity, since low income isn't the barrier.
- Cluster stability check (10 reruns on 80% resamples) showed low variance in silhouette score, confirming the segments are robust and not a one-off artifact.
- Business impact: replacing one blanket marketing strategy with four targeted ones (VIP tier, cross-sell nudges, price-sensitive promos, and a win-back campaign) directly targets retention and revenue growth on the highest-opportunity segments.
Full recommendations per segment are in the notebook (Section 15) and reports/executive\_summary.md / .pdf.
---
git clone <your-repo-url>
cd customer-segmentation
pip install -r requirements.txtpython src/build\_dataset.pyjupyter notebook notebooks/Customer\_Segmentation\_Analysis.ipynbpython src/generate\_images.pystreamlit run app.py---
customer-segmentation/
β
βββ data/
β βββ raw/
β β βββ Mall\_Customers.csv # Real Kaggle source data (200 rows)
β βββ customer\_data.csv # Final working dataset (1,200 rows, real + engineered)
β βββ customer\_data\_with\_segments.csv # Output: customers labeled with their cluster/segment
β βββ rfm\_table.csv # RFM scores per customer
β βββ cluster\_profile.csv # Avg behavior per cluster
β βββ algorithm\_comparison.csv # K-Means vs Hierarchical vs DBSCAN metrics
β
βββ notebooks/
β βββ Customer\_Segmentation\_Analysis.ipynb # Full, commented, story-driven analysis
β
βββ src/
β βββ build\_dataset.py # Loads real Kaggle data + builds the enriched working dataset
β βββ preprocessing.py # Cleaning, RFM, encoding, scaling utilities
β βββ clustering.py # K-Means / Hierarchical / DBSCAN / PCA / evaluation utilities
β βββ generate\_images.py # Reproduces every chart used in this README/report
β
βββ reports/
β βββ executive\_summary.md # Business-facing summary (source)
β βββ executive\_summary.pdf # Business-facing summary (client-ready PDF)
β
βββ images/ # All generated charts (EDA, clustering, profiling)
β
βββ app.py # Streamlit interactive dashboard
βββ requirements.txt
βββ README.md
---
- Swap the engineered behavioral columns for real transaction-level data (order history, timestamps) if/when available, to remove the simulation layer entirely.
- Add a supervised "next best action" model on top of segments (e.g. predict churn probability within the At-Risk segment).
- Track segment migration over time (cohort analysis) to measure whether marketing interventions actually move customers into higher-value segments.
- Deploy the Streamlit dashboard (Streamlit Community Cloud / Docker + cloud hosting) for live stakeholder access.
- Experiment with Gaussian Mixture Models and HDBSCAN as additional clustering baselines.
- Automate the pipeline (Airflow/Prefect) to re-segment customers on a recurring schedule as new data arrives.
---
Harshit Fartiyal
π§ Email: fartiyalharshit41@gmail.com
π LinkedIn: LinkedIn Profile
π» GitHub: Harshit06
This project was built as part of an internship/portfolio submission to demonstrate an end-to-end unsupervised machine learning workflow β from raw data to a business-ready dashboard.
---
This project is released under the MIT License β free to use, modify, and learn from.




