Contents/ Part XXXI · Capstone Projects: Machine Learning/ Chapter 193

Gradient Boosting for Tabular Regression

Capstone 31. Four engineered features were worth 101 seconds of accuracy. Changing model family was worth 17. Twenty configurations of hyperparameter search were worth four. And the number the customer should see is not the prediction.

⏱️ ~23 min read
🎯 Tabular regression
📊 Chapter 193

Most of the effort in a tabular modeling project goes into the model. This chapter measures what each decision was actually worth, in seconds, and the ordering is close to the reverse of the usual one.

The brief
Setting
Eighty-four days of food delivery orders from one city zone: 41,410 usable orders with distance, hour, items, weather, traffic, courier supply and the restaurant, plus the minutes from order placed to delivered.
The question
What arrival time should the app display when the order is placed? Not what the delivery will take. What number to promise.
Why it matters
Arriving late is roughly three times as costly as arriving early, and the service target is that no more than 15 percent of orders arrive after the displayed time. The platform currently shows the prediction plus a flat 8 minutes, and nobody remembers who chose 8.
What we do
Split by time, beat a linear baseline, price feature engineering against model family against hyperparameter search, read the learning curve to decide whether more data would help, find where the model is wrong, and then work out what to display.
A conditional mean is the best guess at the middle of the distribution, so roughly half of all orders arrive after it. With asymmetric costs the right quantity to display is a quantile, and which quantile follows from the cost ratio.
The finding, up front

Four engineered features removed 101 seconds of error, switching from linear regression to gradient boosting removed 17, and twenty configurations of hyperparameter search removed four. Then a conditional quantile and a flat buffer with the same average padding produced the same overall late rate and late rates that ranged over 22 points against 3 across ordinary operating conditions.

1

The Baseline, and a Split That Respects Time

After removing a duplicated export block, 384 cancellations recorded as a delivery time of zero and 211 orders with a GPS distance of 999 kilometers, 41,410 orders remain. Mean delivery time is 51.0 minutes with a standard deviation of 17.9.

Three windows, in time order rather than sampled at random, because the model will always be predicting orders that have not happened yet: days 0 to 69 to train (34,462 orders), 70 to 76 to choose (3,425), 77 to 83 to report (3,523). The middle window does the choosing. The last one is opened once.

The baseline is not an aspiration, it is a hurdle: a linear regression on the raw columns of the export. Every number below is measured against it.

Left: a histogram of delivery time in minutes over the training window, peaking near 49 minutes with a long right tail out past 150, with dashed lines at the median of 49 and the 85th percentile of 69. Right: median and 85th percentile delivery time by hour of day, with the band between them shaded. The band is about twelve minutes wide in the mid-afternoon and about eighteen through the lunch and dinner peaks.
Left: the two dashed lines are the whole decision in miniature. Predict the median and half of all orders are late; quote the 85th percentile and most are not. Right: that gap is not the same size all day, which is why a flat buffer added to every order is the wrong shape for the problem.
2

What Each Decision Was Worth

FeaturesLinear regressionGradient boostingWhat the model bought
Raw columns9.8989.6220.277 min (17 s)
Plus four engineered8.0177.9460.071 min (4 s)
What the features bought1.881 min1.676 min

Test RMSE in minutes. Both models use default settings.

Read the bottom row against the right column. The features are worth roughly twenty-four times what the model family is worth, and a linear regression with good features beats a gradient boosting machine with poor ones by more than a minute and a half.

Then a random search over twenty hyperparameter configurations, each fitted on the training window and scored on the validation window, with the winner scored once on the test window.

Search moved validation
0.272 min
worst config to best
Top 10 on the test set
0.072 min
four seconds apart
Winner vs defaults
7.882 / 7.946
four seconds better
Best of the ten on test
7.865
it ranked 10th on validation

Four seconds is real and it is not nothing. Set it beside the 101 seconds the fourth engineered feature was worth and the hierarchy is settled. It is also worth noticing that the configuration ranked tenth on the validation window did best on the test window: among the leaders, the search is ranking noise.

The reporting point

The score you selected on and the score you did not select on are different numbers. The validation figure is optimistic by however much the search exploited that window, and quoting it as the model's accuracy overstates it. The honest procedure also means deploying the validation winner rather than the configuration that happens to do best on the test set, which would be using the test set to choose.

Left: horizontal bars showing how many minutes of test RMSE each decision removed. Four engineered features remove 1.676 minutes or 101 seconds; switching from linear regression to gradient boosting on raw columns removes 0.277 minutes or 17 seconds; the same switch on engineered columns removes 0.071 minutes or 4 seconds; twenty configurations of hyperparameter search remove 0.064 minutes or 4 seconds. Right: a learning curve on a log x-axis. The test error falls from 8.85 minutes at 1,700 orders to 7.88 at 34,000, while the training error rises from 5.2 to 7.65, and the two curves converge.
Left: the same four decisions every tabular project makes, priced. Right: the training and test curves meeting, which is what convergence looks like.
3

Engineer What the Model Cannot Derive

Four features were added: a load ratio (pending orders per available courier), a peak-hour flag, a weekend flag, and the restaurant's own recent median delivery time built from its past orders only. Drop them one at a time and refit.

RemovedTest RMSECost of removing itCould the model have derived it?
is_weekend7.946+0.000 minYes, from day_of_week
is_peak7.955+0.009 minYes, from hour_of_day
load7.958+0.012 minYes, from its two components
rest_hist9.494+1.548 minNo, it aggregates other rows

One feature carried essentially all of it, and the pattern is not an accident. A boosted tree can split on orders_pending and couriers_available separately and approximate their ratio; it can split on hour_of_day and find the lunch and dinner peaks by itself. Writing those out helps readability and almost nothing else.

💡
The rule

Engineer what the model cannot derive from what it already has. Ratios, flags and thresholds of existing columns are convenience. Aggregates across rows, histories, and anything joined in from outside the table are information.

A note on how that feature was built. The expanding median uses each restaurant's previous orders and stops there. Taking a plain groupby(...).median() over the whole file would have been shorter, slightly more accurate on this test set, and wrong, because it would use next month's orders to predict this month's. That is the trap Chapter 191 is about, and it is easiest to fall into exactly here, in the most valuable feature in the project.

4

More Data, or a Better Model?

Both cost money and they are different purchases, so it is worth answering rather than guessing. Fit on growing subsets of the training window and watch the two errors converge.

Training ordersError on the training dataError on the test windowGap
1,7235.2068.8483.641
3,4465.9888.3722.384
8,6156.9808.1091.129
17,2317.4798.0020.523
34,4627.6547.8820.227

The curves have met. The training error has risen and the test error has fallen until the gap is a quarter of a minute, and the last doubling of the data bought 0.12 minutes, about seven seconds.

More data will not help, and neither will a more flexible model. What is left is not error a model could remove with better use of these features. It is variation in the world: two identical orders from the same restaurant, the same distance, the same minute, genuinely arrive at different times.

Which changes the question the project is answering. If the uncertainty cannot be removed, it has to be communicated, and that is a different piece of work from making the model better.

5

Where the Model Is Wrong

An average error of 7.9 minutes is a summary. The question is whether it is the same 7.9 minutes everywhere.

SegmentnAverage error (bias)Spread of the error
Off peak993−0.134.65
Peak hours2,530−0.078.83
Load under 0.8945−0.094.66
Load above 2.0335+0.6711.52
Under 2 km1,107−0.086.77
Over 6 km394−0.3010.35
Dry2,780−0.117.47
Heavy rain338+0.0310.41

The bias is near zero everywhere and the spread is nowhere near constant. Off peak the model is good to about five minutes. When the zone has more than two pending orders per courier it is good to about twelve. A factor of two and a half, and predictable from features already in the model.

A model with this property is not broken. It is reporting something true: some orders are inherently harder to forecast than others. What would be broken is a system that shows the same kind of number for both.

Left: a scatter of prediction errors against pending orders per available courier, with a two-standard-deviation envelope drawn on top. The envelope widens from about 4.8 minutes at the lowest load to about 11.3 at the highest, while the errors stay centered on zero throughout. Right: grouped bars of the share of orders arriving late under a flat 6.7-minute buffer and under the conditional 85th percentile, across six segments, against a dashed 15 percent service target. The flat buffer ranges from 3 percent on easy orders to 25 percent on high-load orders; the conditional version ranges from 15 to 18.
Left: unbiased everywhere, precise only sometimes. Right: two policies with the same average padding, and completely different service.
6

What Number to Display

The point prediction is the best guess at the middle of the distribution, so 46.5 percent of orders arrive after it. That is not a defect. It is what a conditional mean is.

With late costing three times as much as early, the quantity that minimizes expected cost is not the mean but the quantile at τ = 3 ÷ (3 + 1) = 0.75, which is the newsvendor result, and gradient boosting can be fitted directly to that loss.

What is displayedArrive lateAverage paddingCost per order
The point prediction46.5%0.00 min11.271
Point prediction + the current 8 min11.8%8.00 min11.080
Conditional 70th percentile31.3%2.71 min9.808
Conditional 75th percentile25.5%3.93 min9.638
Conditional 80th percentile20.4%5.30 min9.667
Conditional 85th percentile15.4%6.73 min10.099
Conditional 90th percentile10.5%8.90 min11.169

Cost is three times the minutes late plus one times the minutes early, averaged over orders.

The sweep finds its minimum exactly where the theory says it should, at the 75th percentile, and costs about 13 percent less than the current flat 8-minute policy.

There is a genuine tension here to hand back rather than resolve. The 75th percentile is cost-optimal and leaves 25 percent of orders late, against a service target of 15. The 85th hits the target and costs a little more. Which one is right depends on what the service promise is worth, which is a question for the business. What an analysis can do is make sure whichever they choose is delivered well.

7

The Same Padding, Spent Differently

The conditional 85th percentile pads by 6.73 minutes on average. Give a flat buffer the same average padding and compare. If the model's uncertainty estimates are worth anything, the two will differ in who ends up late.

SegmentnCurrent +8 flatMatched 6.73 flatConditional 85th
Off peak, under 3 km5341.9%3.0%16.3%
Off peak, 3 km or more4596.8%9.8%17.6%
Peak, under 3 km1,36913.1%17.1%14.7%
Peak, 3 km or more1,16117.0%20.0%15.1%
Heavy rain33819.8%23.4%17.2%
Load above 2.033521.8%25.1%16.4%
All orders3,52311.8%15.0%15.4%

Read the bottom row first. The two policies have almost the same overall late rate, 15.0 percent against 15.4. On the headline number they are the same product.

Now read the column above it. The flat buffer keeps its promise to 97 percent of easy orders and breaks it for a quarter of the hard ones. Its late rate ranges over 22 percentage points across these six segments; the conditional version ranges over three.

Padding, easiest 10%
2.4 min
flat policy gives 6.7
Padding, median order
6.7 min
flat policy gives 6.7
Padding, hardest 10%
11.8 min
flat policy gives 6.7
Segment spread
22 pp → 3 pp
in the late rate

That difference is invisible in RMSE, invisible in MAE, and invisible in the overall late rate. It is the difference between a service level and an average of service levels, and it falls on the same customers every time: the ones who live further out, order at dinner time, or order when it is raining.

The current +8 policy has the same shape. Its overall figure of 11.8 percent is comfortably inside the target, and it is failing that target for 21.8 percent of the highest-load orders. The headline number is hiding it.

8

What to Watch

9

Quantiles and Cost in Data Science & AI

Where it appearsThe same question, in a different costume
Inventory and supply chainThe original newsvendor problem: stock the quantile set by the ratio of stockout cost to holding cost, not the forecast
Capacity and staffingRostering to the mean guarantees being short half the time; the target is a service level, which is a quantile
Project estimationThe reason a schedule slips is that every task was estimated at its mode and summed as if it were a maximum
Energy and load forecastingGrid operators buy reserve against a high quantile, because the cost of being short is not the cost of being long
Any user-facing estimateArrival times, wait times, download times: the displayed number is a promise, and a promise is a quantile
Where the research went

Koenker and Bassett introduced quantile regression in 1978 and the pinball loss used here is theirs. Friedman gave gradient boosting its modern form in 2001, and Meinshausen's quantile regression forests showed how to get a full conditional distribution out of an ensemble rather than a single number. The distribution-free alternative is conformal prediction, developed by Vovk, Gammerman and Shafer and extended to conditional coverage by Romano, Patterson and Candès, which produces intervals with a guaranteed marginal coverage rate without assuming anything about the error distribution. On the model-comparison question, Grinsztajn and colleagues assembled the evidence that tree ensembles still lead on tabular data, and Kadra and colleagues made the complementary point that most of the reported gains in this literature are smaller than the tuning budgets that produced them.

🐍

The full project, step by step

The companion notebook cleans three faults out of the export, splits by time, fits the linear baseline, builds and prices the four engineered features, runs the twenty-configuration search and scores it honestly, draws the learning curve, breaks the residuals down by segment, fits the quantile models, and compares a conditional quantile against a flat buffer at matched padding.

📓 View Notebook (code & outputs) ▶ Open in Colab ⬇ View / Download on GitHub
Read the reports & get the data

The dataset (capstone-gradient-boosting-regression.xlsx) holds 42,520 orders across 84 days and 140 restaurants, with a duplicated export block, cancellations recorded as zero minutes, GPS failures recorded as 999 kilometers, and the agreed cost of being late. Two written reports accompany it: a plain-language brief for the operations lead, and a technical report covering the comparison, the search and the quantile policy.

🎓 Key Takeaways

  • Features 101 seconds, model family 17, hyperparameters 4. The effort usually runs in the other order.
  • One feature did all of it. The three the model could have derived were worth 0.02 minutes between them; the cross-row history was worth 1.55.
  • The learning curves met, so the remaining error is in the world rather than in the model.
  • The residual spread varies by a factor of two and a half across ordinary conditions, and it is predictable in advance.
  • Same padding, same overall late rate, 22 points of spread against 3. An average service level is not a service level.

Quiz: Test Yourself