%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%20Interval%20Reduction%20Forecasting%0A%0A%20%20%20%20%5B%60IntervalReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.interval.reduction.IntervalReductionForecaster%2F)%20produces%20prediction%20intervals%20**directly**%0A%20%20%20%20via%20quantile%20regression%2C%20without%20a%20separate%20calibration%20step.%0A%20%20%20%20Each%20coverage%20rate%20trains%20lower%2Fupper%20quantile%20models.%0A%0A%20%20%20%20**Prerequisites%3A**%20Understanding%20of%20%5B%60PointReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.point.reduction.PointReductionForecaster%2F)%20and%20prediction%20intervals.%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%20import%20plotly.graph_objects%20as%20go%0A%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_tourism_monthly%0A%20%20%20%20from%20yohou.interval%20import%20IntervalReductionForecaster%0A%20%20%20%20from%20yohou.metrics%20import%20EmpiricalCoverage%2C%20IntervalScore%2C%20MeanIntervalWidth%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_score_heatmap%2C%0A%20%20%20%20%20%20%20%20plot_score_per_vintage%2C%0A%20%20%20%20)%0A%20%20%20%20from%20yohou.preprocessing%20import%20LagTransformer%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20EmpiricalCoverage%2C%0A%20%20%20%20%20%20%20%20IntervalReductionForecaster%2C%0A%20%20%20%20%20%20%20%20IntervalScore%2C%0A%20%20%20%20%20%20%20%20LagTransformer%2C%0A%20%20%20%20%20%20%20%20MeanIntervalWidth%2C%0A%20%20%20%20%20%20%20%20deepcopy%2C%0A%20%20%20%20%20%20%20%20fetch_tourism_monthly%2C%0A%20%20%20%20%20%20%20%20go%2C%0A%20%20%20%20%20%20%20%20plot_forecast%2C%0A%20%20%20%20%20%20%20%20plot_score_heatmap%2C%0A%20%20%20%20%20%20%20%20plot_score_per_vintage%2C%0A%20%20%20%20%20%20%20%20train_test_split%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%0A%0A%20%20%20%20We%20load%20the%20Monthly%20Tourism%20dataset%20and%20split%20it%20into%20training%20and%20test%20sets.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fetch_tourism_monthly%2C%20train_test_split)%3A%0A%20%20%20%20y%20%3D%20fetch_tourism_monthly().frame.select(%22time%22%2C%20%22T1__tourists%22).drop_nulls().rename(%7B%22T1__tourists%22%3A%20%22tourists%22%7D)%0A%0A%20%20%20%20y_train%2C%20y_test%20%3D%20train_test_split(y%2C%20test_size%3D0.2)%0A%20%20%20%20forecasting_horizon%20%3D%20len(y_test)%0A%0A%20%20%20%20print(f%22Train%3A%20%7Blen(y_train)%7D%2C%20Test%3A%20%7Blen(y_test)%7D%22)%0A%20%20%20%20return%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.%20IntervalReductionForecaster%20Basics%0A%0A%20%20%20%20The%20default%20estimator%20is%20%60MultiOutputRegressor(QuantileRegressor())%60%2C%20a%0A%20%20%20%20separate%20linear%20quantile%20model%20for%20each%20output%20step.%20For%20each%20coverage%20rate%2C%0A%20%20%20%20two%20models%20are%20trained%3A%20one%20for%20the%20lower%20quantile%20and%20one%20for%20the%20upper%20quantile.%0A%20%20%20%20%60coverage_rates%60%20are%20specified%20at%20**fit%20time**%20to%20train%20the%20needed%20quantile%20models.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20IntervalReductionForecaster%2C%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20coverage_rates%20%3D%20%5B0.5%2C%200.9%5D%0A%0A%20%20%20%20interval_fc%20%3D%20IntervalReductionForecaster(%0A%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3Dlist(range(1%2C%2013)))%2C%0A%20%20%20%20)%0A%0A%20%20%20%20interval_fc.fit(%0A%20%20%20%20%20%20%20%20y_train%2C%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dforecasting_horizon%2C%0A%20%20%20%20%20%20%20%20coverage_rates%3Dcoverage_rates%2C%0A%20%20%20%20)%0A%0A%20%20%20%20y_pred_int%20%3D%20interval_fc.predict_interval(%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dforecasting_horizon%2C%0A%20%20%20%20%20%20%20%20coverage_rates%3Dcoverage_rates%2C%0A%20%20%20%20)%0A%0A%20%20%20%20print(f%22Prediction%20columns%3A%20%7By_pred_int.columns%7D%22)%0A%20%20%20%20y_pred_int.head()%0A%20%20%20%20return%20coverage_rates%2C%20interval_fc%2C%20y_pred_int%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)%20renders%20the%20quantile%20regression%20intervals%20as%20shaded%0A%20%20%20%20bands.%20Each%20%60coverage_rates%60%20entry%20produces%20a%20separate%20band.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(coverage_rates%2C%20plot_forecast%2C%20y_pred_int%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%20y_pred_int%2C%0A%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20coverage_rates%3Dcoverage_rates%2C%0A%20%20%20%20%20%20%20%20title%3D%22Quantile%20Regression%20Intervals%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.%20Evaluating%20Interval%20Quality%0A%0A%20%20%20%20We%20assess%20how%20well%20the%20prediction%20intervals%20capture%20the%20true%20values%20using%20interval-specific%20metrics.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20EmpiricalCoverage%2C%0A%20%20%20%20IntervalScore%2C%0A%20%20%20%20MeanIntervalWidth%2C%0A%20%20%20%20coverage_rates%2C%0A%20%20%20%20y_pred_int%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20for%20_scorer_cls%20in%20%5BEmpiricalCoverage%2C%20IntervalScore%2C%20MeanIntervalWidth%5D%3A%0A%20%20%20%20%20%20%20%20scorer%20%3D%20_scorer_cls(coverage_rates%3Dcoverage_rates)%0A%20%20%20%20%20%20%20%20scorer.fit(y_train)%0A%20%20%20%20%20%20%20%20score%20%3D%20scorer.score(y_test%2C%20y_pred_int)%0A%20%20%20%20%20%20%20%20print(f%22%7B_scorer_cls.__name__%7D%3A%20%7Bscore%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%204.%20Multiple%20Coverage%20Rates%0A%0A%20%20%20%20You%20can%20train%20and%20predict%20with%20as%20many%20coverage%20rates%20as%20needed.%0A%20%20%20%20Each%20rate%20adds%20lower%2Fupper%20columns%20to%20the%20prediction.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20IntervalReductionForecaster%2C%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20many_rates%20%3D%20%5B0.5%2C%200.8%2C%200.9%2C%200.95%5D%0A%0A%20%20%20%20interval_fc_many%20%3D%20IntervalReductionForecaster(%0A%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3Dlist(range(1%2C%2013)))%2C%0A%20%20%20%20)%0A%20%20%20%20interval_fc_many.fit(%0A%20%20%20%20%20%20%20%20y_train%2C%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dforecasting_horizon%2C%0A%20%20%20%20%20%20%20%20coverage_rates%3Dmany_rates%2C%0A%20%20%20%20)%0A%0A%20%20%20%20y_pred_many%20%3D%20interval_fc_many.predict_interval(%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dforecasting_horizon%2C%0A%20%20%20%20%20%20%20%20coverage_rates%3Dmany_rates%2C%0A%20%20%20%20)%0A%0A%20%20%20%20print(f%22Columns%20for%20%7Blen(many_rates)%7D%20coverage%20rates%3A%22)%0A%20%20%20%20for%20col%20in%20y_pred_many.columns%3A%0A%20%20%20%20%20%20%20%20print(f%22%20%20%7Bcol%7D%22)%0A%20%20%20%20return%20many_rates%2C%20y_pred_many%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%20all%20four%20coverage%20bands%2C%20showing%20how%20wider%0A%20%20%20%20rates%20produce%20broader%20intervals.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(many_rates%2C%20plot_forecast%2C%20y_pred_many%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%20y_pred_many%2C%0A%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20coverage_rates%3Dmany_rates%2C%0A%20%20%20%20%20%20%20%20title%3D%22Multiple%20Coverage%20Rates%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%205.%20Interval%20Width%20per%20Coverage%20Rate%0A%0A%20%20%20%20How%20much%20wider%20do%20intervals%20get%20as%20coverage%20increases%3F%0A%20%20%20%20We%20score%20%5B%60MeanIntervalWidth%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.metrics.interval.MeanIntervalWidth%2F)%20once%20per%20rate%20and%20compare%20them%0A%20%20%20%20side-by-side%20in%20a%20grouped%20bar%20chart.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(MeanIntervalWidth%2C%20go%2C%20many_rates%2C%20y_pred_many%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20_rates%20%3D%20%5B%5D%0A%20%20%20%20_widths%20%3D%20%5B%5D%0A%20%20%20%20for%20rate%20in%20many_rates%3A%0A%20%20%20%20%20%20%20%20_width_scorer%20%3D%20MeanIntervalWidth(coverage_rates%3D%5Brate%5D)%0A%20%20%20%20%20%20%20%20_width_scorer.fit(y_train)%0A%20%20%20%20%20%20%20%20_rates.append(f%22%7Brate%3A.0%25%7D%22)%0A%20%20%20%20%20%20%20%20_widths.append(_width_scorer.score(y_test%2C%20y_pred_many))%0A%0A%20%20%20%20fig%20%3D%20go.Figure(%0A%20%20%20%20%20%20%20%20go.Bar(%0A%20%20%20%20%20%20%20%20%20%20%20%20x%3D_rates%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20y%3D_widths%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20text%3D%5Bf%22%7Bw%3A.2f%7D%22%20for%20w%20in%20_widths%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20textposition%3D%22outside%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20)%0A%20%20%20%20fig.update_layout(%0A%20%20%20%20%20%20%20%20title%3D%22Mean%20Interval%20Width%20by%20Coverage%20Rate%22%2C%0A%20%20%20%20%20%20%20%20yaxis_title%3D%22Width%22%2C%0A%20%20%20%20%20%20%20%20xaxis_title%3D%22Coverage%20Rate%22%2C%0A%20%20%20%20)%0A%20%20%20%20fig%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%20Multi-vintage%20Scoring%0A%0A%20%20%20%20The%20%60observe_predict_interval%60%20method%20with%20%60stride%3D1%60%20produces%20one%0A%20%20%20%20interval%20forecast%20per%20observation%20point%2C%20creating%20multiple%20*vintages*.%0A%20%20%20%20Each%20vintage%20represents%20a%20different%20forecast%20origin%2C%20so%20you%20can%20analyse%0A%20%20%20%20how%20interval%20quality%20evolves%20as%20the%20model%20absorbs%20more%20data.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(coverage_rates%2C%20deepcopy%2C%20forecasting_horizon%2C%20interval_fc%2C%20y_test)%3A%0A%20%20%20%20_vintage_model%20%3D%20deepcopy(interval_fc)%0A%20%20%20%20y_pred_vintages%20%3D%20_vintage_model.observe_predict_interval(%0A%20%20%20%20%20%20%20%20y%3Dy_test%2C%0A%20%20%20%20%20%20%20%20stride%3D1%2C%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dforecasting_horizon%2C%0A%20%20%20%20%20%20%20%20coverage_rates%3Dcoverage_rates%2C%0A%20%20%20%20)%0A%20%20%20%20print(f%22Vintages%3A%20%7By_pred_vintages%5B'vintage_time'%5D.n_unique()%7D%22)%0A%20%20%20%20y_pred_vintages.head(10)%0A%20%20%20%20return%20(y_pred_vintages%2C)%0A%0A%0A%40app.cell%0Adef%20_(IntervalScore%2C%20y_train)%3A%0A%20%20%20%20vintage_scorer%20%3D%20IntervalScore()%0A%20%20%20%20vintage_scorer.fit(y_train)%0A%20%20%20%20return%20(vintage_scorer%2C)%0A%0A%0A%40app.cell%0Adef%20_(plot_score_per_vintage%2C%20vintage_scorer%2C%20y_pred_vintages%2C%20y_test)%3A%0A%20%20%20%20plot_score_per_vintage(%0A%20%20%20%20%20%20%20%20vintage_scorer%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20y_pred_vintages%2C%0A%20%20%20%20%20%20%20%20title%3D%22Interval%20Score%20per%20Vintage%22%2C%0A%20%20%20%20%20%20%20%20y_label%3D%22Interval%20Score%22%2C%0A%20%20%20%20%20%20%20%20height%3D380%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_score_heatmap%2C%20vintage_scorer%2C%20y_pred_vintages%2C%20y_test)%3A%0A%20%20%20%20plot_score_heatmap(%0A%20%20%20%20%20%20%20%20vintage_scorer%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20y_pred_vintages%2C%0A%20%20%20%20%20%20%20%20title%3D%22Score%20Heatmap%20(Step%20x%20Vintage)%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**Point%20strategy%20comparison**%3A%20See%20%5B%60reduction_strategies.py%60%5D(%2Fexamples%2Fgetting-started%2Freduction_strategies%2F)%20for%20multi-output%20vs%20direct%20vs%20dir-rec%0A%20%20%20%20-%20**CatBoost%20multi-quantile**%3A%20See%20%5B%60catboost_multiquantile.py%60%5D(%2Fexamples%2Fforecasting-models%2Fcatboost_multiquantile%2F)%20for%20single-model%20quantile%20prediction%0A%20%20%20%20-%20**Calibration%20plots**%3A%20Use%20%5B%60plot_calibration%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.evaluation.plot_calibration%2F)%20from%20%60yohou.plotting%60%0A%20%20%20%20-%20**Scoring**%3A%20See%20%5BMetrics%5D(%2Fexamples%2F%23metrics)%20for%20comprehensive%20interval%20metrics%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
a4bdec8a78747a2571876f7468ff94e6