%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%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%20How%20to%20Create%20a%20Custom%20Interval%20Forecaster%0A%0A%20%20%20%20This%20notebook%20implements%20a%20%60NaiveIntervalForecaster%60%20from%20scratch%2C%0A%20%20%20%20validates%20it%20using%20the%20built-in%20check%20generator%2C%20and%20compares%0A%20%20%20%20its%20interval%20predictions%20against%0A%20%20%20%20%5B%60SplitConformalForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.interval.split_conformal.SplitConformalForecaster%2F).%0A%0A%20%20%20%20**Prerequisites%3A**%20Familiarity%20with%20the%20fit%2Fpredict%20API%0A%20%20%20%20(%5BGetting%20Started%5D(%2Fpages%2Ftutorials%2Fgetting-started%2F))%20and%0A%20%20%20%20prediction%20intervals%20(%5BProduce%20Prediction%20Intervals%5D(%2Fpages%2Fhow-to%2Finterval-forecasting%2F)).%0A%20%20%20%20%22%22%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%201.%20Implement%20the%20Forecaster%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20polars%20as%20pl%0A%20%20%20%20import%20scipy.stats%20as%20st%0A%0A%20%20%20%20from%20yohou.interval.base%20import%20BaseIntervalForecaster%0A%20%20%20%20from%20yohou.utils.tags%20import%20Tags%0A%0A%20%20%20%20class%20NaiveIntervalForecaster(BaseIntervalForecaster)%3A%0A%20%20%20%20%20%20%20%20%22%22%22Produces%20intervals%20using%20historical%20mean%20and%20standard%20deviation.%22%22%22%0A%0A%20%20%20%20%20%20%20%20def%20__sklearn_tags__(self)%20-%3E%20Tags%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20tags%20%3D%20super().__sklearn_tags__()%0A%20%20%20%20%20%20%20%20%20%20%20%20tags.forecaster_tags.requires_exogenous%20%3D%20False%0A%20%20%20%20%20%20%20%20%20%20%20%20tags.forecaster_tags.stateful%20%3D%20True%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20tags%0A%0A%20%20%20%20%20%20%20%20%40property%0A%20%20%20%20%20%20%20%20def%20_observation_horizon(self)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20return%2010%0A%0A%20%20%20%20%20%20%20%20def%20_fit(self%2C%20y_t%2C%20X_t%2C%20forecasting_horizon)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20value_cols%20%3D%20%5Bc%20for%20c%20in%20y_t.columns%20if%20c%20!%3D%20%22time%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20self._stats%20%3D%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20col%20in%20value_cols%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20self._stats%5Bcol%5D%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22mean%22%3A%20y_t%5Bcol%5D.mean()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%22std%22%3A%20y_t%5Bcol%5D.std()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%7D%0A%0A%20%20%20%20%20%20%20%20def%20_predict_one(self%2C%20groups%2C%20coverage_rates%3DNone%2C%20**params)%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20rates%20%3D%20coverage_rates%20or%20self.fit_coverage_rates_%0A%20%20%20%20%20%20%20%20%20%20%20%20value_cols%20%3D%20list(self._stats.keys())%0A%20%20%20%20%20%20%20%20%20%20%20%20h%20%3D%20self.fit_forecasting_horizon_%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20data%20%3D%20%7B%7D%0A%20%20%20%20%20%20%20%20%20%20%20%20for%20col%20in%20value_cols%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20mean%20%3D%20self._stats%5Bcol%5D%5B%22mean%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20std_val%20%3D%20self._stats%5Bcol%5D%5B%22std%22%5D%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20for%20rate%20in%20rates%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20z%20%3D%20st.norm.ppf(0.5%20%2B%20rate%20%2F%202)%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data%5Bf%22%7Bcol%7D_lower_%7Brate%7D%22%5D%20%3D%20%5Bmean%20-%20z%20*%20std_val%5D%20*%20h%0A%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20%20data%5Bf%22%7Bcol%7D_upper_%7Brate%7D%22%5D%20%3D%20%5Bmean%20%2B%20z%20*%20std_val%5D%20*%20h%0A%0A%20%20%20%20%20%20%20%20%20%20%20%20y_pred%20%3D%20pl.DataFrame(data)%0A%20%20%20%20%20%20%20%20%20%20%20%20y_pred%20%3D%20self._add_time_columns(y_pred)%0A%20%20%20%20%20%20%20%20%20%20%20%20return%20y_pred%0A%0A%20%20%20%20return%20NaiveIntervalForecaster%2C%20pl%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.%20Fit%20and%20Predict%20Intervals%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(NaiveIntervalForecaster%2C%20pl)%3A%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_sunspot%0A%20%20%20%20from%20yohou.model_selection%20import%20train_test_split%0A%0A%20%20%20%20bunch%20%3D%20fetch_sunspot()%0A%20%20%20%20y%20%3D%20bunch.frame.group_by_dynamic(%22time%22%2C%20every%3D%221mo%22).agg(%0A%20%20%20%20%20%20%20%20pl.col(%22sunspot_number%22).mean()%0A%20%20%20%20)%0A%0A%20%20%20%20forecasting_horizon%20%3D%2024%0A%20%20%20%20y_train%2C%20y_test%20%3D%20train_test_split(y%2C%20test_size%3Dforecasting_horizon)%0A%0A%20%20%20%20forecaster%20%3D%20NaiveIntervalForecaster()%0A%20%20%20%20forecaster.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%3D%5B0.9%5D%2C%0A%20%20%20%20)%0A%20%20%20%20y_pred%20%3D%20forecaster.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%3D%5B0.9%5D%2C%0A%20%20%20%20)%0A%20%20%20%20y_pred.head()%0A%20%20%20%20return%20forecasting_horizon%2C%20y_pred%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%203.%20Score%20Against%20a%20Baseline%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(forecasting_horizon%2C%20y_pred%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20from%20yohou.interval%20import%20SplitConformalForecaster%0A%20%20%20%20from%20yohou.metrics%20import%20MeanIntervalWidth%0A%20%20%20%20from%20yohou.point%20import%20SeasonalNaive%0A%0A%20%20%20%20baseline%20%3D%20SplitConformalForecaster(%0A%20%20%20%20%20%20%20%20point_forecaster%3DSeasonalNaive(seasonality%3D12)%2C%0A%20%20%20%20)%0A%20%20%20%20baseline.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%3D%5B0.9%5D%2C%0A%20%20%20%20)%0A%20%20%20%20y_pred_baseline%20%3D%20baseline.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%3D%5B0.9%5D%2C%0A%20%20%20%20)%0A%0A%20%20%20%20scorer%20%3D%20MeanIntervalWidth()%0A%20%20%20%20scorer.fit(y_train)%0A%0A%20%20%20%20width_custom%20%3D%20scorer.score(y_test%2C%20y_pred)%0A%20%20%20%20width_baseline%20%3D%20scorer.score(y_test%2C%20y_pred_baseline)%0A%20%20%20%20print(f%22NaiveInterval%20avg%20width%3A%20%7Bwidth_custom%3A.2f%7D%22)%0A%20%20%20%20print(f%22SplitConformal%20avg%20width%3A%20%7Bwidth_baseline%3A.2f%7D%22)%0A%20%20%20%20return%20(y_pred_baseline%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.%20Plot%20the%20Comparison%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(y_pred%2C%20y_pred_baseline%2C%20y_test%2C%20y_train)%3A%0A%20%20%20%20from%20yohou.plotting%20import%20plot_forecast%0A%0A%20%20%20%20fig%20%3D%20plot_forecast(%0A%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20y_test%3Dy_test%2C%0A%20%20%20%20%20%20%20%20y_pred%3D%7B%22NaiveInterval%22%3A%20y_pred%2C%20%22SplitConformal%22%3A%20y_pred_baseline%7D%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%20Next%20Steps%0A%0A%20%20%20%20-%20%5BCreate%20an%20Interval%20Forecaster%5D(%2Fpages%2Fhow-to%2Fcreate-an-interval-forecaster%2F)%20for%20the%20full%20guide%0A%20%20%20%20-%20%5BProduce%20Prediction%20Intervals%5D(%2Fpages%2Fhow-to%2Finterval-forecasting%2F)%20for%20built-in%20approaches%0A%20%20%20%20-%20%5BCreate%20a%20Custom%20Scorer%5D(%2Fpages%2Fhow-to%2Fcreate-a-scorer%2F)%20for%20interval%20evaluation%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
b48500f34890ceb12fa71eb2e6f437e3