%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%20Sklearn-Compatible%20Scalers%20and%20Transformers%0A%0A%20%20%20%20Yohou%20wraps%20popular%20sklearn%20preprocessing%20classes%20so%20they%20work%20natively%0A%20%20%20%20with%20polars%20DataFrames%20and%20the%20%60%22time%22%60%20column%20convention.%20Each%20wrapper%0A%20%20%20%20strips%20%60%22time%22%60%20before%20calling%20the%20underlying%20sklearn%20logic%20and%20re-attaches%0A%20%20%20%20it%20afterwards%2C%20preserving%20full%20invertibility.%0A%0A%20%20%20%20**Prerequisites%3A**%20Basic%20familiarity%20with%20sklearn%20preprocessing%20and%20%5B%60PointReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.point.reduction.PointReductionForecaster%2F)%0A%20%20%20%20(see%20%60examples%2Fquickstart.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%20copy%20import%20deepcopy%0A%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_dominick%2C%20fetch_tourism_monthly%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%20(%0A%20%20%20%20%20%20%20%20plot_forecast%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.point%20import%20PointReductionForecaster%0A%20%20%20%20from%20yohou.preprocessing%20import%20(%0A%20%20%20%20%20%20%20%20LagTransformer%2C%0A%20%20%20%20%20%20%20%20MinMaxScaler%2C%0A%20%20%20%20%20%20%20%20PolynomialFeatures%2C%0A%20%20%20%20%20%20%20%20PowerTransformer%2C%0A%20%20%20%20%20%20%20%20RobustScaler%2C%0A%20%20%20%20%20%20%20%20StandardScaler%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%20MinMaxScaler%2C%0A%20%20%20%20%20%20%20%20PointReductionForecaster%2C%0A%20%20%20%20%20%20%20%20PolynomialFeatures%2C%0A%20%20%20%20%20%20%20%20PowerTransformer%2C%0A%20%20%20%20%20%20%20%20Ridge%2C%0A%20%20%20%20%20%20%20%20RobustScaler%2C%0A%20%20%20%20%20%20%20%20StandardScaler%2C%0A%20%20%20%20%20%20%20%20deepcopy%2C%0A%20%20%20%20%20%20%20%20fetch_dominick%2C%0A%20%20%20%20%20%20%20%20fetch_tourism_monthly%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_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.%20Prepare%20Data%0A%0A%20%20%20%20We%20load%20a%20single%20monthly%20tourism%20series%20and%20split%20it%20into%20training%20and%0A%20%20%20%20test%20sets%20with%20%5B%60train_test_split%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.model_selection.split.train_test_split%2F)%20to%20preserve%20temporal%0A%20%20%20%20ordering.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fetch_tourism_monthly%2C%20plot_time_series%2C%20train_test_split)%3A%0A%20%20%20%20df%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%20%20%20%20y_train%2C%20y_test%20%3D%20train_test_split(df%2C%20test_size%3D0.15)%0A%20%20%20%20plot_time_series(y_train%2C%20title%3D%22Training%20Data%22)%0A%20%20%20%20return%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.%20StandardScaler%0A%0A%20%20%20%20Centres%20each%20column%20to%20zero%20mean%20and%20unit%20variance.%20This%20is%20the%20most%0A%20%20%20%20common%20scaler%20for%20regression%20models.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(StandardScaler%2C%20plot_time_series%2C%20y_train)%3A%0A%20%20%20%20std_scaler%20%3D%20StandardScaler()%0A%20%20%20%20y_scaled%20%3D%20std_scaler.fit_transform(y_train)%0A%20%20%20%20plot_time_series(y_scaled%2C%20title%3D%22StandardScaler%22)%0A%20%20%20%20return%20std_scaler%2C%20y_scaled%0A%0A%0A%40app.cell%0Adef%20_(plot_time_series%2C%20std_scaler%2C%20y_scaled%2C%20y_train)%3A%0A%20%20%20%20_y_inv%20%3D%20std_scaler.inverse_transform(y_scaled)%0A%20%20%20%20_combined%20%3D%20y_train.rename(%7B%22tourists%22%3A%20%22original%22%7D).join(%0A%20%20%20%20%20%20%20%20_y_inv.rename(%7B%22tourists%22%3A%20%22Inverted%20scaled%22%7D)%2C%0A%20%20%20%20%20%20%20%20on%3D%22time%22%2C%0A%20%20%20%20)%0A%20%20%20%20plot_time_series(_combined%2C%20title%3D%22RobustScaler%3A%20Original%20vs%20Scaled%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.%20MinMaxScaler%0A%0A%20%20%20%20Scales%20each%20column%20to%20the%20range%20%60%5B0%2C%201%5D%60%20(or%20a%20custom%20%60feature_range%60).%0A%20%20%20%20Useful%20when%20the%20model%20is%20sensitive%20to%20feature%20magnitudes.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(MinMaxScaler%2C%20plot_time_series%2C%20y_train)%3A%0A%20%20%20%20mm_scaler%20%3D%20MinMaxScaler()%0A%20%20%20%20_y_mm%20%3D%20mm_scaler.fit_transform(y_train)%0A%20%20%20%20plot_time_series(_y_mm%2C%20title%3D%22MinMaxScaler%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.%20RobustScaler%0A%0A%20%20%20%20Uses%20median%20and%20IQR%20instead%20of%20mean%20and%20std%2C%20making%20it%20robust%20to%20outliers.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(RobustScaler%2C%20plot_time_series%2C%20y_train)%3A%0A%20%20%20%20rob_scaler%20%3D%20RobustScaler()%0A%20%20%20%20_y_rob%20%3D%20rob_scaler.fit_transform(y_train)%0A%20%20%20%20plot_time_series(_y_rob%2C%20title%3D%22RobustScaler%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.%20Compare%20Scalers%20Visually%0A%0A%20%20%20%20%5B%60plot_time_series%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.exploration.plot_time_series%2F)%20can%20overlay%20multiple%20columns%20in%20a%20single%20chart.%20Here%0A%20%20%20%20we%20horizontally%20concatenate%20the%20outputs%20of%20three%20scalers%20so%20we%20can%0A%20%20%20%20compare%20their%20shapes%20and%20ranges%20side-by-side.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20MinMaxScaler%2C%0A%20%20%20%20RobustScaler%2C%0A%20%20%20%20StandardScaler%2C%0A%20%20%20%20pl%2C%0A%20%20%20%20plot_time_series%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20_std%20%3D%20StandardScaler().fit_transform(y_train).rename(%7B%22tourists%22%3A%20%22StandardScaler%22%7D)%0A%20%20%20%20_mm%20%3D%20MinMaxScaler().fit_transform(y_train).rename(%7B%22tourists%22%3A%20%22MinMaxScaler%22%7D)%0A%20%20%20%20_rob%20%3D%20RobustScaler().fit_transform(y_train).rename(%7B%22tourists%22%3A%20%22RobustScaler%22%7D)%0A%20%20%20%20_combined%20%3D%20pl.concat(%0A%20%20%20%20%20%20%20%20%5B%0A%20%20%20%20%20%20%20%20%20%20%20%20_std.select(%22time%22%2C%20%22StandardScaler%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_mm.select(%22MinMaxScaler%22)%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20_rob.select(%22RobustScaler%22)%2C%0A%20%20%20%20%20%20%20%20%5D%2C%0A%20%20%20%20%20%20%20%20how%3D%22horizontal%22%2C%0A%20%20%20%20)%0A%20%20%20%20plot_time_series(_combined%2C%20title%3D%22Scaler%20Comparison%20on%20Monthly%20Tourism%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.%20PowerTransformer%0A%0A%20%20%20%20%5B%60PowerTransformer%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.sklearn_wrappers.PowerTransformer%2F)%20applies%20Box-Cox%20or%20Yeo-Johnson%20transformations%20to%20make%0A%20%20%20%20data%20more%20Gaussian-like.%20%20Box-Cox%20requires%20strictly%20positive%20values%3B%0A%20%20%20%20Yeo-Johnson%20works%20with%20any%20data.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(PowerTransformer%2C%20plot_time_series%2C%20y_train)%3A%0A%20%20%20%20pw_transformer%20%3D%20PowerTransformer(method%3D%22box-cox%22)%0A%20%20%20%20_y_pw%20%3D%20pw_transformer.fit_transform(y_train)%0A%20%20%20%20_combined%20%3D%20y_train.rename(%7B%22tourists%22%3A%20%22original%22%7D).join(%0A%20%20%20%20%20%20%20%20_y_pw.rename(%7B%22tourists%22%3A%20%22Box-Cox%22%7D)%2C%0A%20%20%20%20%20%20%20%20on%3D%22time%22%2C%0A%20%20%20%20)%0A%20%20%20%20plot_time_series(_combined%2C%20title%3D%22PowerTransformer%20(Box-Cox)%3A%20Original%20vs%20Transformed%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%207.%20PolynomialFeatures%0A%0A%20%20%20%20Creates%20interaction%20and%20polynomial%20terms.%20Useful%20as%20a%20%60feature_transformer%60%0A%20%20%20%20to%20enrich%20the%20feature%20space%20before%20a%20linear%20regression.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(PolynomialFeatures%2C%20plot_time_series%2C%20y_train)%3A%0A%20%20%20%20poly%20%3D%20PolynomialFeatures(degree%3D2%2C%20include_bias%3DFalse%2C%20interaction_only%3DFalse)%0A%20%20%20%20_y_poly%20%3D%20poly.fit_transform(y_train)%0A%20%20%20%20plot_time_series(_y_poly%2C%20title%3D%22PolynomialFeatures%20(degree%3D2)%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%208.%20Inside%20a%20Forecaster%0A%0A%20%20%20%20Pass%20a%20scaler%20as%20%60target_transformer%60%20to%20automatically%20scale%20before%0A%20%20%20%20fitting%20and%20inverse-scale%20predictions.%20Here%20we%20compare%20raw%20predictions%0A%20%20%20%20with%20StandardScaler-transformed%20predictions.%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%20StandardScaler%2C%0A%20%20%20%20plot_score_time_series%2C%0A%20%20%20%20y_test%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20_horizon%20%3D%20len(y_test)%0A%0A%20%20%20%20%23%20Baseline%3A%20no%20target%20scaling%0A%20%20%20%20_fc_raw%20%3D%20PointReductionForecaster(%0A%20%20%20%20%20%20%20%20estimator%3DRidge(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%206%2C%2012%5D)%2C%0A%20%20%20%20)%0A%20%20%20%20_fc_raw.fit(y_train%2C%20forecasting_horizon%3D_horizon)%0A%20%20%20%20_y_pred_raw%20%3D%20_fc_raw.predict(forecasting_horizon%3D_horizon)%0A%0A%20%20%20%20%23%20With%20StandardScaler%20on%20target%0A%20%20%20%20fc_scaled%20%3D%20PointReductionForecaster(%0A%20%20%20%20%20%20%20%20estimator%3DRidge(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20target_transformer%3DStandardScaler()%2C%0A%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%206%2C%2012%5D)%2C%0A%20%20%20%20)%0A%20%20%20%20fc_scaled.fit(y_train%2C%20forecasting_horizon%3D_horizon)%0A%20%20%20%20y_pred_scaled%20%3D%20fc_scaled.predict(forecasting_horizon%3D_horizon)%0A%0A%20%20%20%20_scorer%20%3D%20MeanAbsoluteError()%0A%20%20%20%20_scorer.fit(y_train)%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20_scorer%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20%7B%22No%20Scaler%22%3A%20_y_pred_raw%2C%20%22StandardScaler%22%3A%20y_pred_scaled%7D%2C%0A%20%20%20%20%20%20%20%20title%3D%22MAE%20Over%20Time%3A%20No%20Scaler%20vs%20StandardScaler%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%20fc_scaled%2C%20y_pred_scaled%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%20the%20predicted%20values%20against%20the%20test%20actuals.%0A%20%20%20%20The%20%60n_history%3D36%60%20parameter%20shows%20the%20last%2036%20training%20observations%20for%0A%20%20%20%20visual%20context.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_forecast%2C%20y_pred_scaled%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_scaled%2C%0A%20%20%20%20%20%20%20%20y_train%3Dy_train%2C%0A%20%20%20%20%20%20%20%20n_history%3D36%2C%0A%20%20%20%20%20%20%20%20title%3D%22Forecast%20with%20StandardScaler%20Target%20Transform%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%209.%20With%20Panel%20Data%0A%0A%20%20%20%20When%20a%20scaler%20is%20used%20as%20%60target_transformer%60%20inside%20a%20panel-aware%0A%20%20%20%20forecaster%2C%20yohou%20fits%20a%20**separate%20scaler%20per%20panel%20group**.%20Each%0A%20%20%20%20group's%20data%20is%20scaled%20independently.%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%20PointReductionForecaster%2C%0A%20%20%20%20Ridge%2C%0A%20%20%20%20StandardScaler%2C%0A%20%20%20%20fetch_dominick%2C%0A%20%20%20%20plot_forecast%2C%0A%20%20%20%20train_test_split%2C%0A)%3A%0A%20%20%20%20_panel%20%3D%20fetch_dominick().frame.select(%0A%20%20%20%20%20%20%20%20%22time%22%2C%0A%20%20%20%20%20%20%20%20%22T7__profit%22%2C%0A%20%20%20%20%20%20%20%20%22T11__profit%22%2C%0A%20%20%20%20%20%20%20%20%22T12__profit%22%2C%0A%20%20%20%20%20%20%20%20%22T13__profit%22%2C%0A%20%20%20%20%20%20%20%20%22T15__profit%22%2C%0A%20%20%20%20%20%20%20%20%22T19__profit%22%2C%0A%20%20%20%20%20%20%20%20%22T22__profit%22%2C%0A%20%20%20%20%20%20%20%20%22T23__profit%22%2C%0A%20%20%20%20%20%20%20%20%22T24__profit%22%2C%0A%20%20%20%20)%0A%20%20%20%20_profit_cols%20%3D%20%5Bc%20for%20c%20in%20_panel.columns%20if%20c.endswith(%22__profit%22)%5D%0A%20%20%20%20_selected%20%3D%20_panel.select(%22time%22%2C%20*_profit_cols)%0A%20%20%20%20_y_train_p%2C%20_y_test_p%20%3D%20train_test_split(_selected%2C%20test_size%3D0.1)%0A%0A%20%20%20%20_fc_panel%20%3D%20PointReductionForecaster(%0A%20%20%20%20%20%20%20%20estimator%3DRidge(alpha%3D1.0)%2C%0A%20%20%20%20%20%20%20%20target_transformer%3DStandardScaler()%2C%0A%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%204%5D)%2C%0A%20%20%20%20)%0A%20%20%20%20_horizon_p%20%3D%20min(len(_y_test_p)%2C%208)%0A%20%20%20%20_fc_panel.fit(_y_train_p%2C%20forecasting_horizon%3D_horizon_p)%0A%20%20%20%20_y_pred_p%20%3D%20_fc_panel.predict(forecasting_horizon%3D_horizon_p)%0A%0A%20%20%20%20plot_forecast(%0A%20%20%20%20%20%20%20%20_y_test_p%2C%0A%20%20%20%20%20%20%20%20_y_pred_p%2C%0A%20%20%20%20%20%20%20%20y_train%3D_y_train_p%2C%0A%20%20%20%20%20%20%20%20n_history%3D20%2C%0A%20%20%20%20%20%20%20%20groups%3D%5B%22T7%22%2C%20%22T11%22%5D%2C%0A%20%20%20%20%20%20%20%20title%3D%22Panel%20Forecast%20with%20Per-Group%20StandardScaler%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%60%20method%20with%20%60stride%3D1%60%20produces%20one%20forecast%20per%0A%20%20%20%20observation%20point%2C%20creating%20multiple%20*vintages*.%20Each%20vintage%20represents%0A%20%20%20%20a%20different%20forecast%20origin%2C%20so%20you%20can%20analyse%20how%20accuracy%20evolves%20as%0A%20%20%20%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_(deepcopy%2C%20fc_scaled%2C%20y_test)%3A%0A%20%20%20%20_vintage_model%20%3D%20deepcopy(fc_scaled)%0A%20%20%20%20y_pred_vintages%20%3D%20_vintage_model.observe_predict(%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%3Dlen(y_test)%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_(MeanAbsoluteError%2C%20y_train)%3A%0A%20%20%20%20vintage_scorer%20%3D%20MeanAbsoluteError()%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%22MAE%20per%20Forecast%20Vintage%22%2C%0A%20%20%20%20%20%20%20%20y_label%3D%22MAE%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(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**Column-wise%20transforms**%3A%20See%20%5B%60examples%2Fcompose%2Fcolumn_transformer.py%60%5D(%2Fexamples%2Fdata-features%2Fcolumn_transformer%2F)%20for%20applying%20different%20scalers%20to%20different%20columns%0A%20%20%20%20-%20**Custom%20transforms**%3A%20See%20%5B%60examples%2Fpreprocessing%2Ffunction_transformer.py%60%5D(%2Fexamples%2Fdata-features%2Ffunction_transformer%2F)%20for%20wrapping%20arbitrary%20polars%20operations%0A%20%20%20%20-%20**Stationarity%20transforms**%3A%20See%20%60examples%2Fstationarity%2F%60%20for%20decomposition-based%20transforms%20(LogTransformer%2C%20BoxCoxTransformer%2C%20etc.)%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
d6d78282986fffbbd71572b2d479c170