Orbit Mall sends the same discount SMS to all its loyalty members. Rich big spenders ignore small coupons, and students who are careful with money ignore luxury offers.
The marketing team has 210 members with their age, income, a spending score from the loyalty card and how often they visit. Nobody has put them into groups yet. They want the data to find natural groups of shoppers, so each group gets its own offer.
Goal: Find groups (clusters) of similar shoppers. There is no answer column to learn from: this is unsupervised learning, and K-Means is the most common clustering method.
210 members, one row each.
| customer_id | age | annual_income_lakh | spending_score | visits_per_month |
|---|---|---|---|---|
| 101 | 21 | 6.8 | 84 | 4 |
| 102 | 18 | 23.2 | 91 | 6 |
| 103 | 40 | 25.5 | 36 | 1 |
| 104 | 31 | 6.2 | 70 | 4 |
| 105 | 43 | 24.1 | 24 | 2 |
| 106 | 36 | 5.5 | 74 | 6 |
First 6 of 210 rows · realistic practice data
Press Run on each step in order, or run them all at once. You can change any code and run it again.
Starting Python…
No column says which group a shopper belongs to. That is what makes this unsupervised.
Plot the two columns that matter most for offers. Can you see groups with your own eyes? K-Means will find them with numbers, and it can use more columns than a chart can show.
K-Means groups points by distance. Spending score goes up to 99 while income stays near 40 and visits near 12, so without scaling, spending score would decide almost everything. StandardScaler gives every column the same weight.
K-Means needs K, the number of groups, before it starts. Inertia adds up how far every shopper is from the centre of their group; smaller means tighter groups. Inertia always drops when K goes up, so look for the elbow: the K after which adding a group stops helping much.
The silhouette score asks: is each shopper much closer to their own group than to the next group? It goes from -1 to 1, and higher is better. It is a second opinion next to the elbow.
Pick K from the two checks above and fit the final model. n_init=10 runs K-Means 10 times from different random starts and keeps the best, because one bad start can give poor groups. Change K and run again to compare.
A model output like "group 3" means nothing to marketing. Compare the averages of each group and give it a name, for example "rich but careful" or "young big spenders". This profile table is the real deliverable.
A new member signs up: 27 years old, ₹6 lakh income, spending score 85, visits 6 times a month. The model puts them in the group with the nearest centre. The new data must go through the same scaler that was fitted in step 3.
20 questions on new data. You write the code; hints point the way without giving it.