%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%20Panel%20Point%20Forecasting%0A%0A%20%20%20%20When%20panel%20data%20is%20passed%20to%20a%20forecaster%2C%20each%20group%20(%60__%60-separated%0A%20%20%20%20column%20prefix)%20is%20modelled%20independently.%20This%20notebook%20compares%0A%20%20%20%20global%20models%2C%20per-group%20specialisation%20with%20%5B%60ColumnForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.compose.column_forecaster.ColumnForecaster%2F)%2C%0A%20%20%20%20and%20selective%20group%20operations.%0A%0A%20%20%20%20%23%23%201.%20Prepare%20Panel%20Data%0A%0A%20%20%20%20We%20load%20the%20KDD%20Cup%202018%20air%20quality%20dataset%20with%203%20Beijing%20stations%0A%20%20%20%20each%20monitoring%206%20pollutants.%20%5B%60inspect_panel%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.utils.panel.inspect_panel%2F)%20discovers%20the%20panel%0A%20%20%20%20groups%20from%20the%20%60__%60%20separator%20in%20column%20names.%20The%20data%20is%20split%0A%20%20%20%2085%2F15%20into%20train%20and%20test%20sets.%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%20from%20copy%20import%20deepcopy%0A%0A%20%20%20%20from%20sklearn.linear_model%20import%20Ridge%0A%20%20%20%20from%20sklearn.tree%20import%20DecisionTreeRegressor%0A%0A%20%20%20%20from%20yohou.compose%20import%20ColumnForecaster%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_kdd_cup%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%20(%0A%20%20%20%20%20%20%20%20plot_forecast%2C%0A%20%20%20%20%20%20%20%20plot_group_scores%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)%0A%20%20%20%20from%20yohou.point%20import%20PointReductionForecaster%2C%20SeasonalNaive%0A%20%20%20%20from%20yohou.preprocessing%20import%20LagTransformer%0A%20%20%20%20from%20yohou.utils.panel%20import%20inspect_panel%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%20DecisionTreeRegressor%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%20SeasonalNaive%2C%0A%20%20%20%20%20%20%20%20deepcopy%2C%0A%20%20%20%20%20%20%20%20fetch_kdd_cup%2C%0A%20%20%20%20%20%20%20%20inspect_panel%2C%0A%20%20%20%20%20%20%20%20plot_forecast%2C%0A%20%20%20%20%20%20%20%20plot_group_scores%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_kdd_cup%2C%20inspect_panel%2C%20mo%2C%20plot_time_series%2C%20train_test_split)%3A%0A%20%20%20%20_bunch%20%3D%20fetch_kdd_cup(n_groups%3D3)%0A%20%20%20%20_df%20%3D%20_bunch.frame.drop_nulls().tail(300)%0A%20%20%20%20_globals%2C%20groups%20%3D%20inspect_panel(_df)%0A%20%20%20%20_target_cols%20%3D%20%5Bc%20for%20c%20in%20_df.columns%20if%20c%20!%3D%20%22time%22%5D%0A%20%20%20%20y%20%3D%20_df.select(%22time%22%2C%20*_target_cols)%0A%0A%20%20%20%20y_train%2C%20y_test%20%3D%20train_test_split(y%2C%20test_size%3D0.15)%0A%20%20%20%20horizon%20%3D%20len(y_test)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22**Panel%20groups**%3A%20%7Blist(groups.keys())%7D%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22**Target%20columns**%3A%20%7Blen(_target_cols)%7D%20pollutant%20series%5Cn%5Cn%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22**Train**%3A%20%7Blen(y_train)%7D%20hours%2C%20**Test**%3A%20%7Blen(y_test)%7D%20hours%2C%20%22%0A%20%20%20%20%20%20%20%20%20%20%20%20f%22**Horizon**%3A%20%7Bhorizon%7D%22%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20plot_time_series(y%2C%20title%3D%22KDD%20Cup%202018%3A%20Air%20Quality%20(3%20Stations)%22)%2C%0A%20%20%20%20%5D)%0A%20%20%20%20return%20groups%2C%20horizon%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.%20Panel%20Reduction%20Forecasting%0A%0A%20%20%20%20A%20single%20%5B%60PointReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.point.reduction.PointReductionForecaster%2F)%20applies%20the%20same%20model%20template%0A%20%20%20%20to%20every%20group.%20Each%20group%20gets%20its%20own%20fitted%20parameters%2C%20but%20shares%0A%20%20%20%20the%20same%20hyperparameters.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(LagTransformer%2C%20PointReductionForecaster%2C%20Ridge%2C%20horizon%2C%20y_train)%3A%0A%20%20%20%20fc_global%20%3D%20PointReductionForecaster(%0A%20%20%20%20%20%20%20%20estimator%3DRidge(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%2024%5D)%2C%0A%20%20%20%20)%0A%20%20%20%20fc_global.fit(y_train%2C%20forecasting_horizon%3Dhorizon)%0A%20%20%20%20y_pred_global%20%3D%20fc_global.predict(forecasting_horizon%3Dhorizon)%0A%20%20%20%20return%20fc_global%2C%20y_pred_global%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)%20with%20%60groups%60%20and%20%60n_history%60%20shows%20predictions%0A%20%20%20%20for%20selected%20groups%20in%20a%20faceted%20layout%2C%20trimmed%20to%20the%20last%2048%20time%20steps.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_forecast%2C%20y_pred_global%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20_groups%20%3D%20sorted(%7Bc.split(%22__%22)%5B0%5D%20for%20c%20in%20y_train.columns%20if%20%22__%22%20in%20c%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%20y_pred_global%2C%0A%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20n_history%3D48%2C%0A%20%20%20%20%20%20%20%20groups%3D_groups%5B%3A2%5D%2C%0A%20%20%20%20%20%20%20%20title%3D%22Global%20Ridge%20Model%3A%20Selected%20Stations%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%203.%20ColumnForecaster%3A%20Per-Group%20Specialisation%0A%0A%20%20%20%20Assign%20different%20model%20families%20to%20different%20station%20groups.%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%20DecisionTreeRegressor%2C%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20SeasonalNaive%2C%0A%20%20%20%20groups%2C%0A%20%20%20%20horizon%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20_group_names%20%3D%20sorted(groups.keys())%0A%20%20%20%20_g1_cols%20%3D%20groups%5B_group_names%5B0%5D%5D%0A%20%20%20%20_g2_cols%20%3D%20groups%5B_group_names%5B1%5D%5D%0A%20%20%20%20_g3_cols%20%3D%20groups%5B_group_names%5B2%5D%5D%0A%0A%20%20%20%20fc_column%20%3D%20ColumnForecaster(%0A%20%20%20%20%20%20%20%20forecasters%3D%5B%0A%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%22station_1_ridge%22%2C%0A%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%20estimator%3DRidge(alpha%3D1.0)%2C%0A%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%2024%5D)%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%20%20%20%20_g1_cols%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%20(%22station_2_naive%22%2C%20SeasonalNaive(seasonality%3D24)%2C%20_g2_cols)%2C%0A%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%22station_3_tree%22%2C%0A%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%20estimator%3DDecisionTreeRegressor(max_depth%3D5)%2C%0A%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%2024%2C%2048%5D)%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%20%20%20%20_g3_cols%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20)%0A%20%20%20%20fc_column.fit(y_train%2C%20forecasting_horizon%3Dhorizon)%0A%20%20%20%20y_pred_column%20%3D%20fc_column.predict(forecasting_horizon%3Dhorizon)%0A%20%20%20%20return%20(y_pred_column%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)%20for%20the%20%5B%60ColumnForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.compose.column_forecaster.ColumnForecaster%2F)%20lets%20you%20visually%20compare%20how%0A%20%20%20%20per-group%20model%20specialisation%20affects%20predictions%20for%20the%20same%20groups.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_forecast%2C%20y_pred_column%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20_groups%20%3D%20sorted(%7Bc.split(%22__%22)%5B0%5D%20for%20c%20in%20y_train.columns%20if%20%22__%22%20in%20c%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%20y_pred_column%2C%0A%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20n_history%3D48%2C%0A%20%20%20%20%20%20%20%20groups%3D_groups%5B%3A2%5D%2C%0A%20%20%20%20%20%20%20%20title%3D%22ColumnForecaster%3A%20Per-Group%20Specialisation%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.%20Selective%20Group%20Operations%0A%0A%20%20%20%20%60predict%60%2C%20%60observe%60%2C%20and%20%60rewind%60%20all%20accept%20a%20%60groups%60%0A%20%20%20%20parameter.%20%20This%20lets%20you%20predict%20a%20subset%20of%20groups%2C%20observe%20new%0A%20%20%20%20data%20for%20only%20the%20groups%20that%20have%20reported%20so%20far%20(e.g.%20some%20stations%0A%20%20%20%20report%20with%20different%20delays)%2C%20or%20rewind%20specific%20groups%20without%0A%20%20%20%20touching%20the%20rest.%0A%0A%20%20%20%20Below%20we%20demonstrate%20this%20on%20the%20first%20station%3A%20predict%20from%20the%0A%20%20%20%20training%20window%2C%20then%20observe%20new%20data%20and%20predict%20again%20(the%0A%20%20%20%20forecast%20origin%20moves%20forward)%2C%20and%20finally%20rewind%20back%20and%20predict%0A%20%20%20%20once%20more%20(the%20origin%20returns%20to%20where%20it%20was).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(deepcopy%2C%20fc_global%2C%20groups%2C%20mo%2C%20plot_forecast%2C%20y_test%2C%20y_train)%3A%0A%0A%20%20%20%20_fc%20%3D%20deepcopy(fc_global)%0A%20%20%20%20_group_name%20%3D%20sorted(groups.keys())%5B0%5D%0A%20%20%20%20_group%20%3D%20%5B_group_name%5D%0A%20%20%20%20_group_cols%20%3D%20groups%5B_group_name%5D%0A%20%20%20%20_horizon%20%3D%2012%0A%0A%20%20%20%20%23%201)%20Predict%20from%20training%20window%0A%20%20%20%20_y_pred_before%20%3D%20_fc.predict(forecasting_horizon%3D_horizon%2C%20groups%3D_group)%0A%0A%20%20%20%20%23%202)%20Observe%20the%20first%20half%20of%20test%20data%20for%20this%20station%20only%0A%20%20%20%20_half%20%3D%20len(y_test)%20%2F%2F%202%0A%20%20%20%20_y_obs%20%3D%20y_test.select(%22time%22%2C%20*_group_cols).head(_half)%0A%20%20%20%20_fc.observe(_y_obs%2C%20groups%3D_group)%0A%20%20%20%20_y_pred_after_obs%20%3D%20_fc.predict(forecasting_horizon%3D_horizon%2C%20groups%3D_group)%0A%0A%20%20%20%20%23%203)%20Rewind%20back%3A%20the%20forecast%20origin%20returns%20to%20the%20training%20window%0A%20%20%20%20_fc.rewind(y_test.select(%22time%22%2C%20*_group_cols)%2C%20groups%3D_group)%0A%20%20%20%20_y_pred_after_rwd%20%3D%20_fc.predict(forecasting_horizon%3D_horizon%2C%20groups%3D_group)%0A%0A%20%20%20%20mo.vstack(%5B%0A%20%20%20%20%20%20%20%20mo.md(%22**After%20fit**%3A%20forecast%20starts%20right%20after%20training%20data%22)%2C%0A%20%20%20%20%20%20%20%20plot_forecast(%0A%20%20%20%20%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_y_pred_before%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20groups%3D_group%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20n_history%3D24%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20title%3Df%22%7B_group_name%7D%3A%20Predict%20from%20Training%20Window%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20mo.md(f%22**After%20observe(%7B_half%7D%20rows)**%3A%20forecast%20origin%20moves%20forward%22)%2C%0A%20%20%20%20%20%20%20%20plot_forecast(%0A%20%20%20%20%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_y_pred_after_obs%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20groups%3D_group%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20n_history%3D24%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20title%3Df%22%7B_group_name%7D%3A%20Predict%20After%20Observe%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%20%20%20%20mo.md(%22**After%20rewind**%3A%20forecast%20origin%20returns%20to%20the%20training%20window%22)%2C%0A%20%20%20%20%20%20%20%20plot_forecast(%0A%20%20%20%20%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_y_pred_after_rwd%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20groups%3D_group%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20n_history%3D24%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20title%3Df%22%7B_group_name%7D%3A%20Predict%20After%20Rewind%22%2C%0A%20%20%20%20%20%20%20%20)%2C%0A%20%20%20%20%5D)%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.%20Groupwise%20Scoring%0A%0A%20%20%20%20Use%20%5B%60plot_score_time_series%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.evaluation.plot_score_time_series%2F)%20with%20%60groups%60%20to%20visualise%0A%20%20%20%20per-group%20error%20over%20time.%20%20Each%20group%20gets%20its%20own%20subplot%2C%20making%0A%20%20%20%20it%20easy%20to%20spot%20which%20groups%20are%20well-served%20by%20the%20global%20model%0A%20%20%20%20and%20which%20would%20benefit%20from%20specialisation.%0A%0A%20%20%20%20%5B%60plot_group_scores%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.evaluation.plot_group_scores%2F)%20summarises%20the%20MAE%20per%20model%0A%20%20%20%20broken%20down%20by%20group%20as%20a%20bar%20chart%2C%20box%20distribution%2C%20or%20heatmap.%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%20plot_score_time_series%2C%0A%20%20%20%20y_pred_column%2C%0A%20%20%20%20y_pred_global%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_groups%20%3D%20sorted(%7Bc.split(%22__%22)%5B0%5D%20for%20c%20in%20y_train.columns%20if%20%22__%22%20in%20c%7D)%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20_scorer%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20%7B%22Global%20Ridge%22%3A%20y_pred_global%2C%20%22ColumnForecaster%22%3A%20y_pred_column%7D%2C%0A%20%20%20%20%20%20%20%20groups%3D_groups%5B%3A2%5D%2C%0A%20%20%20%20%20%20%20%20title%3D%22MAE%20Over%20Time%20by%20Station%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20plot_group_scores%2C%0A%20%20%20%20y_pred_column%2C%0A%20%20%20%20y_pred_global%2C%0A%20%20%20%20y_test%2C%0A)%3A%0A%20%20%20%20plot_group_scores(%0A%20%20%20%20%20%20%20%20MeanAbsoluteError()%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20%7B%22Global%20Ridge%22%3A%20y_pred_global%2C%20%22ColumnForecaster%22%3A%20y_pred_column%7D%2C%0A%20%20%20%20%20%20%20%20title%3D%22Groupwise%20MAE%3A%20Global%20vs%20ColumnForecaster%22%2C%0A%20%20%20%20%20%20%20%20y_label%3D%22MAE%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(MeanAbsoluteError%2C%20plot_group_scores%2C%20y_pred_global%2C%20y_test)%3A%0A%20%20%20%20plot_group_scores(%0A%20%20%20%20%20%20%20%20MeanAbsoluteError()%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20y_pred_global%2C%0A%20%20%20%20%20%20%20%20kind%3D%22box%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Global%20Ridge%20-%20MAE%20Distribution%20by%20Group%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20plot_group_scores%2C%0A%20%20%20%20y_pred_column%2C%0A%20%20%20%20y_pred_global%2C%0A%20%20%20%20y_test%2C%0A)%3A%0A%20%20%20%20plot_group_scores(%0A%20%20%20%20%20%20%20%20MeanAbsoluteError()%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20%7B%22Global%20Ridge%22%3A%20y_pred_global%2C%20%22ColumnForecaster%22%3A%20y_pred_column%7D%2C%0A%20%20%20%20%20%20%20%20kind%3D%22heatmap%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Groupwise%20MAE%20-%20Heatmap%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**Panel%20intervals**%3A%20See%20%5B%60examples%2Finterval%2Fpanel_intervals.py%60%5D(%2Fexamples%2Fpanel-data%2Fpanel_intervals%2F)%0A%20%20%20%20-%20**Aggregation%20modes**%3A%20See%20%5B%60examples%2Fmetrics%2Faggregation_modes.py%60%5D(%2Fexamples%2Fevaluation-search%2Faggregation_modes%2F)%0A%20%20%20%20-%20**Panel%20cross-validation**%3A%20See%20%5B%60examples%2Fmodel_selection%2Fpanel_cross_validation.py%60%5D(%2Fexamples%2Fpanel-data%2Fpanel_cross_validation%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
06fe8f901b54485bfcc32473cfc72f8a