import%20marimo%0A%0A__generated_with%20%3D%20%220.25.0%22%0Aapp%20%3D%20marimo.App()%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20marimo%20as%20mo%0A%0A%20%20%20%20return%20(mo%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20METADATA%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22id%22%3A%20%22forecasting_baselines%22%2C%0A%20%20%20%20%20%20%20%20%22name%22%3A%20%22Forecasting%20Baselines%22%2C%0A%20%20%20%20%20%20%20%20%22kind%22%3A%20%22concept%22%2C%0A%20%20%20%20%20%20%20%20%22difficulty%22%3A%20%22beginner%22%2C%0A%20%20%20%20%20%20%20%20%22status%22%3A%20%22complete%22%2C%0A%20%20%20%20%20%20%20%20%22topics%22%3A%20%5B%22forecasting%22%2C%20%22evaluation%22%5D%2C%0A%20%20%20%20%20%20%20%20%22related_models%22%3A%20%5B%22tcn%22%2C%20%22modern_tcn%22%2C%20%22chronos%22%5D%2C%0A%20%20%20%20%20%20%20%20%22prerequisites%22%3A%20%5B%22metrics%22%5D%2C%0A%20%20%20%20%7D%0A%0A%20%20%20%20mo.md(f%22%23%20%7BMETADATA%5B'name'%5D%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20In%20one%20sentence%0A%0A%20%20%20%20A%20forecasting%20baseline%20is%20a%20simple%20rule%20that%20a%20more%20complex%20model%20must%20beat%20on%20the%20same%20future%20windows.%0A%0A%20%20%20%20%23%23%20Why%20start%20simple%0A%0A%20%20%20%20Time%20series%20often%20contain%20persistence%20and%20seasonality.%20Repeating%20the%20last%20observation%20or%20the%20last%20seasonal%20cycle%20can%20therefore%20be%20surprisingly%20strong.%20Without%20these%20controls%2C%20a%20neural%20network%20can%20look%20impressive%20while%20adding%20no%20useful%20predictive%20information.%0A%0A%20%20%20%20The%20baseline%20is%20not%20a%20toy%20to%20discard.%20It%20defines%20the%20minimum%20value%20created%20by%20training%2C%20tuning%2C%20and%20operating%20a%20more%20expensive%20model.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20%23%23%20Three%20reusable%20rules%0A%0A%20%20%20%20**Mean%20forecast**%0A%0A%20%20%20%20%24%24%5Chat%20y_%7BT%2Bh%7D%3D%5Cfrac%7B1%7D%7BT%7D%5Csum_%7Bt%3D1%7D%5E%7BT%7Dy_t%24%24%0A%0A%20%20%20%20Useful%20as%20a%20stable%20level%20estimate%2C%20but%20blind%20to%20recent%20changes%20and%20cycles.%0A%0A%20%20%20%20**Last-value%20forecast**%0A%0A%20%20%20%20%24%24%5Chat%20y_%7BT%2Bh%7D%3Dy_T%24%24%0A%0A%20%20%20%20Strong%20for%20slowly%20changing%20or%20random-walk-like%20series.%0A%0A%20%20%20%20**Seasonal-naive%20forecast**%0A%0A%20%20%20%20%24%24%5Chat%20y_%7BT%2Bh%7D%3Dy_%7BT%2Bh-m%7D%24%24%0A%0A%20%20%20%20Repeats%20the%20observation%20one%20season%20earlier%2C%20where%20%24m%24%20is%20the%20seasonal%20period.%0A%0A%20%20%20%20All%20baselines%20must%20use%20only%20information%20available%20at%20the%20forecast%20origin.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%0A%20%20%20%20---%0A%0A%20%20%20%20%23%23%20Notebook%20%E2%80%94%20which%20simple%20rule%20fits%20the%20structure%3F%0A%0A%20%20%20%20We%20construct%20a%20series%20with%20daily%20seasonality%20and%20a%20mild%20trend%2C%20then%20forecast%20one%20full%20cycle.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%0A%20%20%20%20rng%20%3D%20np.random.default_rng(4)%0A%20%20%20%20period%20%3D%2024%0A%20%20%20%20total%20%3D%2024%20*%2012%0A%20%20%20%20time%20%3D%20np.arange(total)%0A%20%20%20%20series%20%3D%204%20%2B%200.008%20*%20time%20%2B%20np.sin(2%20*%20np.pi%20*%20time%20%2F%20period)%0A%20%20%20%20series%20%2B%3D%20rng.normal(0%2C%200.16%2C%20total)%0A%20%20%20%20train_end%20%3D%20total%20-%20period%0A%20%20%20%20return%20np%2C%20period%2C%20plt%2C%20series%2C%20time%2C%20train_end%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20period%2C%20plt%2C%20series%2C%20time%2C%20train_end)%3A%0A%20%20%20%20history%20%3D%20series%5B%3Atrain_end%5D%0A%20%20%20%20observed%20%3D%20series%5Btrain_end%3A%5D%0A%20%20%20%20forecasts%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22mean%22%3A%20np.repeat(history.mean()%2C%20period)%2C%0A%20%20%20%20%20%20%20%20%22last%20value%22%3A%20np.repeat(history%5B-1%5D%2C%20period)%2C%0A%20%20%20%20%20%20%20%20%22seasonal%20naive%22%3A%20history%5B-period%3A%5D%2C%0A%20%20%20%20%7D%0A%20%20%20%20errors%20%3D%20%7B%0A%20%20%20%20%20%20%20%20name%3A%20np.mean(np.abs(observed%20-%20prediction))%0A%20%20%20%20%20%20%20%20for%20name%2C%20prediction%20in%20forecasts.items()%0A%20%20%20%20%7D%0A%0A%20%20%20%20fig_baselines%2C%20axes%20%3D%20plt.subplots(1%2C%202%2C%20figsize%3D(12%2C%204.5))%0A%20%20%20%20axes%5B0%5D.plot(time%5B-3%20*%20period%3Atrain_end%5D%2C%20history%5B-2%20*%20period%3A%5D%2C%20color%3D%22%2317201c%22%2C%20label%3D%22history%22)%0A%20%20%20%20axes%5B0%5D.plot(time%5Btrain_end%3A%5D%2C%20observed%2C%20color%3D%22%234f8a65%22%2C%20linewidth%3D2%2C%20label%3D%22future%22)%0A%20%20%20%20for%20name%2C%20prediction%20in%20forecasts.items()%3A%0A%20%20%20%20%20%20%20%20axes%5B0%5D.plot(time%5Btrain_end%3A%5D%2C%20prediction%2C%20label%3Dname)%0A%20%20%20%20axes%5B0%5D.axvline(train_end%20-%201%2C%20color%3D%22%2366706a%22%2C%20linestyle%3D%22--%22)%0A%20%20%20%20axes%5B0%5D.set(title%3D%22One%20forecast%20origin%22%2C%20xlabel%3D%22time%22%2C%20ylabel%3D%22value%22)%0A%20%20%20%20axes%5B0%5D.legend(frameon%3DFalse%2C%20fontsize%3D8)%0A%0A%20%20%20%20axes%5B1%5D.bar(errors.keys()%2C%20errors.values()%2C%20color%3D%5B%22%2378909c%22%2C%20%22%23d17700%22%2C%20%22%23173f32%22%5D)%0A%20%20%20%20axes%5B1%5D.set(title%3D%22Mean%20absolute%20error%22%2C%20ylabel%3D%22MAE%22)%0A%20%20%20%20axes%5B1%5D.tick_params(axis%3D%22x%22%2C%20rotation%3D20)%0A%20%20%20%20fig_baselines.tight_layout()%0A%20%20%20%20return%20(errors%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(errors%2C%20mo)%3A%0A%20%20%20%20best%20%3D%20min(errors%2C%20key%3Derrors.get)%0A%20%20%20%20mo.md(f%22%22%22%0A%20%20%20%20%23%23%20Reading%20the%20result%0A%0A%20%20%20%20The%20best%20rule%20here%20is%20**%7Bbest%7D**%20because%20the%20data-generating%20pattern%20repeats%20every%2024%20steps.%20A%20trained%20forecaster%20should%20be%20compared%20with%20this%20rule%2C%20not%20only%20with%20the%20overall%20mean.%0A%0A%20%20%20%20%23%23%20Practical%20takeaway%0A%0A%20%20%20%20Keep%20last-value%20and%20seasonal-naive%20forecasts%20in%20every%20experiment.%20Add%20complexity%20only%20when%20it%20wins%20across%20several%20chronological%20test%20windows%20and%20the%20improvement%20matters%20operationally.%0A%0A%20%20%20%20%23%23%20Continue%0A%0A%20%20%20%20Next%3A%20%5BRolling-Origin%20Backtesting%5D(%2Fconcepts%2Frolling_origin_backtesting).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0Aif%20__name__%20%3D%3D%20%22__main__%22%3A%0A%20%20%20%20app.run()%0A
932578492b9276387a51800a65abaa9a