A posterior forecast band instead of one fitted line

Today let's understand Bayesian structural time series clearly, using one long real series as the running example throughout.

The series is AirPassengers, R's own built-in dataset: the monthly count of international airline passengers, January 1949 to December 1960, 144 months in all. It starts at 112 thousand passengers and ends at 432 thousand, climbing most years with the same summer peak repeating season after season.

Here is the whole series, plotted in the order the months actually happened.

A structural model fits that climbing, seasonal shape with one best number per moving part. This lesson turns each of those numbers into a whole range of plausible ones instead.

One fitted number per state: the maximum-likelihood version

A structural model breaks a series like this one into separate moving parts: a level that drifts, a slope, a seasonal pattern, and left-over noise. Fit it once by maximum likelihood, the ordinary way, and R hands back exactly one number for how much each part is allowed to move.

Fit the structural model on the log of AirPassengers, the same fit base R's StructTS() gives you, and read off those four numbers.

RInteractive R
# Fit a structural time series model by maximum likelihood and see its one best guess per state ap <- AirPassengers log_ap <- log(ap) fit <- StructTS(log_ap, type = "BSM") fit$coef

  
#>        level        slope         seas      epsilon 
#> 0.0007718511 0.0000000000 0.0013969062 0.0000000000

level, slope, seas and epsilon are the variances of the level, the slope, the seasonal pattern and the leftover noise. Maximum likelihood searches over every possible value of those four variances and keeps the one combination that makes the observed 144 months most likely to have happened. It hands back 0.00077 for the level and 0.0014 for the seasonal swing, and nothing else: no sense of whether 0.0005 or 0.001 would have explained the data almost as well.

That is the gap this lesson closes. Instead of one best guess per variance, put a range of plausible values on each one, update that range with the data, and read the forecast's uncertainty straight out of the result.