%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%20Metrics%20for%20Prediction%20Interval%20Evaluation%0A%0A%20%20%20%20Prediction%20intervals%20need%20specialized%20metrics%20beyond%20point%20accuracy.%0A%20%20%20%20Yohou%20provides%205%20interval%20scorers%20that%20evaluate%20coverage%2C%20width%2C%20and%20calibration.%0A%0A%20%20%20%20**Prerequisites%3A**%20Understanding%20of%20prediction%20intervals%20from%20%60interval%2F%60%20examples.%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%20QuantileRegressor%0A%20%20%20%20from%20sklearn.multioutput%20import%20MultiOutputRegressor%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%20(%0A%20%20%20%20%20%20%20%20CalibrationError%2C%0A%20%20%20%20%20%20%20%20EmpiricalCoverage%2C%0A%20%20%20%20%20%20%20%20IntervalScore%2C%0A%20%20%20%20%20%20%20%20MeanIntervalWidth%2C%0A%20%20%20%20%20%20%20%20PinballLoss%2C%0A%20%20%20%20)%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_calibration%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%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.preprocessing%20import%20LagTransformer%0A%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20CalibrationError%2C%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%20MultiOutputRegressor%2C%0A%20%20%20%20%20%20%20%20PinballLoss%2C%0A%20%20%20%20%20%20%20%20QuantileRegressor%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%20plot_calibration%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%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(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.%20Generate%20Interval%20Predictions%0A%0A%20%20%20%20We%20fit%20an%20%5B%60IntervalReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.interval.reduction.IntervalReductionForecaster%2F)%20that%20wraps%20a%20%60QuantileRegressor%60%20with%0A%20%20%20%20a%20%5B%60LagTransformer%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.window.LagTransformer%2F)%2C%20then%20produce%20prediction%20intervals%20at%20multiple%20coverage%0A%20%20%20%20rates.%20These%20intervals%20serve%20as%20input%20for%20all%20the%20interval%20metrics%20below.%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%20MultiOutputRegressor%2C%0A%20%20%20%20QuantileRegressor%2C%0A%20%20%20%20fetch_tourism_monthly%2C%0A%20%20%20%20train_test_split%2C%0A)%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%20fh%20%3D%20len(y_test)%0A%20%20%20%20coverage_rates%20%3D%20%5B0.1%2C%200.2%2C%200.3%2C%200.4%2C%200.5%2C%200.8%2C%200.9%2C%200.95%5D%0A%0A%20%20%20%20interval_forecaster%20%3D%20IntervalReductionForecaster(%0A%20%20%20%20%20%20%20%20estimator%3DMultiOutputRegressor(QuantileRegressor(solver%3D%22highs%22))%2C%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_forecaster.fit(y_train%2C%20forecasting_horizon%3Dfh%2C%20coverage_rates%3Dcoverage_rates)%0A%20%20%20%20y_pred_int%20%3D%20interval_forecaster.predict_interval(forecasting_horizon%3Dfh%2C%20coverage_rates%3Dcoverage_rates)%0A%0A%20%20%20%20%23%20Drop%20vintage_time%3A%20not%20needed%20for%20metrics%2Fplotting%0A%20%20%20%20if%20%22vintage_time%22%20in%20y_pred_int.columns%3A%0A%20%20%20%20%20%20%20%20y_pred_int%20%3D%20y_pred_int.drop(%22vintage_time%22)%0A%0A%20%20%20%20print(f%22Coverage%20rates%3A%20%7Bcoverage_rates%7D%22)%0A%20%20%20%20print(f%22Prediction%20columns%3A%20%7By_pred_int.columns%7D%22)%0A%20%20%20%20return%20(%0A%20%20%20%20%20%20%20%20coverage_rates%2C%0A%20%20%20%20%20%20%20%20fh%2C%0A%20%20%20%20%20%20%20%20interval_forecaster%2C%0A%20%20%20%20%20%20%20%20y%2C%0A%20%20%20%20%20%20%20%20y_pred_int%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20y_train%2C%0A%20%20%20%20)%0A%0A%0A%40app.cell%0Adef%20_(plot_time_series%2C%20y)%3A%0A%20%20%20%20plot_time_series(y%2C%20title%3D%22Tourism%20Monthly%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%5B%60plot_forecast%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.forecasting.plot_forecast%2F)%20renders%20the%20prediction%20intervals%20as%20shaded%20bands%20around%20the%0A%20%20%20%20point%20forecast%2C%20with%20one%20band%20per%20coverage%20rate.%20This%20gives%20a%20visual%20check%0A%20%20%20%20that%20the%20intervals%20are%20reasonable%20before%20computing%20numeric%20metrics.%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%22Intervals%20for%20Evaluation%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%202.%20EmpiricalCoverage%0A%0A%20%20%20%20Measures%20the%20fraction%20of%20actual%20values%20falling%20within%20the%20interval.%0A%20%20%20%20A%2090%25%20interval%20should%20contain%20~90%25%20of%20observations.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(EmpiricalCoverage%2C%20coverage_rates%2C%20y_pred_int%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20ec%20%3D%20EmpiricalCoverage(coverage_rates%3D%5B0.9%5D)%0A%20%20%20%20ec.fit(y_train)%0A%20%20%20%20coverage_result%20%3D%20ec.score(y_test%2C%20y_pred_int)%0A%20%20%20%20print(%22Empirical%20Coverage%3A%22)%0A%20%20%20%20print(%22%20%20Nominal%20%E2%86%92%20Empirical%22)%0A%20%20%20%20for%20rate%20in%20coverage_rates%3A%0A%20%20%20%20%20%20%20%20print(f%22%20%20%7Brate%3A.0%25%7D%20%20%20%20%20%E2%86%92%20result%20included%22)%0A%20%20%20%20print(f%22%5Cn%20%20Result%3A%20%7Bcoverage_result%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20EmpiricalCoverage%2C%0A%20%20%20%20coverage_rates%2C%0A%20%20%20%20plot_score_time_series%2C%0A%20%20%20%20y_pred_int%2C%0A%20%20%20%20y_test%2C%0A)%3A%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20EmpiricalCoverage(coverage_rates%3Dcoverage_rates)%2C%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%20title%3D%22Empirical%20Coverage%20for%20an%20Expected%20Coverage%20of%2090%25%20per%20Timestep%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.%20IntervalScore%20(Winkler%20Score)%0A%0A%20%20%20%20The%20interval%20score%20rewards%20narrow%20intervals%20and%20penalizes%20miscoverage.%0A%20%20%20%20Lower%20is%20better.%20Combines%20both%20sharpness%20and%20calibration.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(IntervalScore%2C%20y_pred_int%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20is_scorer%20%3D%20IntervalScore(coverage_rates%3D%5B0.9%5D)%0A%20%20%20%20is_scorer.fit(y_train)%0A%20%20%20%20is_result%20%3D%20is_scorer.score(y_test%2C%20y_pred_int)%0A%20%20%20%20print(f%22Interval%20Score%3A%20%7Bis_result%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20IntervalScore%2C%0A%20%20%20%20coverage_rates%2C%0A%20%20%20%20plot_score_time_series%2C%0A%20%20%20%20y_pred_int%2C%0A%20%20%20%20y_test%2C%0A)%3A%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20IntervalScore(coverage_rates%3Dcoverage_rates)%2C%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%20title%3D%22Interval%20Score%20per%20Timestep%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.%20MeanIntervalWidth%0A%0A%20%20%20%20Simply%20the%20average%20width%20of%20the%20prediction%20interval.%0A%20%20%20%20Narrower%20is%20better%20**given%20adequate%20coverage**.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(MeanIntervalWidth%2C%20y_pred_int%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20miw%20%3D%20MeanIntervalWidth(coverage_rates%3D%5B0.9%5D)%0A%20%20%20%20miw.fit(y_train)%0A%20%20%20%20width_result%20%3D%20miw.score(y_test%2C%20y_pred_int)%0A%20%20%20%20print(f%22Mean%20Interval%20Width%3A%20%7Bwidth_result%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20MeanIntervalWidth%2C%0A%20%20%20%20coverage_rates%2C%0A%20%20%20%20plot_score_time_series%2C%0A%20%20%20%20y_pred_int%2C%0A%20%20%20%20y_test%2C%0A)%3A%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20MeanIntervalWidth(coverage_rates%3Dcoverage_rates)%2C%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%20title%3D%22Mean%20Interval%20Width%20per%20Timestep%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.%20PinballLoss%20and%20CalibrationError%0A%0A%20%20%20%20%5B%60PinballLoss%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.metrics.interval.PinballLoss%2F)%20measures%20quantile-specific%20accuracy%3A%20it%20penalizes%20under-prediction%0A%20%20%20%20and%20over-prediction%20asymmetrically%20according%20to%20the%20quantile%20level.%20Lower%0A%20%20%20%20values%20indicate%20better-calibrated%20quantile%20estimates.%0A%0A%20%20%20%20%5B%60CalibrationError%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.metrics.interval.CalibrationError%2F)%20computes%20the%20absolute%20gap%20between%20nominal%20coverage%20rates%0A%20%20%20%20and%20empirical%20coverage.%20A%20perfectly%20calibrated%20model%20has%20zero%20calibration%0A%20%20%20%20error%20at%20every%20coverage%20level.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20CalibrationError%2C%0A%20%20%20%20PinballLoss%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%20pb%20%3D%20PinballLoss(coverage_rates%3D%5B0.9%5D)%0A%20%20%20%20pb.fit(y_train)%0A%20%20%20%20pinball_result%20%3D%20pb.score(y_test%2C%20y_pred_int)%0A%20%20%20%20print(f%22Pinball%20Loss%3A%20%7Bpinball_result%7D%22)%0A%0A%20%20%20%20ce%20%3D%20CalibrationError(coverage_rates%3Dcoverage_rates)%0A%20%20%20%20ce.fit(y_train)%0A%20%20%20%20cal_result%20%3D%20ce.score(y_test%2C%20y_pred_int)%0A%20%20%20%20print(f%22Calibration%20Error%3A%20%7Bcal_result%7D%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(PinballLoss%2C%20coverage_rates%2C%20plot_score_time_series%2C%20y_pred_int%2C%20y_test)%3A%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20PinballLoss(coverage_rates%3Dcoverage_rates)%2C%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%20title%3D%22Pinball%20Loss%20per%20Timestep%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.%20Aggregation%20Methods%0A%0A%20%20%20%20Like%20point%20scorers%2C%20interval%20scorers%20support%20aggregation.%0A%20%20%20%20%60%22coveragewise%22%60%20gives%20per-coverage-rate%20scores.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(EmpiricalCoverage%2C%20coverage_rates%2C%20y_pred_int%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20ec_cw%20%3D%20EmpiricalCoverage(%0A%20%20%20%20%20%20%20%20coverage_rates%3Dcoverage_rates%2C%0A%20%20%20%20%20%20%20%20aggregation_method%3D%22coveragewise%22%2C%0A%20%20%20%20)%0A%20%20%20%20ec_cw.fit(y_train)%0A%20%20%20%20cw_result%20%3D%20ec_cw.score(y_test%2C%20y_pred_int)%0A%20%20%20%20print(%22Coverage-wise%20Empirical%20Coverage%3A%22)%0A%20%20%20%20print(cw_result)%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%207.%20Calibration%20Plot%0A%0A%20%20%20%20%5B%60plot_calibration%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.evaluation.plot_calibration%2F)%20plots%20nominal%20coverage%20(x-axis)%20against%20empirical%20coverage%0A%20%20%20%20(y-axis).%20A%20well-calibrated%20forecaster%20produces%20points%20along%20the%20diagonal.%0A%20%20%20%20Deviations%20above%20the%20diagonal%20indicate%20over-coverage%20(intervals%20too%20wide)%2C%0A%20%20%20%20while%20deviations%20below%20indicate%20under-coverage%20(intervals%20too%20narrow).%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(coverage_rates%2C%20plot_calibration%2C%20y_pred_int%2C%20y_test)%3A%0A%20%20%20%20plot_calibration(%0A%20%20%20%20%20%20%20%20y_pred_int%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20coverage_rates%3Dcoverage_rates%2C%0A%20%20%20%20%20%20%20%20columns%3D%22tourists%22%2C%0A%20%20%20%20%20%20%20%20title%3D%22Calibration%3A%20Nominal%20vs%20Empirical%20Coverage%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%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%20fh%2C%20interval_forecaster%2C%20y_test)%3A%0A%20%20%20%20_vintage_model%20%3D%20deepcopy(interval_forecaster)%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%3Dfh%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%20metrics**%3A%20See%20%5B%60point_metrics.py%60%5D(%2Fexamples%2Fevaluation-search%2Fpoint_metrics%2F)%20for%20forecast%20accuracy%20metrics%0A%20%20%20%20-%20**Model%20selection**%3A%20See%20%5BModel%20Selection%5D(%2Fexamples%2F%23model-selection)%20for%20CV%20with%20scoring%0A%20%20%20%20-%20**Time%20weighting**%3A%20See%20%60examples%2Ftime_weighted_forecasting.py%60%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
9010bc36d43e3e1744016e94ac96f0d5