← Back to Predictive Analytics

Regression — Predicting a Number

Chapter 3 — A Pipeline End to End

Regression predicts a continuous value. Here the task is to estimate each customer's lifetime sales from their behaviour — how often they order, their average discount, their typical quantity, and how long they've been active. The whole workflow is a few lines of scikit-learn, but the discipline is in how you read the result.

Fit and Score

Python · scikit-learn

from sklearn.ensemble import RandomForestRegressor
from sklearn.metrics import r2_score, mean_absolute_error

features = ["orders", "avg_discount", "avg_quantity", "tenure_days"]
X, y = cust[features], cust["total_sales"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.25, random_state=42)

model = RandomForestRegressor(n_estimators=200, random_state=42).fit(X_train, y_train)
pred = model.predict(X_test)
print(f"R^2 = {r2_score(y_test, pred):.2f}")             # 0.96
print(f"MAE = {mean_absolute_error(y_test, pred):,.0f}") # ~$1,550

On the held-out set this model scores R² ≈ 0.96 with a mean absolute error of about $1,550 — meaning it explains most of the variation in lifetime sales, and its typical miss is around $1,550. The high R² is unsurprising here: order count is a very strong predictor of total spend.

Predicted vs Actual — The Honest Picture

The most useful regression diagnostic is a predicted-vs-actual scatter. Perfect predictions land on the diagonal; the spread around it is the error. This plot shows where the model is reliable and where it drifts — far more informative than a single R² number.

Scatter of predicted versus actual customer lifetime sales, with points clustered along the diagonal of perfect prediction

Points hug the diagonal, so predictions track reality well; the spread widens for the largest customers, where data is thinner.

Which Features Drive the Prediction?

A model you can't explain is hard to trust. Feature importance ranks how much each input contributes, turning the model from a black box into an explanation. Here order count dominates — the more a customer orders, the more they spend, which matches intuition and the diagnostic findings.

Python · scikit-learn

importances = pd.Series(model.feature_importances_, index=features)
print(importances.sort_values(ascending=False))
Horizontal bar chart of feature importance, with order count by far the largest contributor

Order count is the dominant driver of predicted lifetime sales — the model's reasoning is legible.

Always Quote a Baseline

An R² or MAE means nothing without context. Compare against the simplest possible model — predicting the average for everyone. If your model's MAE isn't comfortably below that baseline's, the sophistication isn't buying anything. Reporting "R² = 0.96, versus a mean-baseline MAE of X" is honest; reporting "R² = 0.96" alone is salesmanship.

Next: Classification — Predicting a Label →

← Back to Predictive Analytics