A retail company wants to predict customer purchases from historical sales. Explore the data, predict a customer live, then compare five machine-learning models on accuracy, precision, recall and F1 โ and recommend the best one.
There's no single "run the model" step. Real projects follow a pipeline โ and most of the value is in framing and features, not the algorithm.
A logistic-regression model trained on RFM features. Move the sliders to describe a customer; the dot moves through the cloud of past customers (green = bought again, red = didn't), the dashed line is the model's decision boundary, and the gauge shows the predicted probability.
The heart of the experiment: train several classifiers and compare. Pick a metric โ the bars re-sort and the leader gets the gold bar and a Recommended tag. Notice the winner can change with the metric.
Every prediction lands in one of four boxes. The two green boxes are correct; the two red boxes are the two kinds of mistake.
(TP+TN)/all. Overall correctness. Misleading when classes are imbalanced.TP/(TP+FP). Of those predicted to buy, how many actually did. Matters when false alarms are costly.TP/(TP+FN). Of the real buyers, how many we caught. Matters when missing a buyer is costly.Two clear explainers from StatQuest with Josh Starmer on how we judge and compare classification models.
Videos are embedded from YouTube and belong to their creators. If a frame is blank, your network may block YouTube โ search the titles on youtube.com.
Build RFM features, then loop over several models and compare them with a single, clean evaluation.
import pandas as pd
tx = pd.read_csv("online_retail.csv", parse_dates=["InvoiceDate"])
ref = tx["InvoiceDate"].max()
# Build RFM features per customer
rfm = tx.groupby("CustomerID").agg(
Recency = ("InvoiceDate", lambda d: (ref - d.max()).days),
Frequency = ("InvoiceNo", "nunique"),
Monetary = ("Amount", "sum"),
).reset_index()
# Target: did the customer buy in the next period? (1/0)
rfm["WillBuy"] = (rfm["Recency"] < 60).astype(int) # example label
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.neighbors import KNeighborsClassifier
from sklearn.naive_bayes import GaussianNB
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
X = rfm[["Recency","Frequency","Monetary"]]; y = rfm["WillBuy"]
X = StandardScaler().fit_transform(X)
X_tr,X_te,y_tr,y_te = train_test_split(X,y,test_size=0.25,random_state=1)
models = {
"Logistic Regression": LogisticRegression(),
"KNN": KNeighborsClassifier(),
"Naive Bayes": GaussianNB(),
"Decision Tree": DecisionTreeClassifier(max_depth=5),
"Random Forest": RandomForestClassifier(n_estimators=200),
}
for name, m in models.items():
m.fit(X_tr, y_tr); p = m.predict(X_te)
print(f"{name:20s}",
"acc", round(accuracy_score(y_te,p),3),
"prec", round(precision_score(y_te,p),3),
"rec", round(recall_score(y_te,p),3),
"f1", round(f1_score(y_te,p),3))
# Robust comparison with cross-validation, then recommend
for name, m in models.items():
scores = cross_val_score(m, X, y, cv=5, scoring="f1")
print(name, "mean F1:", scores.mean().round(3))
# Recommendation: choose the model with the best F1 that meets
# the business need (precision for budgeted campaigns,
# recall for retention). Random Forest is a strong default.
Historical sales were transformed into RFM features and used to train five classifiers. The models were compared on accuracy, precision, recall and F1. The ensemble (Random Forest) gave the best overall balance and is recommended, while the choice can shift toward precision- or recall-focused models depending on the campaign goal โ demonstrating CO1.