Bias and variance: where a model's errors come from

On this page
  1. The idea, with a person
  2. The formula
  3. Measuring it
  4. Overfitting and underfitting
  5. The same curve on real data
  6. How to find the sweet spot in practice
  7. The code
  8. Summary
  9. References

This is the idea behind overfitting, and it’s explained in section 2.2.2 of An Introduction to Statistical Learning. It’s the reason a model that looks perfect in testing can fail in production, and the reason three later posts (bagging, random forests, boosting) exist at all.

In the decision trees post, a fully grown tree scored a perfect 1.000 on the rows it trained on and 0.742 on test rows it had not seen (on a scale where 0.5 is a coin flip). This post explains why, with a formula you can actually measure.

The idea, with a person

Imagine two new risk analysts forecasting next month’s volatility.

  • Analyst A has one rule: “a jumpy month is followed by a jumpy month.” Simple, consistent, and often wrong in the same way. That’s bias: a model too simple for the real pattern.
  • Analyst B remembers every single month they’ve ever seen and predicts from the most similar one. Give B a different few years of history, and B’s forecasts change completely. That’s variance: a model that reacts too much to the particular data it learned from.

A good analyst is in between: they learn the real pattern and ignore the one-off quirks.

The formula

For a model f^\key{\hat{f}} trained on some data, the expected squared error on a new point x0x_0 splits into three parts. This is equation 2.7 in An Introduction to Statistical Learning:

f̂, the model's predictionf and y, the truthbiasvariance

E(y0−f^(x0))2=Var(f^(x0))+[Bias(f^(x0))]2+Var(ε)\begin{aligned} E\left(\good{y_0} - \key{\hat{f}}(x_0)\right)^2 &= \risk{\text{Var}}\left(\key{\hat{f}}(x_0)\right) \\ &\quad + \left[\bad{\text{Bias}}\left(\key{\hat{f}}(x_0)\right)\right]^2 \\ &\quad + \text{Var}(\varepsilon) \end{aligned}

Written out term by term (same thing, with each part spelled out; the symbols are in Table 1):

E[(y−f^(x))2]=(E[f^(x)]−f(x))2⏟bias2+E[(f^(x)−E[f^(x)])2]⏟variance+σ2⏟noise\begin{aligned} E\left[\left(\good{y} - \key{\hat{f}}(x)\right)^2\right] &= \underbrace{\left(E[\key{\hat{f}}(x)] - \good{f(x)}\right)^2}_{\bad{\text{bias}}^2} \\ &\quad + \underbrace{E\left[\left(\key{\hat{f}}(x) - E[\key{\hat{f}}(x)]\right)^2\right]}_{\risk{\text{variance}}} \\ &\quad + \underbrace{\sigma^2}_{\text{noise}} \end{aligned}
Table 1. Symbols in the bias-variance decomposition
SymbolMeaning
f(x)\good{f(x)}the true average answer at xx, the real pattern
f^(x)\key{\hat{f}}(x)what our model predicts at xx
E[f^(x)]E[\key{\hat{f}}(x)]the model’s average prediction, if we could train it again and again on fresh samples
σ2\sigma^2the variance of the noise: randomness in y\good{y} that no model can predict

In words:

  • Bias2^2: how far the model’s average guess is from the truth. Too simple → large.
  • Variance: how much the model’s guess jumps around depending on the sample it trained on. Too complex → large.
  • Noise: the part of the error that stays even with a perfect model.

The expectation E[⋅]E[\cdot] here is over many different training samples. That is the thing to hold on to about variance. It is not a property of one trained model. It measures how much the model would change if you had collected different data.

Measuring it

Usually you can’t measure bias and variance, because you don’t know the true pattern f(x)\good{f(x)}. With made-up data, you can. I invented a true curve for next month’s volatility as a function of this month’s, shaped like the real SPY data in the linear regression post: a gentle slope, plus a step up once the market is already above about 25% (once markets are wild, they tend to stay wild). Then I added random noise with a standard deviation of 3 points (so σ2=9\sigma^2 = 9).

Then, for each tree depth, I repeated this 300 times: draw 80 fresh months, train a regression tree, record its predictions. That gives me 300 versions of each model, enough to measure its average and its spread (Table 2).

Table 2. Bias2^2, variance and measured error by tree depth, simulated
Tree depthBias2^2VarianceNoiseBias2^2 + variance + noiseMeasured error on new months
18.006.259.0023.2423.29
20.574.469.0014.0214.00
30.012.829.0011.8311.82
50.026.099.0015.1115.06
80.038.499.0017.5217.44
150.049.119.0018.1418.21

Two things to see. First, the formula works: the three parts add up to the error I measured directly on new months, to within simulation noise. Second, the trade-off, drawn in Figure 1:

{"panels":[{"x0":43.64,"x1":565.2,"y0":29.16,"y1":221.54,"title":"1. Bias falls and variance rises as the tree gets deeper","xlabel":"Tree depth (more depth = more complex model)","ylabel":"Squared error on new months (volatility points\u00b2)","xlog":false},{"x0":43.64,"x1":565.2,"y0":371.3,"y1":563.68,"title":"2. Six training samples each: depth-1 trees agree, depth-15 trees zig-zag","xlabel":"This month's volatility (% a year)","ylabel":"Next month's volatility (% a year)","xlog":false}],"series":[{"panel":0,"label":"bias\u00b2","color":"var(--chart-blue, #3b6ea5)","kind":"line","x":[1.0,2.0,3.0,4.0,5.0,6.0,8.0,10.0,15.0],"y":[7.99765,0.567031,0.0135222,0.0210622,0.0183405,0.0298146,0.0289699,0.0316175,0.0369362],"sx":[67.35,101.22,135.08,168.95,202.82,236.69,304.42,372.16,541.49],"sy":[152.8,208.63,212.79,212.74,212.76,212.67,212.68,212.66,212.62]},{"panel":0,"label":"variance","color":"var(--chart-maroon, #b6262c)","kind":"line","x":[1.0,2.0,3.0,4.0,5.0,6.0,8.0,10.0,15.0],"y":[6.2472,4.45538,2.82035,4.66839,6.09086,7.3936,8.48628,9.04216,9.10771],"sx":[67.35,101.22,135.08,168.95,202.82,236.69,304.42,372.16,541.49],"sy":[165.95,179.42,191.7,177.81,167.13,157.34,149.13,144.95,144.46]},{"panel":0,"label":"error on new months","color":"#7d7b77","kind":"line","x":[1.0,2.0,3.0,4.0,5.0,6.0,8.0,10.0,15.0],"y":[23.2875,13.9995,11.8164,13.551,15.0553,16.5442,17.4356,18.0739,18.2057],"sx":[67.35,101.22,135.08,168.95,202.82,236.69,304.42,372.16,541.49],"sy":[37.9,107.7,124.1,111.07,99.76,88.57,81.88,77.08,76.09]},{"panel":1,"label":"depth 15","color":"var(--chart-maroon, #b6262c)","kind":"line","x":[5.0,5.20101,5.40201,5.60302,5.80402,6.00503,6.20603,6.40704,6.60804,6.80905,7.01005,7.21106,7.41206,7.61307,7.81407,8.01508,8.21608,8.41709,8.61809,8.8191,9.0201,9.22111,9.42211,9.62312,9.82412,10.0251,10.2261,10.4271,10.6281,10.8291,11.0302,11.2312,11.4322,11.6332,11.8342,12.0352,12.2362,12.4372,12.6382,12.8392,13.0402,13.2412,13.4422,13.6432,13.8442,14.0452,14.2462,14.4472,14.6482,14.8492,15.0503,15.2513,15.4523,15.6533,15.8543,16.0553,16.2563,16.4573,16.6583,16.8593,17.0603,17.2613,17.4623,17.6633,17.8643,18.0653,18.2663,18.4673,18.6683,18.8693,19.0704,19.2714,19.4724,19.6734,19.8744,20.0754,20.2764,20.4774,20.6784,20.8794,21.0804,21.2814,21.4824,21.6834,21.8844,22.0854,22.2864,22.4874,22.6884,22.8894,23.0905,23.2915,23.4925,23.6935,23.8945,24.0955,24.2965,24.4975,24.6985,24.8995,25.1005,25.3015,25.5025,25.7035,25.9045,26.1055,26.3065,26.5075,26.7085,26.9095,27.1106,27.3116,27.5126,27.7136,27.9146,28.1156,28.3166,28.5176,28.7186,28.9196,29.1206,29.3216,29.5226,29.7236,29.9246,30.1256,30.3266,30.5276,30.7286,30.9296,31.1307,31.3317,31.5327,31.7337,31.9347,32.1357,32.3367,32.5377,32.7387,32.9397,33.1407,33.3417,33.5427,33.7437,33.9447,34.1457,34.3467,34.5477,34.7487,34.9497,35.1508,35.3518,35.5528,35.7538,35.9548,36.1558,36.3568,36.5578,36.7588,36.9598,37.1608,37.3618,37.5628,37.7638,37.9648,38.1658,38.3668,38.5678,38.7688,38.9698,39.1709,39.3719,39.5729,39.7739,39.9749,40.1759,40.3769,40.5779,40.7789,40.9799,41.1809,41.3819,41.5829,41.7839,41.9849,42.1859,42.3869,42.5879,42.7889,42.9899,43.191,43.392,43.593,43.794,43.995,44.196,44.397,44.598,44.799,45.0],"y":[13.3818,13.3818,13.3818,13.3818,13.3818,13.3818,13.3818,13.3818,15.1384,15.1384,10.1108,12.0089,12.0089,12.0089,12.0089,4.56186,4.56186,4.56186,4.56186,6.14261,6.14261,6.14261,14.5135,12.9951,7.63218,8.78216,8.78216,8.78216,9.38142,9.38142,9.38142,10.6515,13.544,13.544,13.544,12.2855,12.2855,12.2855,12.2855,12.2855,18.888,18.888,18.888,18.888,18.888,13.9779,13.9779,13.9779,13.9779,10.9617,10.9617,10.9617,9.46102,9.46102,9.46102,9.46102,11.6611,11.6611,11.6611,11.6611,11.6611,11.6611,11.6611,15.7101,15.7101,15.7101,15.7101,15.7101,15.7101,16.9502,16.9502,16.9502,16.9502,16.9502,13.9397,13.9397,13.9397,13.9397,13.9397,13.1428,16.4174,18.2356,17.0939,19.1593,19.1593,19.1593,16.4033,16.4033,16.4033,16.4033,24.0315,24.0315,24.0315,22.0742,22.341,22.341,22.0743,21.0343,20.69,17.2522,17.2522,13.1279,13.1279,24.4553,21.143,23.9889,23.9889,17.123,17.123,22.0263,24.5674,23.0343,27.466,27.466,24.5484,24.5484,20.6553,20.6553,21.2928,21.2928,21.2928,23.6851,23.6851,23.6851,23.6851,23.6851,23.6851,23.6851,23.6851,23.6633,23.6633,23.6633,23.6633,23.6633,23.6633,23.6633,23.6633,28.118,28.118,28.118,28.118,26.4229,26.4229,29.5096,33.097,26.5663,26.5663,31.809,31.809,31.809,23.2025,23.2025,23.2025,29.3325,29.3325,26.2208,26.2208,26.4358,26.4358,29.4847,29.4847,29.4847,30.6425,30.6425,30.6425,36.6003,36.6003,30.1395,30.1395,30.1395,29.5997,29.5997,31.2673,31.2673,31.2673,30.1692,30.1692,30.1692,25.8274,25.8274,25.8274,37.2406,37.2406,37.2406,37.2406,37.8902,37.8902,33.3848,30.3495,32.1416,32.1416,34.0321,40.2488,40.2488,40.2488,37.3729,37.3729,34.7928,34.7928,34.7928],"sx":[67.35,69.73,72.11,74.5,76.88,79.26,81.65,84.03,86.41,88.79,91.18,93.56,95.94,98.32,100.71,103.09,105.47,107.85,110.24,112.62,115.0,117.38,119.77,122.15,124.53,126.92,129.3,131.68,134.06,136.45,138.83,141.21,143.59,145.98,148.36,150.74,153.12,155.51,157.89,160.27,162.65,165.04,167.42,169.8,172.19,174.57,176.95,179.33,181.72,184.1,186.48,188.86,191.25,193.63,196.01,198.39,200.78,203.16,205.54,207.92,210.31,212.69,215.07,217.46,219.84,222.22,224.6,226.99,229.37,231.75,234.13,236.52,238.9,241.28,243.66,246.05,248.43,250.81,253.19,255.58,257.96,260.34,262.73,265.11,267.49,269.87,272.26,274.64,277.02,279.4,281.79,284.17,286.55,288.93,291.32,293.7,296.08,298.46,300.85,303.23,305.61,308.0,310.38,312.76,315.14,317.53,319.91,322.29,324.67,327.06,329.44,331.82,334.2,336.59,338.97,341.35,343.73,346.12,348.5,350.88,353.27,355.65,358.03,360.41,362.8,365.18,367.56,369.94,372.33,374.71,377.09,379.47,381.86,384.24,386.62,389.0,391.39,393.77,396.15,398.54,400.92,403.3,405.68,408.07,410.45,412.83,415.21,417.6,419.98,422.36,424.74,427.13,429.51,431.89,434.27,436.66,439.04,441.42,443.81,446.19,448.57,450.95,453.34,455.72,458.1,460.48,462.87,465.25,467.63,470.01,472.4,474.78,477.16,479.54,481.93,484.31,486.69,489.07,491.46,493.84,496.22,498.61,500.99,503.37,505.75,508.14,510.52,512.9,515.28,517.67,520.05,522.43,524.81,527.2,529.58,531.96,534.34,536.73,539.11,541.49],"sy":[507.5,507.5,507.5,507.5,507.5,507.5,507.5,507.5,499.17,499.17,523.02,514.02,514.02,514.02,514.02,549.35,549.35,549.35,549.35,541.85,541.85,541.85,502.13,509.34,534.78,529.32,529.32,529.32,526.48,526.48,526.48,520.46,506.73,506.73,506.73,512.7,512.7,512.7,512.7,512.7,481.38,481.38,481.38,481.38,481.38,504.67,504.67,504.67,504.67,518.98,518.98,518.98,526.1,526.1,526.1,526.1,515.67,515.67,515.67,515.67,515.67,515.67,515.67,496.46,496.46,496.46,496.46,496.46,496.46,490.57,490.57,490.57,490.57,490.57,504.86,504.86,504.86,504.86,504.86,508.64,493.1,484.48,489.89,480.09,480.09,480.09,493.17,493.17,493.17,493.17,456.98,456.98,456.98,466.26,465.0,465.0,466.26,471.2,472.83,489.14,489.14,508.71,508.71,454.97,470.68,457.18,457.18,489.75,489.75,466.49,454.44,461.71,440.69,440.69,454.53,454.53,473.0,473.0,469.97,469.97,469.97,458.62,458.62,458.62,458.62,458.62,458.62,458.62,458.62,458.73,458.73,458.73,458.73,458.73,458.73,458.73,458.73,437.59,437.59,437.59,437.59,445.63,445.63,430.99,413.97,444.95,444.95,420.08,420.08,420.08,460.91,460.91,460.91,431.83,431.83,446.59,446.59,445.57,445.57,431.11,431.11,431.11,425.62,425.62,425.62,397.35,397.35,428.0,428.0,428.0,430.56,430.56,422.65,422.65,422.65,427.86,427.86,427.86,448.46,448.46,448.46,394.31,394.31,394.31,394.31,391.23,391.23,412.61,427.0,418.5,418.5,409.53,380.04,380.04,380.04,393.69,393.69,405.93,405.93,405.93]},{"panel":1,"label":"depth 1","color":"var(--chart-blue, #3b6ea5)","kind":"line","x":[5.0,5.20101,5.40201,5.60302,5.80402,6.00503,6.20603,6.40704,6.60804,6.80905,7.01005,7.21106,7.41206,7.61307,7.81407,8.01508,8.21608,8.41709,8.61809,8.8191,9.0201,9.22111,9.42211,9.62312,9.82412,10.0251,10.2261,10.4271,10.6281,10.8291,11.0302,11.2312,11.4322,11.6332,11.8342,12.0352,12.2362,12.4372,12.6382,12.8392,13.0402,13.2412,13.4422,13.6432,13.8442,14.0452,14.2462,14.4472,14.6482,14.8492,15.0503,15.2513,15.4523,15.6533,15.8543,16.0553,16.2563,16.4573,16.6583,16.8593,17.0603,17.2613,17.4623,17.6633,17.8643,18.0653,18.2663,18.4673,18.6683,18.8693,19.0704,19.2714,19.4724,19.6734,19.8744,20.0754,20.2764,20.4774,20.6784,20.8794,21.0804,21.2814,21.4824,21.6834,21.8844,22.0854,22.2864,22.4874,22.6884,22.8894,23.0905,23.2915,23.4925,23.6935,23.8945,24.0955,24.2965,24.4975,24.6985,24.8995,25.1005,25.3015,25.5025,25.7035,25.9045,26.1055,26.3065,26.5075,26.7085,26.9095,27.1106,27.3116,27.5126,27.7136,27.9146,28.1156,28.3166,28.5176,28.7186,28.9196,29.1206,29.3216,29.5226,29.7236,29.9246,30.1256,30.3266,30.5276,30.7286,30.9296,31.1307,31.3317,31.5327,31.7337,31.9347,32.1357,32.3367,32.5377,32.7387,32.9397,33.1407,33.3417,33.5427,33.7437,33.9447,34.1457,34.3467,34.5477,34.7487,34.9497,35.1508,35.3518,35.5528,35.7538,35.9548,36.1558,36.3568,36.5578,36.7588,36.9598,37.1608,37.3618,37.5628,37.7638,37.9648,38.1658,38.3668,38.5678,38.7688,38.9698,39.1709,39.3719,39.5729,39.7739,39.9749,40.1759,40.3769,40.5779,40.7789,40.9799,41.1809,41.3819,41.5829,41.7839,41.9849,42.1859,42.3869,42.5879,42.7889,42.9899,43.191,43.392,43.593,43.794,43.995,44.196,44.397,44.598,44.799,45.0],"y":[13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,13.95,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165,30.1165],"sx":[67.35,69.73,72.11,74.5,76.88,79.26,81.65,84.03,86.41,88.79,91.18,93.56,95.94,98.32,100.71,103.09,105.47,107.85,110.24,112.62,115.0,117.38,119.77,122.15,124.53,126.92,129.3,131.68,134.06,136.45,138.83,141.21,143.59,145.98,148.36,150.74,153.12,155.51,157.89,160.27,162.65,165.04,167.42,169.8,172.19,174.57,176.95,179.33,181.72,184.1,186.48,188.86,191.25,193.63,196.01,198.39,200.78,203.16,205.54,207.92,210.31,212.69,215.07,217.46,219.84,222.22,224.6,226.99,229.37,231.75,234.13,236.52,238.9,241.28,243.66,246.05,248.43,250.81,253.19,255.58,257.96,260.34,262.73,265.11,267.49,269.87,272.26,274.64,277.02,279.4,281.79,284.17,286.55,288.93,291.32,293.7,296.08,298.46,300.85,303.23,305.61,308.0,310.38,312.76,315.14,317.53,319.91,322.29,324.67,327.06,329.44,331.82,334.2,336.59,338.97,341.35,343.73,346.12,348.5,350.88,353.27,355.65,358.03,360.41,362.8,365.18,367.56,369.94,372.33,374.71,377.09,379.47,381.86,384.24,386.62,389.0,391.39,393.77,396.15,398.54,400.92,403.3,405.68,408.07,410.45,412.83,415.21,417.6,419.98,422.36,424.74,427.13,429.51,431.89,434.27,436.66,439.04,441.42,443.81,446.19,448.57,450.95,453.34,455.72,458.1,460.48,462.87,465.25,467.63,470.01,472.4,474.78,477.16,479.54,481.93,484.31,486.69,489.07,491.46,493.84,496.22,498.61,500.99,503.37,505.75,508.14,510.52,512.9,515.28,517.67,520.05,522.43,524.81,527.2,529.58,531.96,534.34,536.73,539.11,541.49],"sy":[504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,504.81,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11,428.11]},{"panel":1,"label":"true average (the curve we set)","color":"#7d7b77","kind":"line","x":[5.0,5.20101,5.40201,5.60302,5.80402,6.00503,6.20603,6.40704,6.60804,6.80905,7.01005,7.21106,7.41206,7.61307,7.81407,8.01508,8.21608,8.41709,8.61809,8.8191,9.0201,9.22111,9.42211,9.62312,9.82412,10.0251,10.2261,10.4271,10.6281,10.8291,11.0302,11.2312,11.4322,11.6332,11.8342,12.0352,12.2362,12.4372,12.6382,12.8392,13.0402,13.2412,13.4422,13.6432,13.8442,14.0452,14.2462,14.4472,14.6482,14.8492,15.0503,15.2513,15.4523,15.6533,15.8543,16.0553,16.2563,16.4573,16.6583,16.8593,17.0603,17.2613,17.4623,17.6633,17.8643,18.0653,18.2663,18.4673,18.6683,18.8693,19.0704,19.2714,19.4724,19.6734,19.8744,20.0754,20.2764,20.4774,20.6784,20.8794,21.0804,21.2814,21.4824,21.6834,21.8844,22.0854,22.2864,22.4874,22.6884,22.8894,23.0905,23.2915,23.4925,23.6935,23.8945,24.0955,24.2965,24.4975,24.6985,24.8995,25.1005,25.3015,25.5025,25.7035,25.9045,26.1055,26.3065,26.5075,26.7085,26.9095,27.1106,27.3116,27.5126,27.7136,27.9146,28.1156,28.3166,28.5176,28.7186,28.9196,29.1206,29.3216,29.5226,29.7236,29.9246,30.1256,30.3266,30.5276,30.7286,30.9296,31.1307,31.3317,31.5327,31.7337,31.9347,32.1357,32.3367,32.5377,32.7387,32.9397,33.1407,33.3417,33.5427,33.7437,33.9447,34.1457,34.3467,34.5477,34.7487,34.9497,35.1508,35.3518,35.5528,35.7538,35.9548,36.1558,36.3568,36.5578,36.7588,36.9598,37.1608,37.3618,37.5628,37.7638,37.9648,38.1658,38.3668,38.5678,38.7688,38.9698,39.1709,39.3719,39.5729,39.7739,39.9749,40.1759,40.3769,40.5779,40.7789,40.9799,41.1809,41.3819,41.5829,41.7839,41.9849,42.1859,42.3869,42.5879,42.7889,42.9899,43.191,43.392,43.593,43.794,43.995,44.196,44.397,44.598,44.799,45.0],"y":[8.26017,8.35132,8.44253,8.53379,8.6251,8.71647,8.8079,8.89941,8.99098,9.08263,9.17437,9.26619,9.35811,9.45013,9.54226,9.6345,9.72687,9.81937,9.912,10.0048,10.0977,10.1909,10.2842,10.3777,10.4714,10.5653,10.6595,10.7539,10.8486,10.9436,11.0388,11.1345,11.2304,11.3268,11.4235,11.5207,11.6183,11.7164,11.815,11.9141,12.0139,12.1142,12.2153,12.317,12.4194,12.5227,12.6268,12.7318,12.8377,12.9447,13.0527,13.1618,13.2721,13.3837,13.4967,13.611,13.7268,13.8442,13.9633,14.0841,14.2067,14.3313,14.4579,14.5866,14.7175,14.8508,14.9864,15.1246,15.2654,15.4089,15.5552,15.7044,15.8566,16.0118,16.1703,16.332,16.4969,16.6653,16.837,17.0121,17.1907,17.3728,17.5583,17.7472,17.9395,18.1351,18.3339,18.5358,18.7407,18.9485,19.159,19.3719,19.5872,19.8045,20.0237,20.2445,20.4665,20.6896,20.9135,21.1378,21.3622,21.5865,21.8104,22.0335,22.2555,22.4763,22.6955,22.9128,23.1281,23.341,23.5515,23.7593,23.9642,24.1661,24.3649,24.5605,24.7528,24.9417,25.1272,25.3093,25.4879,25.663,25.8347,26.0031,26.168,26.3297,26.4882,26.6434,26.7956,26.9448,27.0911,27.2346,27.3754,27.5136,27.6492,27.7825,27.9134,28.0421,28.1687,28.2933,28.4159,28.5367,28.6558,28.7732,28.889,29.0033,29.1163,29.2279,29.3382,29.4473,29.5553,29.6623,29.7682,29.8732,29.9773,30.0806,30.183,30.2847,30.3858,30.4861,30.5859,30.685,30.7836,30.8817,30.9793,31.0765,31.1732,31.2696,31.3655,31.4612,31.5564,31.6514,31.7461,31.8405,31.9347,32.0286,32.1223,32.2158,32.3091,32.4023,32.4952,32.588,32.6806,32.7731,32.8655,32.9577,33.0499,33.1419,33.2338,33.3256,33.4174,33.509,33.6006,33.6921,33.7835,33.8749,33.9662,34.0575,34.1487,34.2398],"sx":[67.35,69.73,72.11,74.5,76.88,79.26,81.65,84.03,86.41,88.79,91.18,93.56,95.94,98.32,100.71,103.09,105.47,107.85,110.24,112.62,115.0,117.38,119.77,122.15,124.53,126.92,129.3,131.68,134.06,136.45,138.83,141.21,143.59,145.98,148.36,150.74,153.12,155.51,157.89,160.27,162.65,165.04,167.42,169.8,172.19,174.57,176.95,179.33,181.72,184.1,186.48,188.86,191.25,193.63,196.01,198.39,200.78,203.16,205.54,207.92,210.31,212.69,215.07,217.46,219.84,222.22,224.6,226.99,229.37,231.75,234.13,236.52,238.9,241.28,243.66,246.05,248.43,250.81,253.19,255.58,257.96,260.34,262.73,265.11,267.49,269.87,272.26,274.64,277.02,279.4,281.79,284.17,286.55,288.93,291.32,293.7,296.08,298.46,300.85,303.23,305.61,308.0,310.38,312.76,315.14,317.53,319.91,322.29,324.67,327.06,329.44,331.82,334.2,336.59,338.97,341.35,343.73,346.12,348.5,350.88,353.27,355.65,358.03,360.41,362.8,365.18,367.56,369.94,372.33,374.71,377.09,379.47,381.86,384.24,386.62,389.0,391.39,393.77,396.15,398.54,400.92,403.3,405.68,408.07,410.45,412.83,415.21,417.6,419.98,422.36,424.74,427.13,429.51,431.89,434.27,436.66,439.04,441.42,443.81,446.19,448.57,450.95,453.34,455.72,458.1,460.48,462.87,465.25,467.63,470.01,472.4,474.78,477.16,479.54,481.93,484.31,486.69,489.07,491.46,493.84,496.22,498.61,500.99,503.37,505.75,508.14,510.52,512.9,515.28,517.67,520.05,522.43,524.81,527.2,529.58,531.96,534.34,536.73,539.11,541.49],"sy":[531.8,531.37,530.94,530.5,530.07,529.64,529.2,528.77,528.33,527.9,527.46,527.03,526.59,526.16,525.72,525.28,524.84,524.4,523.96,523.52,523.08,522.64,522.2,521.75,521.31,520.86,520.42,519.97,519.52,519.07,518.62,518.16,517.71,517.25,516.79,516.33,515.87,515.4,514.94,514.47,513.99,513.52,513.04,512.55,512.07,511.58,511.08,510.59,510.08,509.58,509.06,508.55,508.02,507.49,506.96,506.42,505.87,505.31,504.74,504.17,503.59,503.0,502.4,501.79,501.17,500.53,499.89,499.23,498.57,497.89,497.19,496.48,495.76,495.03,494.27,493.51,492.72,491.93,491.11,490.28,489.43,488.57,487.69,486.79,485.88,484.95,484.01,483.05,482.08,481.09,480.09,479.08,478.06,477.03,475.99,474.95,473.89,472.83,471.77,470.71,469.64,468.58,467.52,466.46,465.4,464.36,463.32,462.29,461.26,460.25,459.26,458.27,457.3,456.34,455.4,454.47,453.56,452.66,451.78,450.92,450.07,449.24,448.42,447.63,446.84,446.08,445.32,444.59,443.87,443.16,442.46,441.78,441.11,440.46,439.82,439.18,438.56,437.95,437.35,436.76,436.18,435.61,435.04,434.48,433.93,433.39,432.86,432.33,431.8,431.29,430.77,430.27,429.76,429.26,428.77,428.28,427.79,427.31,426.83,426.36,425.88,425.41,424.95,424.48,424.02,423.56,423.1,422.64,422.18,421.73,421.28,420.83,420.38,419.93,419.48,419.04,418.59,418.15,417.71,417.27,416.83,416.39,415.95,415.51,415.07,414.63,414.19,413.76,413.32,412.89,412.45,412.02,411.58,411.15,410.71,410.28,409.85,409.41,408.98,408.55]}]} 2026-10-31T01:54:52.630025 image/svg+xml Matplotlib v3.11.2, https://matplotlib.org/ 2 4 6 8 10 12 14 Tree depth (more depth = more complex model) 0 5 10 15 20 Squared error on new months (volatility points²) noise (can't be removed) 1. Bias falls and variance rises as the tree gets deeper bias² variance error on new months 5 10 15 20 25 30 35 40 45 This month's volatility (% a year) 5 10 15 20 25 30 35 40 Next month's volatility (% a year) 2. Six training samples each: depth-1 trees agree, depth-15 trees zig-zag depth 15 depth 1 true average (the curve we set)
Figure 1. Bias, variance and total error by tree depth, and the fitted trees

  • Depth 1 (blue on the right): a single question. Every version gives nearly the same flat steps, and all of them miss the shape of the curve. High bias.
  • Depth 15 (red): every version zig-zags through its own noise, and no two agree. Bias is almost zero, because on average they follow the curve, but each one alone is far off. High variance.
  • Depth 3 gives the lowest total error here. Not the most flexible model, not the simplest. Three questions are enough to place the step and the slope on either side of it.

A detail I did not expect: depths 1 and 2 have more variance than depth 3. With so few splits, where the cut-offs land jumps around a lot between samples. The general trend (more depth, more variance) holds after that.

Overfitting and underfitting

These are the everyday names (Table 3):

Table 3. Underfitting against overfitting
ItemUnderfittingOverfitting
CauseModel too simpleModel too complex
Main errorBiasVariance
Training errorHighVery low
Error on new dataHighHigh
FixMore flexible model, better featuresSimpler model, more data, or averaging

The tell-tale sign of overfitting is a big gap between training error and error on new data, like the decision tree with a perfect 1.000 on training rows and 0.742 on test rows.

The same curve on real data

On the real version of the problem, predicting next month’s volatility from this month’s for the five tickers, with one regression tree and the minimum rows per leaf swept from 1 to 200 (Table 4). The score is RMSE, the typical size of a miss in points of volatility; lower is better:

Table 4. Training and test RMSE by rows per leaf, one tree on real data
Rows per leafTraining RMSETest RMSEReading
10.00\key{0.00}18.26\risk{18.26}memorised: perfect on seen rows, worse than guessing the mean on new ones
58.3515.40already under the baseline of 17.69
2011.3613.35the gap has closed to two points
5012.5312.90the two curves have all but met
10012.8912.57test now below training
20013.3112.40\key{12.40}the best of the table, and still falling

Training error rises the whole way. Test error falls the whole way too, and at 200 rows per leaf (a fifth of the training set) it is still falling, because this target is so noisy that a tree needs to average hundreds of rows before it says anything true. The right-hand side of the U, where a too-simple tree blurs the real pattern, lies past the sizes swept here; the bagging post shows what happens when averaging, not leaf size, does the smoothing. Read any model from the two numbers (Table 5):

Table 5. Reading a model from its training and test error
Training errorTest errorDiagnosisFix
highhigh, and similarunderfit, biasa more flexible model, better features; a simpler one makes it worse
very lowmuch higheroverfit, variancea simpler model, a penalty on the weights (ridge, lasso), more or more representative data
lowlow, and similargoodtest once and stop

Two rules of thumb that go with the curve. Choose the simplest model whose validation error is within one standard error of the best (ISLP section 6.1.3 calls this the one-standard-error rule; the standard error is how much the validation score itself would wobble with different data), since a difference that small is noise. And remember that some dials run backwards: in nearest neighbours a larger kk is a simpler model, and in ridge or lasso a larger penalty is a simpler model, the opposite of tree depth and polynomial degree.

How to find the sweet spot in practice

You never know the true curve in real life, so you can’t compute bias and variance directly. Instead:

  • Hold out data. Train on part of the history, test on the rest. Only the test score counts.
  • Cross-validation. Split the data into, say, 5 parts. Train on 4, test on the 5th, rotate, and average. More reliable than one split.
  • For time series, test forward in time. In finance, never test on dates before your training data. Train on January to June, test on July. Otherwise the model quietly learns from the future.
  • Tune complexity on validation data, a slice held back from training, or on cross-validation: tree depth, number of features, and so on. Keep the real test set for one final check at the end. A setting chosen by looking at the test score makes that score look better than the model is, the subject of the scoring post.

And there’s a third option, which the bagging post builds on: keep the complex, low-bias model, but reduce its variance by averaging many of them. If each deep tree zig-zags differently, the average of many comes much closer to the real curve. That’s bagging.

The code

The simulation behind Table 2, complete, so it runs as pasted (pip install numpy scikit-learn). true_curve is the made-up truth; each round draws 80 fresh months (x is this month’s volatility, y next month’s), trains one tree, and records its predictions at 200 test points. preds ends up with 300 rows, one per trained tree, which is what makes bias and variance measurable:

import numpy as np
from sklearn.tree import DecisionTreeRegressor

def true_curve(x):
    """A made-up 'true' next-month volatility for this month's volatility x (both % a year):
    a gentle slope, plus a step up once the market is already above about 25%."""
    return 6 + 0.45 * x + 8 / (1 + np.exp(-(x - 25) / 3))

NOISE = 3.0                              # spread of the random part no model can predict
grid = np.linspace(5, 45, 200)           # 200 values of this month's volatility to test at
truth = true_curve(grid)                 # known only because we made the curve up
rng = np.random.default_rng(11)

print("depth  bias^2  variance  noise  sum    measured error on new months")
for depth in [1, 2, 3, 4, 5, 6, 8, 10, 15]:
    preds, errors = [], []
    for _ in range(300):                 # 300 different training samples of 80 months each
        sample = np.random.default_rng(rng.integers(1 << 31))
        x = sample.uniform(5, 45, 80)                        # this month's volatility
        y = true_curve(x) + sample.normal(0, NOISE, 80)      # next month's: truth plus noise
        tree = DecisionTreeRegressor(max_depth=depth, random_state=0).fit(x.reshape(-1, 1), y)
        p = tree.predict(grid.reshape(-1, 1))
        preds.append(p)
        y_new = truth + rng.normal(0, NOISE, len(grid))     # fresh months the tree never saw
        errors.append(np.mean((y_new - p) ** 2))
    preds = np.array(preds)                                  # 300 rows: one per trained tree
    bias2 = np.mean((preds.mean(axis=0) - truth) ** 2)       # how far the AVERAGE tree is off
    variance = np.mean(preds.var(axis=0))                    # how much the trees disagree
    print(f"{depth:5}  {bias2:6.2f}  {variance:8.2f}  {NOISE**2:5.2f}  "
          f"{bias2 + variance + NOISE**2:5.2f}  {np.mean(errors):5.2f}")

It prints Table 2, number for number, including the depths left out of it (4, 6 and 10). preds.mean(axis=0) averages the 300 trees at each test point (down the rows), and preds.var(axis=0) measures how much they disagree there.

The scripts behind the charts and the real-data table

Figure 1 comes from examples/bias-and-variance/bias_variance.py, the same simulation as above plus the drawing. The real-data sweep over rows per leaf is in examples/machine-learning-in-ten-ideas/ten_ideas.py; it uses the blog’s five tickers. To run it yourself, clone the examples repo: its README has a three-command Docker setup, or run uv run on it.

Summary

Table 6 is the post in six lines.

Table 6. Bias and variance in six lines
IdeaMeaningRemember it as
BiasAverage guess is off from the truthToo simple
VarianceGuess changes a lot with the training sampleToo sensitive
NoiseRandomness in the data itselfNobody can fix it
Decompositionerror=bias2+variance+noise\text{error} = \text{bias}^2 + \text{variance} + \text{noise}You can trade one for another
Overfittingtraining great, new data poorToo much variance
Fixessimpler model, more data, or average many modelsBagging attacks variance

References

Tagged machine-learning, overfitting, finance, volatility← Home