%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%20Time-Weighted%20Reduction%20Forecasting%0A%0A%20%20%20%20By%20default%2C%20every%20training%20sample%20contributes%20equally%20to%20the%20fitted%0A%20%20%20%20estimator.%20With%20**time%20weighting**%20you%20can%20emphasise%20recent%20observations%2C%0A%20%20%20%20de-emphasise%20stale%20data%2C%20or%20boost%20seasonal%20positions%2C%20all%20without%0A%20%20%20%20discarding%20any%20data.%0A%0A%20%20%20%20%5B%60PointReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.point.reduction.PointReductionForecaster%2F)%20accepts%20a%20%60time_weight%60%20argument%20in%0A%20%20%20%20%60fit()%60%20and%20converts%20it%20to%20sklearn's%20%60sample_weight%60%20using%20a%20configurable%0A%20%20%20%20%60sample_weight_alignment%60%20strategy.%0A%0A%20%20%20%20This%20notebook%20shows%20how%20to%20use%20time_weight%20and%20sample_weight_alignment%20to%20emphasise%20recent%20or%20seasonal%20training%20samples%20in%20PointReductionForecaster%2C%20with%20visualisation%20of%20weight%20curves%20and%20alignment%20strategy%20comparison.%0A%0A%20%20%20%20**Prerequisites%3A**%20Familiarity%20with%20%5B%60PointReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.point.reduction.PointReductionForecaster%2F)%20(see%20%5B%60reduction_forecaster.py%60%5D(%2Fexamples%2Fgetting-started%2Freduction_forecaster%2F)).%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%20import%20polars%20as%20pl%0A%20%20%20%20from%20sklearn.linear_model%20import%20Ridge%0A%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_sunspot%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%20plot_forecast%2C%20plot_score_per_step%2C%20plot_score_summary%2C%20plot_time_weight%0A%20%20%20%20from%20yohou.point%20import%20PointReductionForecaster%0A%20%20%20%20from%20yohou.preprocessing%20import%20LagTransformer%0A%20%20%20%20from%20yohou.utils.weighting%20import%20(%0A%20%20%20%20%20%20%20%20compose_weights%2C%0A%20%20%20%20%20%20%20%20exponential_decay_weight%2C%0A%20%20%20%20%20%20%20%20linear_decay_weight%2C%0A%20%20%20%20%20%20%20%20seasonal_emphasis_weight%2C%0A%20%20%20%20)%0A%0A%20%20%20%20return%20(%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%20compose_weights%2C%0A%20%20%20%20%20%20%20%20exponential_decay_weight%2C%0A%20%20%20%20%20%20%20%20fetch_sunspot%2C%0A%20%20%20%20%20%20%20%20linear_decay_weight%2C%0A%20%20%20%20%20%20%20%20pl%2C%0A%20%20%20%20%20%20%20%20plot_forecast%2C%0A%20%20%20%20%20%20%20%20plot_score_summary%2C%0A%20%20%20%20%20%20%20%20plot_time_weight%2C%0A%20%20%20%20%20%20%20%20seasonal_emphasis_weight%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%20use%20the%20Sunspot%20dataset%20resampled%20to%20monthly%20frequency%20and%20split%20it%0A%20%20%20%20into%20training%20and%20test%20sets%20with%20a%2024-month%20forecast%20horizon.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fetch_sunspot%2C%20pl%2C%20train_test_split)%3A%0A%20%20%20%20y_raw%20%3D%20fetch_sunspot().frame%0A%20%20%20%20y%20%3D%20y_raw.group_by_dynamic(%22time%22%2C%20every%3D%221mo%22).agg(pl.col(%22sunspot_number%22).mean())%0A%0A%20%20%20%20y_train%2C%20y_test%20%3D%20train_test_split(y%2C%20test_size%3D0.05)%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%2C%20Horizon%3A%20%7Bforecasting_horizon%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.%20Weight%20Functions%0A%0A%20%20%20%20Yohou%20provides%20three%20built-in%20weight%20generators.%20Each%20returns%20a%20callable%0A%20%20%20%20%60(pl.Series)%20-%3E%20pl.Series%60%20that%20maps%20a%20time%20column%20to%20non-negative%20weights.%0A%0A%20%20%20%20%7C%20Function%20%7C%20Behaviour%20%7C%0A%20%20%20%20%7C---%7C---%7C%0A%20%20%20%20%7C%20%60exponential_decay_weight(half_life)%60%20%7C%20Halves%20weight%20every%20%60half_life%60%20steps%20from%20the%20most%20recent%20time%20%7C%0A%20%20%20%20%7C%20%60linear_decay_weight(max_steps)%60%20%7C%20Linear%20ramp%20from%200%20(oldest)%20to%201%20(newest)%20%7C%0A%20%20%20%20%7C%20%60seasonal_emphasis_weight(seasonality%2C%20emphasis)%60%20%7C%20Multiplies%20weight%20by%20%60emphasis%60%20for%20times%20matching%20the%20seasonal%20phase%20%7C%0A%0A%20%20%20%20Let's%20visualise%20each%20one%20on%20our%20training%20data.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(exponential_decay_weight%2C%20pl%2C%20plot_time_weight%2C%20y_train)%3A%0A%20%20%20%20_times%20%3D%20y_train.get_column(%22time%22)%0A%0A%20%20%20%20%23%20Build%20a%20DataFrame%20with%20each%20weight%20as%20a%20column%0A%20%20%20%20weight_df%20%3D%20pl.DataFrame(%7B%0A%20%20%20%20%20%20%20%20%22time%22%3A%20_times%2C%0A%20%20%20%20%20%20%20%20%22time_weight%22%3A%20exponential_decay_weight(half_life%3D365)(_times).to_list()%2C%0A%20%20%20%20%7D)%0A%20%20%20%20plot_time_weight(weight_df%2C%20title%3D%22Exponential%20Decay%20(half_life%3D365%20days)%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(linear_decay_weight%2C%20pl%2C%20plot_time_weight%2C%20y_train)%3A%0A%20%20%20%20_times%20%3D%20y_train.get_column(%22time%22)%0A%20%20%20%20weight_df_linear%20%3D%20pl.DataFrame(%7B%0A%20%20%20%20%20%20%20%20%22time%22%3A%20_times%2C%0A%20%20%20%20%20%20%20%20%22time_weight%22%3A%20linear_decay_weight(max_steps%3DNone)(_times).to_list()%2C%0A%20%20%20%20%7D)%0A%20%20%20%20plot_time_weight(weight_df_linear%2C%20title%3D%22Linear%20Decay%20(full%20range)%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(pl%2C%20plot_time_weight%2C%20seasonal_emphasis_weight%2C%20y_train)%3A%0A%20%20%20%20_times%20%3D%20y_train.get_column(%22time%22)%0A%20%20%20%20weight_df_seasonal%20%3D%20pl.DataFrame(%7B%0A%20%20%20%20%20%20%20%20%22time%22%3A%20_times%2C%0A%20%20%20%20%20%20%20%20%22time_weight%22%3A%20seasonal_emphasis_weight(seasonality%3D12%2C%20emphasis%3D3.0)(_times).to_list()%2C%0A%20%20%20%20%7D)%0A%20%20%20%20plot_time_weight(weight_df_seasonal%2C%20title%3D%22Seasonal%20Emphasis%20(period%3D12%2C%20emphasis%3D3x)%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.%20Composing%20Weights%0A%0A%20%20%20%20%5B%60compose_weights%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.utils.weighting.compose_weights%2F)%20multiplies%20outputs%20of%20multiple%20weight%20functions.%20This%20lets%0A%20%20%20%20you%20combine%2C%20for%20example%2C%20exponential%20recency%20with%20seasonal%20emphasis%3A%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20compose_weights%2C%0A%20%20%20%20exponential_decay_weight%2C%0A%20%20%20%20pl%2C%0A%20%20%20%20plot_time_weight%2C%0A%20%20%20%20seasonal_emphasis_weight%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20composed_fn%20%3D%20compose_weights(%0A%20%20%20%20%20%20%20%20exponential_decay_weight(half_life%3D365)%2C%0A%20%20%20%20%20%20%20%20seasonal_emphasis_weight(seasonality%3D12%2C%20emphasis%3D3.0)%2C%0A%20%20%20%20)%0A%0A%20%20%20%20_times%20%3D%20y_train.get_column(%22time%22)%0A%20%20%20%20weight_df_composed%20%3D%20pl.DataFrame(%7B%0A%20%20%20%20%20%20%20%20%22time%22%3A%20_times%2C%0A%20%20%20%20%20%20%20%20%22time_weight%22%3A%20composed_fn(_times).to_list()%2C%0A%20%20%20%20%7D)%0A%20%20%20%20plot_time_weight(weight_df_composed%2C%20title%3D%22Composed%3A%20Exponential%20Decay%20%2B%20Seasonal%20Emphasis%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.%20Fitting%20with%20Time%20Weights%0A%0A%20%20%20%20Pass%20a%20weight%20callable%20(or%20a%20DataFrame%20with%20%60%22time%22%60%20and%20%60%22weight%22%60%20columns)%0A%20%20%20%20to%20%60fit()%60%20via%20the%20%60time_weight%60%20parameter.%20The%20forecaster%20evaluates%20the%0A%20%20%20%20function%20on%20the%20training%20time%20column%20and%20converts%20it%20to%20sklearn%0A%20%20%20%20%60sample_weight%60%20during%20tabularization.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20exponential_decay_weight%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20plot_forecast%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20fc_uniform%20%3D%20PointReductionForecaster(%0A%20%20%20%20%20%20%20%20estimator%3DRidge()%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%20fc_uniform.fit(y_train%2C%20forecasting_horizon%3Dforecasting_horizon)%0A%20%20%20%20pred_uniform%20%3D%20fc_uniform.predict(forecasting_horizon%3Dforecasting_horizon)%0A%0A%20%20%20%20fc_weighted%20%3D%20PointReductionForecaster(%0A%20%20%20%20%20%20%20%20estimator%3DRidge()%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%20fc_weighted.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%20time_weight%3Dexponential_decay_weight(half_life%3D365)%2C%0A%20%20%20%20)%0A%20%20%20%20pred_weighted%20%3D%20fc_weighted.predict(forecasting_horizon%3Dforecasting_horizon)%0A%0A%20%20%20%20mae%20%3D%20MeanAbsoluteError()%0A%20%20%20%20mae.fit(y_train)%0A%20%20%20%20print(f%22MAE%20(uniform)%3A%20%20%7Bmae.score(y_test%2C%20pred_uniform)%3A.2f%7D%22)%0A%20%20%20%20print(f%22MAE%20(weighted)%3A%20%7Bmae.score(y_test%2C%20pred_weighted)%3A.2f%7D%22)%0A%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%20%7B%22Uniform%22%3A%20pred_uniform%2C%20%22Exp.%20Decay%22%3A%20pred_weighted%7D%2C%0A%20%20%20%20%20%20%20%20y_train%3Dy_train.tail(120)%2C%0A%20%20%20%20%20%20%20%20title%3D%22Uniform%20vs%20Exponential%20Decay%20Weighting%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.%20Sample%20Weight%20Alignment%0A%0A%20%20%20%20After%20tabularization%20each%20training%20sample%20covers%20a%20window%20of%20%60H%60%20future%0A%20%20%20%20steps.%20The%20original%20per-timestep%20weights%20must%20be%20collapsed%20into%20a%20single%0A%20%20%20%20%60sample_weight%60%20per%20row.%20The%20%60sample_weight_alignment%60%20parameter%20controls%0A%20%20%20%20how%3A%0A%0A%20%20%20%20%7C%20Strategy%20%7C%20Rule%20%7C%0A%20%20%20%20%7C---%7C---%7C%0A%20%20%20%20%7C%20%60%22first_step%22%60%20(default)%20%7C%20Weight%20at%20the%20first%20forecast%20step%20%60t%2B1%60%20%7C%0A%20%20%20%20%7C%20%60%22mean_step%22%60%20%7C%20Arithmetic%20mean%20across%20all%20%60H%60%20steps%20%7C%0A%20%20%20%20%7C%20%60%22weighted_mean_step%22%60%20%7C%20Exponentially%20weighted%20mean%20favouring%20near%20steps%20%7C%0A%20%20%20%20%7C%20%60%22max_weight_step%22%60%20%7C%20Maximum%20weight%20across%20%60H%60%20steps%20%7C%0A%20%20%20%20%7C%20%60%22min_weight_step%22%60%20%7C%20Minimum%20weight%20(conservative%3A%20all%20steps%20must%20be%20important)%20%7C%0A%0A%20%20%20%20The%20choice%20matters%20most%20when%20the%20weight%20function%20changes%20steeply%20across%20the%0A%20%20%20%20horizon%20window.%20Let's%20compare%20all%20five%20on%20our%20dataset.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20exponential_decay_weight%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20mo%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20_alignments%20%3D%20%5B%0A%20%20%20%20%20%20%20%20%22first_step%22%2C%0A%20%20%20%20%20%20%20%20%22mean_step%22%2C%0A%20%20%20%20%20%20%20%20%22weighted_mean_step%22%2C%0A%20%20%20%20%20%20%20%20%22max_weight_step%22%2C%0A%20%20%20%20%20%20%20%20%22min_weight_step%22%2C%0A%20%20%20%20%5D%0A%20%20%20%20_weight_fn%20%3D%20exponential_decay_weight(half_life%3D365)%0A%20%20%20%20_mae%20%3D%20MeanAbsoluteError()%0A%20%20%20%20_mae.fit(y_train)%0A%0A%20%20%20%20alignment_rows%20%3D%20%5B%5D%0A%20%20%20%20for%20_align%20in%20_alignments%3A%0A%20%20%20%20%20%20%20%20_fc%20%3D%20PointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3Dlist(range(1%2C%2013)))%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20_fc.fit(%0A%20%20%20%20%20%20%20%20%20%20%20%20y_train%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20forecasting_horizon%3Dforecasting_horizon%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20time_weight%3D_weight_fn%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20sample_weight_alignment%3D_align%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20_pred%20%3D%20_fc.predict(forecasting_horizon%3Dforecasting_horizon)%0A%20%20%20%20%20%20%20%20_score%20%3D%20_mae.score(y_test%2C%20_pred)%0A%20%20%20%20%20%20%20%20alignment_rows.append(%7B%22Strategy%22%3A%20_align%2C%20%22MAE%22%3A%20round(_score%2C%202)%7D)%0A%0A%20%20%20%20mo.ui.table(alignment_rows%2C%20label%3D%22Sample%20Weight%20Alignment%20Comparison%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%206.%20Comparing%20Weight%20Functions%0A%0A%20%20%20%20Let's%20compare%20no%20weighting%2C%20exponential%20decay%2C%20linear%20decay%2C%20and%20seasonal%0A%20%20%20%20emphasis%20side%20by%20side.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20MeanAbsoluteError%2C%0A%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20exponential_decay_weight%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20linear_decay_weight%2C%0A%20%20%20%20plot_score_summary%2C%0A%20%20%20%20seasonal_emphasis_weight%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20_weight_configs%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22Uniform%22%3A%20None%2C%0A%20%20%20%20%20%20%20%20%22Exp.%20Decay%20(365d)%22%3A%20exponential_decay_weight(half_life%3D365)%2C%0A%20%20%20%20%20%20%20%20%22Linear%20Decay%22%3A%20linear_decay_weight(max_steps%3DNone)%2C%0A%20%20%20%20%20%20%20%20%22Seasonal%20(12)%22%3A%20seasonal_emphasis_weight(seasonality%3D12%2C%20emphasis%3D3.0)%2C%0A%20%20%20%20%7D%0A%0A%20%20%20%20_y_preds%20%3D%20%7B%7D%0A%20%20%20%20for%20_label%2C%20_wfn%20in%20_weight_configs.items()%3A%0A%20%20%20%20%20%20%20%20_fc%20%3D%20PointReductionForecaster(%0A%20%20%20%20%20%20%20%20%20%20%20%20estimator%3DRidge()%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3Dlist(range(1%2C%2013)))%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20_fit_kwargs%20%3D%20%7B%22forecasting_horizon%22%3A%20forecasting_horizon%7D%0A%20%20%20%20%20%20%20%20if%20_wfn%20is%20not%20None%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20_fit_kwargs%5B%22time_weight%22%5D%20%3D%20_wfn%0A%20%20%20%20%20%20%20%20_fc.fit(y_train%2C%20**_fit_kwargs)%0A%20%20%20%20%20%20%20%20_y_preds%5B_label%5D%20%3D%20_fc.predict(forecasting_horizon%3Dforecasting_horizon)%0A%0A%20%20%20%20plot_score_summary(%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_y_preds%2C%0A%20%20%20%20%20%20%20%20title%3D%22Weight%20Function%20Comparison%20(MAE)%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%5BApply%20Time-Weighted%20Training%5D(%2Fpages%2Fhow-to%2Ftime-weighting%2F)%20for%20the%20full%20guide%0A%20%20%20%20-%20%5BBuild%20Reduction%20Forecasters%5D(%2Fpages%2Fhow-to%2Fbuild-reduction-forecasters%2F)%20for%20related%20techniques%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
a81c630bf9806546cc8cd01bdb19cd1f