ECON 8310: Business Forecasting — Lecture 4
University of Nebraska at Omaha
Real-world relationships are often nonlinear, involve interactions, and shift with context.
Three things a constant slope cannot represent:
Retail Sales Example
Monthly sales depend on last year’s same-month sales (trend), whether it is December (seasonality), and the unemployment rate (conditions). The December effect is larger in a strong economy — an interaction a linear model misses.
Decision trees capture nonlinearity and interactions automatically, without your having to specify them in advance.
Bias–Variance Decomposition
\[\text{Expected MSE} = \underbrace{\text{Bias}^2}_{\text{systematic error}} + \underbrace{\text{Variance}}_{\text{sensitivity to data}} + \underbrace{\sigma^2}_{\text{irreducible noise}}\]
Weekly CA_1 FOODS, 20 bootstrap refits per model. Stumps (one-question trees) agree and miss: bias. Deep trees center on the truth but scatter: variance. (The miss includes noise, so it is not pure bias.) Goal: the complexity that balances the two, visible only out-of-sample.
Partition the feature space into rectangles; predict the mean in each region.
A flowchart of yes/no questions about the features, ending in a prediction. Here is the real depth-2 tree for weekly CA_1 FOODS units:
Non-parametric · nonlinear (captures thresholds) · interpretable · scale-invariant. A single deep tree overfits severely; ensembles, the next lecture, are the fix.
\(y_{t-4}\): units four weeks earlier; \(y_{t-52}\): the same week last year. Fitted on the 173 weeks before the test year.
Each question is a straight cut parallel to an axis. Each leaf is a rectangle, shaded by its mean; every week inside it gets that forecast.
Last year’s sales cut only the right half: they matter only when recent demand is already high. That is an interaction, and nobody specified it.
At each node, CART tries every feature \(j\) and threshold \(t\), and keeps the split with the least squared error:
\[\textstyle\sum_{x_{ij} \leq t} (y_i - \bar{y}_{L})^2 + \sum_{x_{ij} > t} (y_i - \bar{y}_{R})^2\]
Each leaf predicts its mean; then repeat inside each group.
Geometrically: slide the cut and total the squared vertical sticks. Our best first cut, \(y_{t-4} \leq 20{,}603\), removes 35% of the squared error.
Classification uses Gini impurity or entropy instead.
CART is exhaustive at each node: it tries every feature and every threshold. But it is greedy across nodes: it never looks ahead. An illustration:
| Split at the root | Variance removed now | …plus what it enables |
|---|---|---|
| On price | 40% | \(+\) 12% (total 52%) |
| On promotion | 38% | \(+\) 50% (total 88%) |
CART takes the 40%. It cannot see the 50% coming: it scores one split at a time.
So a fitted tree is a sequence of locally best choices, not the optimal tree (finding that is intractable). It can miss real structure, and a small change in the data can send the greedy sequence down a different path: the instability we turn to next.
A stump asks one question: high bias, low variance. A full tree, one week per leaf, memorizes the sample: zero training error, high variance.
Weekly CA_1 FOODS, one week ahead (seasonal naive: 1,660). Training error falls to zero; test error stops improving after depth 3 (only 173 weeks). Read the shape, not the minimum: picking depth from the test year is a leak. Unstable, too: one changed week can flip the root split, and everything below it. Tune by TimeSeriesSplit.
max_depth caps the tree in advance. Two other controls do the job better.
| Parameter | What it does |
|---|---|
min_samples_leaf |
Stop early. At the default of 1, a leaf may hold a single observation and “predict” that one value. Set it to 5–10 and every prediction is an average over a real group. |
ccp_alpha |
Prune after. Grow the tree out fully, then charge a penalty \(\alpha\) per leaf and cut back the branches that do not pay for themselves. |
Choose either one by TimeSeriesSplit cross-validation, never by the test year.
Pruning minimizes \(\sum_{\text{leaves}} \text{SSE} + \alpha\,|T|\): the fit, plus a price \(\alpha\) for each of the \(|T|\) leaves. Each black dot is the best pruned tree for some range of \(\alpha\).
Push a line of slope \(-\alpha\) up from below: the first dot it touches is the tree \(\alpha\) picks. A bigger \(\alpha\) tilts it and picks a smaller tree. The 4-leaf tree is the flowchart from earlier.
The same idea as Lecture 3’s smoothing penalty and Lecture 6’s Ridge and LASSO; \(\alpha\) is chosen by cross-validation. scikit-learn’s ccp_alpha is \(\alpha/n\).
One class, a few hyperparameters, interpretable results.
sklearn Code Template
| Parameter | Effect |
|---|---|
max_depth |
Cap tree depth |
min_samples_leaf |
Minimum observations per leaf |
max_features |
Feature subsampling |
ccp_alpha |
Cost-complexity pruning |
Cross-validate with TimeSeriesSplit, never KFold — random folds leak the future into the training set.
Impurity-Based Feature Importance
For each feature \(j\), sum the total reduction in variance across all splits where \(j\) was used, weighted by the fraction of observations in each node. Normalize so the importances sum to 1.
| Feature (CA_1 FOODS, weekly) | Importance |
|---|---|
units_lag4 |
0.62 |
units_lag52 |
0.15 |
units_lag1 |
0.13 |
snap_days |
0.05 |
avg_price |
0.04 |
From the previous slide’s depth-5 tree. Read it as a list of what the tree leaned on: a fast way to screen predictors.
But impurity importance is biased toward features with many split points. Permutation importance gives a more reliable ranking; we return to it in Lecture 5.
A tree’s main advantage is that you can explain why a specific prediction was made.
Explaining a Prediction to a Manager
“Our model forecasts 22,988 units for this week because:
Produce the path with sklearn.tree.plot_tree(tree) or export_text(tree, feature_names=[...]).
This is where business buy-in comes from — a manager can check that the tree is splitting on variables they consider sensible.
A single tree is a weak learner. Combine hundreds to build a strong one.
Strengths:
Weaknesses:
The ensemble solution: average many trees fitted to bootstrap samples. Variance falls sharply and feature importance survives, typically for 20–40% lower RMSE than one tree.
min_samples_leaf or ccp_alpha, tuned by TimeSeriesSplit.Next: Tree Ensembles — variance reduction through bootstrap aggregation, and sequential error correction with boosting.
ECON 8310 | University of Nebraska at Omaha