%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%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%20Cross-Validation%20for%20Time%20Series%0A%0A%20%20%20%20Yohou%20provides%20three%20functions%20for%20cross-validated%20evaluation%20of%20forecasters%3A%0A%0A%20%20%20%20-%20%5B%60cross_val_score%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.model_selection.validation.cross_val_score%2F)%3A%20returns%20a%20DataFrame%20with%20%60split%60%20and%20%60score%60%20columns%20(simplest%20entry%20point).%0A%20%20%20%20-%20%5B%60cross_validate%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.model_selection.validation.cross_validate%2F)%3A%20returns%20a%20DataFrame%20with%20scores%20and%20timings%2C%20or%20a%20dict%20when%20extra%20outputs%20are%20requested.%0A%20%20%20%20-%20%5B%60cross_val_predict%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.model_selection.validation.cross_val_predict%2F)%3A%20returns%20out-of-fold%20predictions%20as%20a%20DataFrame.%0A%0A%20%20%20%20**Prerequisites%3A**%20Familiarity%20with%20splitters%20(see%20%60cv_splitters.py%60)%20and%20scorers%20(see%20%60point_metrics.py%60).%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%20sklearn.linear_model%20import%20Ridge%0A%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_electricity_demand%0A%20%20%20%20from%20yohou.metrics%20import%20MeanAbsoluteError%2C%20RootMeanSquaredError%0A%20%20%20%20from%20yohou.model_selection%20import%20(%0A%20%20%20%20%20%20%20%20ExpandingWindowSplitter%2C%0A%20%20%20%20%20%20%20%20cross_val_predict%2C%0A%20%20%20%20%20%20%20%20cross_val_score%2C%0A%20%20%20%20%20%20%20%20cross_validate%2C%0A%20%20%20%20)%0A%20%20%20%20from%20yohou.point%20import%20PointReductionForecaster%2C%20SeasonalNaive%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20ExpandingWindowSplitter%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%20RootMeanSquaredError%2C%0A%20%20%20%20%20%20%20%20SeasonalNaive%2C%0A%20%20%20%20%20%20%20%20cross_val_predict%2C%0A%20%20%20%20%20%20%20%20cross_val_score%2C%0A%20%20%20%20%20%20%20%20cross_validate%2C%0A%20%20%20%20%20%20%20%20fetch_electricity_demand%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.%20Setup%0A%0A%20%20%20%20Load%20the%20dataset%20and%20define%20the%20forecaster%20and%20cross-validation%20splitter%20used%20throughout.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20ExpandingWindowSplitter%2C%0A%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20fetch_electricity_demand%2C%0A)%3A%0A%20%20%20%20data%20%3D%20fetch_electricity_demand()%0A%20%20%20%20y%20%3D%20data.frame.select(%22time%22%2C%20%22vic__demand%22).drop_nulls().head(3000)%0A%0A%20%20%20%20forecaster%20%3D%20PointReductionForecaster(estimator%3DRidge())%0A%20%20%20%20cv%20%3D%20ExpandingWindowSplitter(n_splits%3D5%2C%20test_size%3D14)%0A%20%20%20%20fh%20%3D%2014%0A%0A%20%20%20%20print(f%22Series%20length%3A%20%7Blen(y)%7D%2C%20Forecasting%20horizon%3A%20%7Bfh%7D%22)%0A%20%20%20%20return%20cv%2C%20fh%2C%20forecaster%2C%20y%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.%20Quick%20Evaluation%20with%20%60cross_val_score%60%0A%0A%20%20%20%20%60cross_val_score%60%20is%20the%20simplest%20way%20to%20get%20per-fold%20scores.%20It%20returns%20a%20DataFrame%20with%20%60split%60%20and%20%60score%60%20columns.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(MeanAbsoluteError%2C%20cross_val_score%2C%20cv%2C%20fh%2C%20forecaster%2C%20y)%3A%0A%20%20%20%20scores%20%3D%20cross_val_score(%0A%20%20%20%20%20%20%20%20forecaster%2C%0A%20%20%20%20%20%20%20%20y%2C%0A%20%20%20%20%20%20%20%20scoring%3DMeanAbsoluteError()%2C%0A%20%20%20%20%20%20%20%20cv%3Dcv%2C%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dfh%2C%0A%20%20%20%20)%0A%20%20%20%20print(scores)%0A%20%20%20%20print(f%22Mean%3A%20%7Bscores%5B'score'%5D.mean()%3A.2f%7D%20(%2B%2F-%20%7Bscores%5B'score'%5D.std()%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.%20Detailed%20Results%20with%20%60cross_validate%60%0A%0A%20%20%20%20%60cross_validate%60%20returns%20a%20DataFrame%20with%20scores%2C%20fit%20times%2C%20and%20score%20times.%0A%20%20%20%20With%20a%20single%20scorer%20the%20score%20column%20is%20%60test_score%60.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(MeanAbsoluteError%2C%20cross_validate%2C%20cv%2C%20fh%2C%20forecaster%2C%20y)%3A%0A%20%20%20%20single_results%20%3D%20cross_validate(%0A%20%20%20%20%20%20%20%20forecaster%2C%0A%20%20%20%20%20%20%20%20y%2C%0A%20%20%20%20%20%20%20%20scoring%3DMeanAbsoluteError()%2C%0A%20%20%20%20%20%20%20%20cv%3Dcv%2C%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dfh%2C%0A%20%20%20%20)%0A%20%20%20%20print(f%22Columns%3A%20%7Bsingle_results.columns%7D%22)%0A%20%20%20%20print(single_results)%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%23%20Multi-Metric%20Evaluation%0A%0A%20%20%20%20Pass%20a%20dictionary%20of%20scorers%20to%20evaluate%20multiple%20metrics%20at%20once.%0A%20%20%20%20The%20DataFrame%20columns%20follow%20the%20pattern%20%60test_%7Bname%7D%60%20for%20each%20scorer%20name.%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%20RootMeanSquaredError%2C%0A%20%20%20%20cross_validate%2C%0A%20%20%20%20cv%2C%0A%20%20%20%20fh%2C%0A%20%20%20%20forecaster%2C%0A%20%20%20%20y%2C%0A)%3A%0A%20%20%20%20multi_results%20%3D%20cross_validate(%0A%20%20%20%20%20%20%20%20forecaster%2C%0A%20%20%20%20%20%20%20%20y%2C%0A%20%20%20%20%20%20%20%20scoring%3D%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%22mae%22%3A%20MeanAbsoluteError()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%22rmse%22%3A%20RootMeanSquaredError()%2C%0A%20%20%20%20%20%20%20%20%7D%2C%0A%20%20%20%20%20%20%20%20cv%3Dcv%2C%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dfh%2C%0A%20%20%20%20)%0A%20%20%20%20print(f%22Columns%3A%20%7Bmulti_results.columns%7D%22)%0A%20%20%20%20print(multi_results)%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.%20Baseline%20Comparison%20with%20%60cross_val_score%60%0A%0A%20%20%20%20Compare%20a%20model%20against%20a%20naive%20baseline%20to%20confirm%20it%20adds%20value.%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%20SeasonalNaive%2C%0A%20%20%20%20cross_val_score%2C%0A%20%20%20%20cv%2C%0A%20%20%20%20fh%2C%0A%20%20%20%20forecaster%2C%0A%20%20%20%20y%2C%0A)%3A%0A%20%20%20%20model_scores%20%3D%20cross_val_score(%0A%20%20%20%20%20%20%20%20forecaster%2C%0A%20%20%20%20%20%20%20%20y%2C%0A%20%20%20%20%20%20%20%20scoring%3DMeanAbsoluteError()%2C%0A%20%20%20%20%20%20%20%20cv%3Dcv%2C%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dfh%2C%0A%20%20%20%20)%0A%0A%20%20%20%20baseline_scores%20%3D%20cross_val_score(%0A%20%20%20%20%20%20%20%20SeasonalNaive(seasonality%3D7)%2C%0A%20%20%20%20%20%20%20%20y%2C%0A%20%20%20%20%20%20%20%20scoring%3DMeanAbsoluteError()%2C%0A%20%20%20%20%20%20%20%20cv%3Dcv%2C%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dfh%2C%0A%20%20%20%20)%0A%0A%20%20%20%20print(f%22Model%20MAE%3A%20%20%20%20%7Bmodel_scores%5B'score'%5D.mean()%3A.2f%7D%20(%2B%2F-%20%7Bmodel_scores%5B'score'%5D.std()%3A.2f%7D)%22)%0A%20%20%20%20print(f%22Baseline%20MAE%3A%20%7Bbaseline_scores%5B'score'%5D.mean()%3A.2f%7D%20(%2B%2F-%20%7Bbaseline_scores%5B'score'%5D.std()%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.%20Out-of-Fold%20Predictions%20with%20%60cross_val_predict%60%0A%0A%20%20%20%20%60cross_val_predict%60%20returns%20a%20DataFrame%20of%20predictions%20from%20each%20fold%2C%0A%20%20%20%20with%20a%20%60split%60%20column%20identifying%20which%20fold%20produced%20each%20prediction.%0A%20%20%20%20This%20is%20useful%20for%20visualization%20and%20model%20blending%20(stacking).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(cross_val_predict%2C%20cv%2C%20fh%2C%20forecaster%2C%20y)%3A%0A%20%20%20%20predictions%20%3D%20cross_val_predict(%0A%20%20%20%20%20%20%20%20forecaster%2C%0A%20%20%20%20%20%20%20%20y%2C%0A%20%20%20%20%20%20%20%20cv%3Dcv%2C%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dfh%2C%0A%20%20%20%20)%0A%20%20%20%20print(f%22Predictions%20shape%3A%20%7Bpredictions.shape%7D%22)%0A%20%20%20%20print(f%22Columns%3A%20%7Bpredictions.columns%7D%22)%0A%20%20%20%20predictions.head(10)%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
1c7fe85dcc4a1d99c81c9482c52db049