%23%20%2F%2F%2F%20script%0A%23%20requires-python%20%3D%20%22%3E%3D3.11%22%0A%23%20dependencies%20%3D%20%5B%0A%23%20%20%20%20%20%22scikit-learn%22%2C%0A%23%20%20%20%20%20%22yohou%5Bplotting%5D%22%2C%0A%23%20%5D%0A%23%20%2F%2F%2F%0A%0Aimport%20marimo%0A%0A__generated_with%20%3D%20%220.23.8%22%0Aapp%20%3D%20marimo.App(width%3D%22medium%22)%0A%0A%0A%40app.cell(hide_code%3DTrue)%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%20mo.md(r%22%22%22%0A%20%20%20%20%23%20Forecasting%20with%20Forecasted%20Features%0A%0A%20%20%20%20When%20exogenous%20features%20(X_actual)%20are%20**not%20known%20in%20advance**%20at%20prediction%20time%2C%0A%20%20%20%20you%20need%20to%20forecast%20them%20first.%20%5B%60ForecastedFeatureForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.compose.forecasted_feature_forecaster.ForecastedFeatureForecaster%2F)%20chains%20a%0A%20%20%20%20**feature%20forecaster**%20and%20a%20**target%20forecaster**%20automatically.%0A%0A%20%20%20%20**Prerequisites%3A**%20Familiarity%20with%20%5B%60PointReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.point.reduction.PointReductionForecaster%2F).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_()%3A%0A%20%20%20%20import%20polars%20as%20pl%0A%20%20%20%20from%20sklearn.linear_model%20import%20Ridge%0A%0A%20%20%20%20from%20yohou.compose%20import%20ColumnForecaster%2C%20ForecastedFeatureForecaster%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_electricity_demand%0A%20%20%20%20from%20yohou.metrics%20import%20MeanAbsoluteError%0A%20%20%20%20from%20yohou.plotting%20import%20plot_forecast%2C%20plot_time_series%0A%20%20%20%20from%20yohou.point%20import%20PointReductionForecaster%0A%20%20%20%20from%20yohou.preprocessing%20import%20LagTransformer%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20ColumnForecaster%2C%0A%20%20%20%20%20%20%20%20ForecastedFeatureForecaster%2C%0A%20%20%20%20%20%20%20%20LagTransformer%2C%0A%20%20%20%20%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20%20%20%20%20Ridge%2C%0A%20%20%20%20%20%20%20%20fetch_electricity_demand%2C%0A%20%20%20%20%20%20%20%20pl%2C%0A%20%20%20%20%20%20%20%20plot_forecast%2C%0A%20%20%20%20%20%20%20%20plot_time_series%2C%0A%20%20%20%20)%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%201.%20Prepare%20Data%20with%20Exogenous%20Features%0A%0A%20%20%20%20We'll%20forecast%20Victoria's%20electricity%20demand%20using%20NSW%20demand%20as%20an%0A%20%20%20%20exogenous%20feature%20plus%20**calendar%20features**%20(day%20of%20week%2C%20month).%0A%20%20%20%20All%20exogenous%20features%20are%20forecasted%20by%20the%20feature%20forecaster.%0A%20%20%20%20Calendar%20features%20follow%20predictable%20patterns%2C%20so%20they%20are%20easy%20to%0A%20%20%20%20forecast%20accurately.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fetch_electricity_demand%2C%20mo%2C%20pl%2C%20plot_time_series)%3A%0A%20%20%20%20raw%20%3D%20fetch_electricity_demand().frame%0A%0A%20%20%20%20%23%20Resample%20to%20daily%20for%20speed%20(drop%20trailing%20all-null%20days)%0A%20%20%20%20daily%20%3D%20(%0A%20%20%20%20%20%20%20%20raw%0A%20%20%20%20%20%20%20%20.group_by_dynamic(%22time%22%2C%20every%3D%221d%22)%0A%20%20%20%20%20%20%20%20.agg(%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22vic__demand%22).mean().alias(%22demand%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20pl.col(%22nsw__demand%22).mean().alias(%22nsw_demand%22)%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20.sort(%22time%22)%0A%20%20%20%20%20%20%20%20.drop_nulls()%0A%20%20%20%20)%0A%0A%20%20%20%20y%20%3D%20daily.select(%22time%22%2C%20%22demand%22)%0A%0A%20%20%20%20%23%20NSW%20demand%20%2B%20calendar%20features%20as%20exogenous%0A%20%20%20%20X_actual%20%3D%20daily.select(%0A%20%20%20%20%20%20%20%20%22time%22%2C%0A%20%20%20%20%20%20%20%20%22nsw_demand%22%2C%0A%20%20%20%20%20%20%20%20pl.col(%22time%22).dt.weekday().cast(pl.Float64).alias(%22day_of_week%22)%2C%0A%20%20%20%20%20%20%20%20pl.col(%22time%22).dt.month().cast(pl.Float64).alias(%22month%22)%2C%0A%20%20%20%20)%0A%0A%20%20%20%20from%20yohou.model_selection%20import%20train_test_split%0A%0A%20%20%20%20y_train%2C%20y_test%2C%20X_actual_train%2C%20X_actual_test%20%3D%20train_test_split(%0A%20%20%20%20%20%20%20%20y%2C%20X_actual%2C%20test_size%3D14%0A%20%20%20%20)%0A%20%20%20%20forecasting_horizon%20%3D%20len(y_test)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20plot_time_series(y%2C%20title%3D%22Target%3A%20VIC%20Demand%22)%2C%0A%20%20%20%20%20%20%20%20plot_time_series(X_actual%2C%20title%3D%22Exogenous%20Features%3A%20NSW%20Demand%20%2B%20Calendar%22)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%20X_actual_test%2C%20X_actual_train%2C%20forecasting_horizon%2C%20y_test%2C%20y_train%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%202.%20ForecastedFeatureForecaster%20with%20%22actual%22%20Strategy%0A%0A%20%20%20%20The%20default%20%60strategy%3D%22actual%22%60%20trains%20the%20target%20forecaster%20on%20actual%20X_actual%20values.%0A%20%20%20%20Simple%2C%20but%20the%20target%20model%20sees%20perfect%20features%20at%20train%20time%20vs.%20noisy%0A%20%20%20%20forecasted%20features%20at%20predict%20time.%0A%0A%20%20%20%20The%20%60feature_forecaster%60%20forecasts%20all%20exogenous%20columns%20(NSW%20demand%20and%0A%20%20%20%20calendar%20features).%20%20Calendar%20patterns%20are%20easy%20for%20the%20feature%20forecaster%0A%20%20%20%20to%20capture%2C%20while%20NSW%20demand%20requires%20real%20forecasting%20effort.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20ForecastedFeatureForecaster%2C%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20X_actual_train%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20ff_actual%20%3D%20ForecastedFeatureForecaster(%0A%20%20%20%20%20%20%20%20target_forecaster%3DPointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%202%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20feature_forecaster%3DPointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%202%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20strategy%3D%22actual%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20ff_actual.fit(y_train%2C%20X_actual_train%2C%20forecasting_horizon%3Dforecasting_horizon)%0A%20%20%20%20y_pred_actual%20%3D%20ff_actual.predict(forecasting_horizon%3Dforecasting_horizon)%0A%0A%20%20%20%20print(f%22Strategy%3D'actual'%2C%20predicted%20%7Blen(y_pred_actual)%7D%20steps%22)%0A%20%20%20%20y_pred_actual.head()%0A%20%20%20%20return%20(y_pred_actual%2C)%0A%0A%0A%40app.cell%0Adef%20_(MeanAbsoluteError%2C%20y_pred_actual%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20mae_actual%20%3D%20MeanAbsoluteError()%0A%20%20%20%20mae_actual.fit(y_train)%0A%20%20%20%20score_actual%20%3D%20mae_actual.score(y_test%2C%20y_pred_actual)%0A%20%20%20%20print(f%22MAE%20(actual%20strategy)%3A%20%7Bscore_actual%3A.2f%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%203.%20Comparing%20Training%20Strategies%0A%0A%20%20%20%20The%20%60strategy%60%20parameter%20controls%20what%20features%20the%20**target%20forecaster**%0A%20%20%20%20sees%20during%20training%3A%0A%0A%20%20%20%20%7C%20Strategy%20%7C%20How%20the%20target%20trains%20%7C%20Trade-off%20%7C%0A%20%20%20%20%7C----------%7C----------------------%7C----------%7C%0A%20%20%20%20%7C%20%60%22actual%22%60%20%7C%20On%20the%20**real**%20X_actual%20values%20%7C%20Simplest%20and%20fastest%2C%20but%20the%20target%20sees%20perfect%20features%20at%20train%20time%20yet%20noisy%20forecasted%20features%20at%20test%20time%20(distribution%20shift)%20%7C%0A%20%20%20%20%7C%20%60%22predicted%22%60%20%7C%20On%20**forecasted**%20X_actual%20from%20a%20held-out%20split%20(%60split_ratio%60)%20%7C%20No%20distribution%20shift%2C%20but%20both%20forecasters%20train%20on%20less%20data%20because%20the%20training%20set%20is%20split%20in%20two%20%7C%0A%20%20%20%20%7C%20%60%22rewind%22%60%20%7C%20On%20**forecasted**%20X_actual%20produced%20by%20%60observe%60%20%2F%20%60rewind%60%20over%20the%20full%20training%20set%20%7C%20Best%20of%20both%20worlds%3A%20the%20target%20sees%20realistic%20noisy%20features%20**and**%20trains%20on%20the%20full%20dataset.%20Slower%20because%20the%20feature%20forecaster%20produces%20rolling%20predictions%20row-by-row%20%7C%0A%0A%20%20%20%20Let's%20compare%20all%20three.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20ForecastedFeatureForecaster%2C%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20X_actual_train%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20strategy_results%20%3D%20%7B%7D%0A%0A%20%20%20%20for%20strategy%20in%20%5B%22actual%22%2C%20%22predicted%22%2C%20%22rewind%22%5D%3A%0A%20%20%20%20%20%20%20%20ff%20%3D%20ForecastedFeatureForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20target_forecaster%3DPointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%202%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_forecaster%3DPointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%202%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20strategy%3Dstrategy%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20split_ratio%3D0.6%2C%20%20%23%20only%20used%20for%20%22predicted%22%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20ff.fit(y_train%2C%20X_actual_train%2C%20forecasting_horizon%3Dforecasting_horizon)%0A%20%20%20%20%20%20%20%20_pred%20%3D%20ff.predict(forecasting_horizon%3Dforecasting_horizon)%0A%0A%20%20%20%20%20%20%20%20_scorer%20%3D%20MeanAbsoluteError()%0A%20%20%20%20%20%20%20%20_scorer.fit(y_train)%0A%20%20%20%20%20%20%20%20_score%20%3D%20_scorer.score(y_test%2C%20_pred)%0A%0A%20%20%20%20%20%20%20%20strategy_results%5Bf%22Forecast%20with%20%7Bstrategy%7D%20strategy%22%5D%20%3D%20%7B%22pred%22%3A%20_pred%2C%20%22mae%22%3A%20_score%7D%0A%20%20%20%20%20%20%20%20print(f%22strategy%3D%7Bstrategy%3A%3E10s%7D%20%20MAE%3A%20%7B_score%3A.2f%7D%22)%0A%20%20%20%20return%20(strategy_results%2C)%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%5B%60plot_forecast%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.forecasting.plot_forecast%2F)%20overlays%20predictions%20from%20all%20three%20strategies%20against%20the%0A%20%20%20%20test%20actuals%20so%20you%20can%20visually%20compare%20%60%22actual%22%60%2C%20%60%22predicted%22%60%2C%20and%0A%20%20%20%20%60%22rewind%22%60.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_forecast%2C%20strategy_results%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20preds_dict%20%3D%20%7Bname%3A%20r%5B%22pred%22%5D%20for%20name%2C%20r%20in%20strategy_results.items()%7D%0A%20%20%20%20plot_forecast(%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20preds_dict%2C%0A%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20n_history%3D365%2C%0A%20%20%20%20%20%20%20%20title%3D%22ForecastedFeatureForecaster%3A%20Strategy%20Comparison%22%2C%0A%20%20%20%20)%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%204.%20Update%20Workflow%0A%0A%20%20%20%20%5B%60ForecastedFeatureForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.compose.forecasted_feature_forecaster.ForecastedFeatureForecaster%2F)%20supports%20%60observe%60%20for%20rolling%20evaluation.%0A%20%20%20%20New%20observations%20are%20passed%20to%20both%20the%20target%20and%20feature%20forecasters%0A%20%20%20%20simultaneously%2C%20updating%20their%20internal%20buffers%20without%20refitting.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20ForecastedFeatureForecaster%2C%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20X_actual_test%2C%0A%20%20%20%20X_actual_train%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20pl%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20ff_rolling%20%3D%20ForecastedFeatureForecaster(%0A%20%20%20%20%20%20%20%20target_forecaster%3DPointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%202%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20feature_forecaster%3DPointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%202%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20strategy%3D%22actual%22%2C%0A%20%20%20%20)%0A%20%20%20%20ff_rolling.fit(y_train%2C%20X_actual_train%2C%20forecasting_horizon%3Dforecasting_horizon)%0A%0A%20%20%20%20step%20%3D%20forecasting_horizon%0A%20%20%20%20rolling_preds%20%3D%20%5B%5D%0A%0A%20%20%20%20for%20i%20in%20range(0%2C%20len(y_test)%2C%20step)%3A%0A%20%20%20%20%20%20%20%20chunk_y%20%3D%20y_test.slice(i%2C%20min(step%2C%20len(y_test)%20-%20i))%0A%20%20%20%20%20%20%20%20chunk_X%20%3D%20X_actual_test.slice(i%2C%20min(step%2C%20len(X_actual_test)%20-%20i))%0A%20%20%20%20%20%20%20%20if%20len(chunk_y)%20%3D%3D%200%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20break%0A%20%20%20%20%20%20%20%20_rpred%20%3D%20ff_rolling.predict(forecasting_horizon%3Dlen(chunk_y))%0A%20%20%20%20%20%20%20%20rolling_preds.append(_rpred)%0A%20%20%20%20%20%20%20%20ff_rolling.observe(chunk_y%2C%20chunk_X)%0A%0A%20%20%20%20all_preds%20%3D%20pl.concat(rolling_preds)%0A%20%20%20%20y_test_aligned%20%3D%20y_test.head(len(all_preds))%0A%0A%20%20%20%20mae_rolling%20%3D%20MeanAbsoluteError()%0A%20%20%20%20mae_rolling.fit(y_train)%0A%20%20%20%20score_rolling%20%3D%20mae_rolling.score(y_test_aligned%2C%20all_preds)%0A%0A%20%20%20%20print(f%22Rolling%20evaluation%3A%20%7Blen(rolling_preds)%7D%20windows%22)%0A%20%20%20%20print(f%22Rolling%20MAE%3A%20%7Bscore_rolling%3A.2f%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%205.%20Known-in-Advance%20Features%20with%20ColumnForecaster%0A%0A%20%20%20%20Calendar%20features%20like%20%60day_of_week%60%20and%20%60month%60%20are%20**known%20in%20advance**%3A%0A%20%20%20%20we%20always%20know%20what%20day%20it%20will%20be%20tomorrow.%20%20Forecasting%20them%20wastes%0A%20%20%20%20effort%20and%20adds%20noise.%0A%0A%20%20%20%20The%20trick%3A%20use%20a%20%5B%60ColumnForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.compose.column_forecaster.ColumnForecaster%2F)%20as%20the%20%60feature_forecaster%60%20that%0A%20%20%20%20only%20forecasts%20%60nsw_demand%60%20and%20**drops**%20the%20calendar%20columns.%20%20At%0A%20%20%20%20predict%20time%2C%20pass%20the%20known%20calendar%20values%20via%20%60X_actual%60%20so%20they%20are%20merged%0A%20%20%20%20back%20in%20for%20the%20target%20forecaster.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20ColumnForecaster%2C%0A%20%20%20%20ForecastedFeatureForecaster%2C%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20X_actual_test%2C%0A%20%20%20%20X_actual_train%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20plot_forecast%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20ff_known%20%3D%20ForecastedFeatureForecaster(%0A%20%20%20%20%20%20%20%20target_forecaster%3DPointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%202%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20feature_forecaster%3DColumnForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20forecasters%3D%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22nsw%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20PointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%202%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22nsw_demand%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20remainder%3D%22drop%22%2C%20%20%23%20calendar%20columns%20are%20NOT%20forecasted%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20strategy%3D%22actual%22%2C%0A%20%20%20%20)%0A%0A%20%20%20%20ff_known.fit(y_train%2C%20X_actual_train%2C%20forecasting_horizon%3Dforecasting_horizon)%0A%0A%20%20%20%20%23%20Pass%20known%20calendar%20features%20via%20X_actual%20at%20predict%20time%0A%20%20%20%20X_known%20%3D%20X_actual_test.select(%22time%22%2C%20%22day_of_week%22%2C%20%22month%22)%0A%20%20%20%20y_pred_known%20%3D%20ff_known.predict(forecasting_horizon%3Dforecasting_horizon%2C%20X_future%3DX_known)%0A%0A%20%20%20%20mae_known%20%3D%20MeanAbsoluteError()%0A%20%20%20%20mae_known.fit(y_train)%0A%20%20%20%20score_known%20%3D%20mae_known.score(y_test%2C%20y_pred_known)%0A%20%20%20%20print(f%22MAE%20(known-ahead%20calendar)%3A%20%7Bscore_known%3A.2f%7D%22)%0A%0A%20%20%20%20plot_forecast(%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20y_pred_known%2C%0A%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20n_history%3D60%2C%0A%20%20%20%20%20%20%20%20title%3D%22Known-in-Advance%20Calendar%20Features%22%2C%0A%20%20%20%20)%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%20Next%20Steps%0A%0A%20%20%20%20-%20**Multi-column**%3A%20See%20%5B%60multi_column_forecasting.py%60%5D(%2Fexamples%2Fpanel-data%2Fmulti_column_forecasting%2F)%20for%20%5B%60ColumnForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.compose.column_forecaster.ColumnForecaster%2F)%0A%20%20%20%20-%20**Interval%20forecasting**%3A%20See%20%5BInterval%5D(%2Fexamples%2F%23interval-forecasting)%20for%20prediction%20intervals%0A%20%20%20%20-%20**Decomposition**%3A%20See%20%5BStationarity%5D(%2Fexamples%2F%23stationarity)%20for%20%5B%60DecompositionPipeline%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.compose.decomposition_pipeline.DecompositionPipeline%2F)%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
70fbb2398fa9c9f1510e19b0a090cc3d