%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%20ForecastedFeatureForecaster%0A%0A%20%20%20%20When%20exogenous%20features%20are%20not%20known%20at%20prediction%20time%2C%0A%20%20%20%20%5B%60ForecastedFeatureForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.compose.forecasted_feature_forecaster.ForecastedFeatureForecaster%2F)%20chains%20a%20feature%20forecaster%20with%0A%20%20%20%20a%20target%20forecaster.%0A%0A%20%20%20%20%23%23%201.%20Prepare%20Multivariate%20Data%0A%0A%20%20%20%20We%20use%20the%20Hospital%20dataset%20with%20T1%20as%20the%20target%20and%20T2-T4%20as%0A%20%20%20%20exogenous%20covariates.%20The%20covariates%20are%20renamed%20to%20non-panel%0A%20%20%20%20column%20names%20for%20a%20standard%20multivariate%20workflow.%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%20ForecastedFeatureForecaster%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_hospital%0A%20%20%20%20from%20yohou.metrics%20import%20MeanAbsoluteError%0A%20%20%20%20from%20yohou.model_selection%20import%20train_test_split%0A%20%20%20%20from%20yohou.plotting%20import%20plot_forecast%2C%20plot_score_time_series%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%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_hospital%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_score_time_series%2C%0A%20%20%20%20%20%20%20%20plot_time_series%2C%0A%20%20%20%20%20%20%20%20train_test_split%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(fetch_hospital%2C%20mo%2C%20pl%2C%20train_test_split)%3A%0A%20%20%20%20_hosp%20%3D%20fetch_hospital().frame%0A%20%20%20%20%23%20Select%204%20series%20and%20rename%20for%20multivariate%20analysis%0A%20%20%20%20hospital%20%3D%20_hosp.select(%0A%20%20%20%20%20%20%20%20%22time%22%2C%0A%20%20%20%20%20%20%20%20pl.col(%22T1__patients%22).alias(%22target%22)%2C%0A%20%20%20%20%20%20%20%20pl.col(%22T2__patients%22).alias(%22feature_1%22)%2C%0A%20%20%20%20%20%20%20%20pl.col(%22T3__patients%22).alias(%22feature_2%22)%2C%0A%20%20%20%20%20%20%20%20pl.col(%22T4__patients%22).alias(%22feature_3%22)%2C%0A%20%20%20%20)%0A%20%20%20%20_train_df%2C%20_test_df%20%3D%20train_test_split(hospital%2C%20test_size%3D0.15)%0A%20%20%20%20y_train%20%3D%20_train_df.select(%22time%22%2C%20%22target%22)%0A%20%20%20%20y_test%20%3D%20_test_df.select(%22time%22%2C%20%22target%22)%0A%20%20%20%20X_actual_train%20%3D%20_train_df.select(%22time%22%2C%20%22feature_1%22%2C%20%22feature_2%22%2C%20%22feature_3%22)%0A%20%20%20%20X_actual_test%20%3D%20_test_df.select(%22time%22%2C%20%22feature_1%22%2C%20%22feature_2%22%2C%20%22feature_3%22)%0A%20%20%20%20horizon%20%3D%20len(y_test)%0A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20f%22**Hospital%20(monthly)**%3A%20%7Blen(hospital)%7D%20rows%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20f%22**Target**%3A%20target%2C%20**Features**%3A%20feature_1%2C%20feature_2%2C%20feature_3%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20f%22**Train**%3A%20%7Blen(y_train)%7D%2C%20**Test**%3A%20%7Blen(y_test)%7D%22%0A%20%20%20%20)%0A%20%20%20%20return%20X_actual_train%2C%20horizon%2C%20hospital%2C%20y_test%2C%20y_train%0A%0A%0A%40app.cell%0Adef%20_(hospital%2C%20plot_time_series)%3A%0A%20%20%20%20plot_time_series(hospital%2C%20title%3D%22Hospital%20Monthly%20Patients%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%202.%20Strategy%3A%20%22actual%22%0A%0A%20%20%20%20The%20target%20forecaster%20is%20trained%20on%20actual%20feature%20values.%20At%0A%20%20%20%20prediction%20time%2C%20you%20must%20provide%20X_actual%20(or%20use%20the%20default%20forecast).%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%20horizon%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20fc_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(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%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(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%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%20fc_actual.fit(y_train%2C%20X_actual_train%2C%20forecasting_horizon%3Dhorizon)%0A%20%20%20%20y_pred_actual%20%3D%20fc_actual.predict(forecasting_horizon%3Dhorizon)%0A%20%20%20%20return%20(y_pred_actual%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%23%203.%20Strategy%3A%20%22predicted%22%0A%0A%20%20%20%20Both%20fit%20and%20predict%20use%20the%20feature%20forecaster's%20predictions.%0A%20%20%20%20This%20avoids%20train-test%20leakage.%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%20horizon%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20fc_predicted%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(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%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(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20strategy%3D%22predicted%22%2C%0A%20%20%20%20%20%20%20%20split_ratio%3D0.7%2C%0A%20%20%20%20)%0A%20%20%20%20fc_predicted.fit(y_train%2C%20X_actual_train%2C%20forecasting_horizon%3Dhorizon)%0A%20%20%20%20y_pred_predicted%20%3D%20fc_predicted.predict(forecasting_horizon%3Dhorizon)%0A%20%20%20%20return%20(y_pred_predicted%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%23%204.%20Strategy%3A%20%22rewind%22%0A%0A%20%20%20%20The%20feature%20forecaster's%20observation%20state%20is%20rewound%20before%0A%20%20%20%20prediction%2C%20providing%20a%20different%20initialisation%20point.%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%20horizon%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20fc_rewind%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(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%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(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%203%5D)%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20strategy%3D%22rewind%22%2C%0A%20%20%20%20)%0A%20%20%20%20fc_rewind.fit(y_train%2C%20X_actual_train%2C%20forecasting_horizon%3Dhorizon)%0A%20%20%20%20y_pred_rewind%20%3D%20fc_rewind.predict(forecasting_horizon%3Dhorizon)%0A%20%20%20%20return%20(y_pred_rewind%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%23%205.%20Compare%20Strategies%0A%0A%20%20%20%20%5B%60plot_score_time_series%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.evaluation.plot_score_time_series%2F)%20shows%20per-timestep%20MAE%20for%20each%20strategy%2C%0A%20%20%20%20and%20%5B%60plot_forecast%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.forecasting.plot_forecast%2F)%20overlays%20all%20three%20predictions%20against%20actuals.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20y_pred_actual%2C%0A%20%20%20%20y_pred_predicted%2C%0A%20%20%20%20y_pred_rewind%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20scorer%20%3D%20MeanAbsoluteError()%0A%20%20%20%20scorer.fit(y_train)%0A%20%20%20%20strategies%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22actual%22%3A%20y_pred_actual%2C%0A%20%20%20%20%20%20%20%20%22predicted%22%3A%20y_pred_predicted%2C%0A%20%20%20%20%20%20%20%20%22rewind%22%3A%20y_pred_rewind%2C%0A%20%20%20%20%7D%0A%20%20%20%20return%20scorer%2C%20strategies%0A%0A%0A%40app.cell%0Adef%20_(plot_score_time_series%2C%20scorer%2C%20strategies%2C%20y_test)%3A%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20scorer%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20strategies%2C%0A%20%20%20%20%20%20%20%20title%3D%22Per-Timestep%20MAE%20by%20Strategy%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_forecast%2C%20strategies%2C%20y_test%2C%20y_train)%3A%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%20strategies%2C%0A%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20n_history%3D36%2C%0A%20%20%20%20%20%20%20%20title%3D%22All%20Strategies%20vs%20Actuals%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%206.%20split_ratio%20Tuning%0A%0A%20%20%20%20%60split_ratio%60%20controls%20how%20the%20training%20data%20is%20split%20between%0A%20%20%20%20fitting%20the%20feature%20forecaster%20and%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%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%20horizon%2C%0A%20%20%20%20mo%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%20_scorer%20%3D%20MeanAbsoluteError()%0A%20%20%20%20_scorer.fit(y_train)%0A%20%20%20%20_rows%20%3D%20%5B%5D%0A%20%20%20%20for%20_ratio%20in%20%5B0.55%2C%200.65%2C%200.75%5D%3A%0A%20%20%20%20%20%20%20%20_fc%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(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%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(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%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%3D%22predicted%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20split_ratio%3D_ratio%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20_fc.fit(y_train%2C%20X_actual_train%2C%20forecasting_horizon%3Dhorizon)%0A%20%20%20%20%20%20%20%20_pred%20%3D%20_fc.predict(forecasting_horizon%3Dhorizon)%0A%20%20%20%20%20%20%20%20_mae%20%3D%20float(_scorer.score(y_test%2C%20_pred))%0A%20%20%20%20%20%20%20%20_rows.append(%7B%22split_ratio%22%3A%20_ratio%2C%20%22MAE%22%3A%20round(_mae%2C%203)%7D)%0A%0A%20%20%20%20mo.ui.table(pl.DataFrame(_rows))%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**Pipeline%20composition**%3A%20See%20%5B%60examples%2Fcompose%2Fpipeline_composition.py%60%5D(%2Fexamples%2Fdata-features%2Fpipeline_composition%2F)%0A%20%20%20%20-%20**Feature%20union**%3A%20See%20%5B%60examples%2Fcompose%2Ffeature_union.py%60%5D(%2Fexamples%2Fdata-features%2Ffeature_union%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
d9ee0fd684ebe99edebbb9821f9db417