%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%20Class-Probability%20Forecasting%0A%0A%20%20%20%20This%20notebook%20demonstrates%20**class-probability%20forecasting**%2C%20that%20is%2C%20predicting%20the%0A%20%20%20%20probability%20distribution%20over%20categorical%20outcomes%20at%20future%20time%20steps.%0A%0A%20%20%20%20**Prerequisites%3A**%20Basic%20familiarity%20with%20sklearn's%20fit%2Fpredict%20API%20and%20classification%20concepts.%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%20sklearn.tree%20import%20DecisionTreeClassifier%0A%0A%20%20%20%20from%20yohou.class_proba%20import%20ClassProbaReductionForecaster%0A%20%20%20%20from%20yohou.datasets%20import%20fetch_air_quality_classification%2C%20fetch_demand_classification%0A%20%20%20%20from%20yohou.metrics%20import%20Accuracy%2C%20BrierScore%2C%20LogLoss%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_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%20Accuracy%2C%0A%20%20%20%20%20%20%20%20BrierScore%2C%0A%20%20%20%20%20%20%20%20ClassProbaReductionForecaster%2C%0A%20%20%20%20%20%20%20%20DecisionTreeClassifier%2C%0A%20%20%20%20%20%20%20%20LagTransformer%2C%0A%20%20%20%20%20%20%20%20LogLoss%2C%0A%20%20%20%20%20%20%20%20fetch_air_quality_classification%2C%0A%20%20%20%20%20%20%20%20fetch_demand_classification%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_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.%20Load%20the%20Data%0A%0A%20%20%20%20We%20use%20%5B%60fetch_air_quality_classification%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.datasets._fetchers.fetch_air_quality_classification%2F)%0A%20%20%20%20to%20derive%20a%20categorical%20air%20quality%20target%20from%20KDD%20Cup%202018%20PM2.5%20data.%0A%20%20%20%20The%20target%20has%204%20WHO-based%20classes%20(good%2C%20moderate%2C%20unhealthy%2C%20hazardous)%0A%20%20%20%20and%205%20pollutant%20features%20(PM10%2C%20NO2%2C%20CO%2C%20O3%2C%20SO2)%20at%20hourly%20intervals.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fetch_air_quality_classification)%3A%0A%20%20%20%20data%20%3D%20fetch_air_quality_classification()%0A%20%20%20%20y%2C%20X_actual%20%3D%20data.y%2C%20data.X_actual%0A%0A%20%20%20%20print(f%22Classes%3A%20%7Bdata.classes%7D%22)%0A%20%20%20%20print(f%22Dataset%3A%20%7Blen(y)%7D%20observations%20from%20%7By%5B'time'%5D.min()%7D%20to%20%7By%5B'time'%5D.max()%7D%22)%0A%20%20%20%20y.head(10)%0A%20%20%20%20return%20X_actual%2C%20data%2C%20y%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%23%20Explore%20the%20Features%0A%0A%20%20%20%20The%20exogenous%20features%20are%205%20pollutant%20measurements%20(PM10%2C%20NO2%2C%20CO%2C%20O3%2C%20SO2)%0A%20%20%20%20measured%20hourly.%20These%20serve%20as%20known-in-advance%20inputs%20to%20the%20forecaster.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(X_actual%2C%20plot_time_series)%3A%0A%20%20%20%20plot_time_series(X_actual%2C%20title%3D%22Pollutant%20Features%20Over%20Time%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%23%20Target%20Class%20Distribution%0A%0A%20%20%20%20The%20target%20variable%20is%20a%20WHO-based%20air%20quality%20category%20derived%20from%20PM2.5%0A%20%20%20%20concentration.%20Let's%20see%20how%20the%20classes%20are%20distributed%20over%20time.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(data%2C%20y)%3A%0A%0A%20%20%20%20target_col%20%3D%20data.target_names%5B0%5D%0A%20%20%20%20counts%20%3D%20y.group_by(target_col).len().sort(%22len%22%2C%20descending%3DTrue)%0A%20%20%20%20print(%22Class%20distribution%3A%22)%0A%20%20%20%20counts%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%23%20Categorical%20Target%20Over%20Time%0A%0A%20%20%20%20Visualizing%20the%20categorical%20target%20as%20a%20step%20chart%20reveals%20temporal%0A%20%20%20%20patterns%3A%20transitions%20between%20classes%20and%20how%20long%20each%20state%20persists.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_time_series%2C%20y)%3A%0A%20%20%20%20plot_time_series(%0A%20%20%20%20%20%20%20%20y.tail(200)%2C%0A%20%20%20%20%20%20%20%20title%3D%22Air%20Quality%20Target%20Over%20Time%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.%20Train%2FTest%20Split%0A%0A%20%20%20%20We%20hold%20out%20the%20last%20200%20hours%20for%20testing.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(X_actual%2C%20train_test_split%2C%20y)%3A%0A%20%20%20%20y_train%2C%20y_test%2C%20X_actual_train%2C%20X_actual_test%20%3D%20train_test_split(y%2C%20X_actual%2C%20test_size%3D200)%0A%20%20%20%20forecasting_horizon%20%3D%2024%0A%0A%20%20%20%20print(f%22Training%3A%20%7Blen(y_train)%7D%20obs%22)%0A%20%20%20%20print(f%22Test%3A%20%7Blen(y_test)%7D%20obs%22)%0A%20%20%20%20return%20X_actual_test%2C%20X_actual_train%2C%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%203.%20Fit%20a%20Class-Probability%20Forecaster%0A%0A%20%20%20%20%5B%60ClassProbaReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.class_proba.reduction.ClassProbaReductionForecaster%2F)%20wraps%20any%20sklearn%20classifier%20(here%2C%20a%20Decision%20Tree)%20and%0A%20%20%20%20converts%20the%20time%20series%20problem%20into%20tabular%20classification%3A%0A%0A%20%20%20%201.%20**Encode**%3A%20String%20labels%20are%20mapped%20to%20numeric%20codes%0A%20%20%20%202.%20**Tabularize**%3A%20Lag%20features%20are%20created%20from%20past%20values%0A%20%20%20%203.%20**Fit**%3A%20The%20classifier%20trains%20on%20the%20tabular%20data%0A%20%20%20%204.%20**Predict**%3A%20Recursive%20probability%20forecasting%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(%0A%20%20%20%20ClassProbaReductionForecaster%2C%0A%20%20%20%20DecisionTreeClassifier%2C%0A%20%20%20%20LagTransformer%2C%0A%20%20%20%20X_actual_train%2C%0A%20%20%20%20forecasting_horizon%2C%0A%20%20%20%20y_train%2C%0A)%3A%0A%20%20%20%20forecaster%20%3D%20ClassProbaReductionForecaster(%0A%20%20%20%20%20%20%20%20estimator%3DDecisionTreeClassifier(random_state%3D42)%2C%0A%20%20%20%20%20%20%20%20feature_transformer%3DLagTransformer(lag%3D%5B1%2C%202%2C%203%2C%206%2C%2012%2C%2024%5D)%2C%0A%20%20%20%20)%0A%20%20%20%20forecaster.fit(y_train%2C%20X_actual_train%2C%20forecasting_horizon%3Dforecasting_horizon)%0A%0A%20%20%20%20print(f%22Discovered%20classes%3A%20%7Bforecaster.classes_%7D%22)%0A%20%20%20%20return%20(forecaster%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.%20Probability%20Predictions%0A%0A%20%20%20%20%60predict_class_proba()%60%20returns%20one%20column%20per%20class%2C%20with%20probabilities%0A%20%20%20%20summing%20to%201%20at%20each%20time%20step.%20%60predict()%60%20returns%20the%20most%20likely%20class.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(forecaster%2C%20forecasting_horizon)%3A%0A%20%20%20%20y_proba%20%3D%20forecaster.predict_class_proba(%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dforecasting_horizon%2C%0A%20%20%20%20)%0A%20%20%20%20print(%22Probability%20predictions%20(first%2012%20steps)%3A%22)%0A%20%20%20%20y_proba%0A%20%20%20%20return%20(y_proba%2C)%0A%0A%0A%40app.cell%0Adef%20_(forecaster%2C%20forecasting_horizon)%3A%0A%20%20%20%20y_pred%20%3D%20forecaster.predict(%0A%20%20%20%20%20%20%20%20forecasting_horizon%3Dforecasting_horizon%2C%0A%20%20%20%20)%0A%20%20%20%20print(%22Class%20label%20predictions%3A%22)%0A%20%20%20%20y_pred%0A%20%20%20%20return%20(y_pred%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%205.%20Visualize%20Forecasts%0A%0A%20%20%20%20%5B%60plot_forecast%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.forecasting.plot_forecast%2F)%0A%20%20%20%20auto-detects%20class-probability%20and%20categorical%20prediction%20columns.%0A%0A%20%20%20%20-%20**Probability%20predictions**%20are%20rendered%20as%20stacked%20area%20charts%20showing%0A%20%20%20%20%20%20how%20the%20probability%20mass%20shifts%20across%20classes%20over%20the%20forecast%20horizon.%0A%20%20%20%20%20%20Diamond%20markers%20highlight%20the%20true%20class%20from%20%60y_test%60.%0A%20%20%20%20-%20**Categorical%20predictions**%20(from%20%60predict()%60)%20are%20rendered%20as%20step%0A%20%20%20%20%20%20charts%20comparing%20predicted%20vs%20actual%20class%20labels.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_forecast%2C%20y_proba%2C%20y_test)%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_proba%2C%0A%20%20%20%20%20%20%20%20title%3D%22Probability%20Forecast%20(Stacked%20Area)%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_forecast%2C%20y_pred%2C%20y_test)%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%2C%0A%20%20%20%20%20%20%20%20title%3D%22Categorical%20Forecast%20(Step%20Chart)%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.%20Evaluate%20with%20Metrics%0A%0A%20%20%20%20Yohou%20provides%20three%20class-probability%20metrics%3A%0A%0A%20%20%20%20-%20%5B%60LogLoss%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.metrics.class_proba.LogLoss%2F)%3A%20Measures%20how%20well%20predicted%20probabilities%20match%20the%20true%20distribution%20(lower%20is%20better)%0A%20%20%20%20-%20%5B%60BrierScore%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.metrics.class_proba.BrierScore%2F)%3A%20Mean%20squared%20error%20between%20predicted%20probabilities%20and%20one-hot%20truth%20(lower%20is%20better)%0A%20%20%20%20-%20%5B%60Accuracy%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.metrics.class_proba.Accuracy%2F)%3A%20Fraction%20of%20correct%20argmax%20predictions%20(higher%20is%20better)%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Accuracy%2C%20BrierScore%2C%20LogLoss%2C%20y_proba%2C%20y_test)%3A%0A%20%20%20%20y_truth_slice%20%3D%20y_test.head(len(y_proba))%0A%0A%20%20%20%20log_loss%20%3D%20LogLoss().fit(y_truth_slice)%0A%20%20%20%20brier%20%3D%20BrierScore().fit(y_truth_slice)%0A%20%20%20%20accuracy%20%3D%20Accuracy().fit(y_truth_slice)%0A%0A%20%20%20%20print(f%22Log%20Loss%3A%20%20%20%20%7Blog_loss.score(y_truth_slice%2C%20y_proba)%3A.4f%7D%22)%0A%20%20%20%20print(f%22Brier%20Score%3A%20%7Bbrier.score(y_truth_slice%2C%20y_proba)%3A.4f%7D%22)%0A%20%20%20%20print(f%22Accuracy%3A%20%20%20%20%7Baccuracy.score(y_truth_slice%2C%20y_proba)%3A.4f%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%207.%20Rolling%20Observe-Predict%0A%0A%20%20%20%20The%20%60observe_predict_class_proba()%60%20method%20performs%20rolling%20evaluation%3A%0A%20%20%20%20observe%20new%20data%2C%20then%20predict%20the%20next%20horizon.%20This%20simulates%20real-world%0A%20%20%20%20deployment%20where%20predictions%20are%20updated%20as%20new%20observations%20arrive.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(X_actual_test%2C%20forecaster%2C%20y_test)%3A%0A%20%20%20%20y_rolling_proba%20%3D%20forecaster.observe_predict_class_proba(%0A%20%20%20%20%20%20%20%20y%3Dy_test%2C%0A%20%20%20%20%20%20%20%20X_actual%3DX_actual_test%2C%0A%20%20%20%20).sort(%22time%22)%0A%20%20%20%20print(f%22Rolling%20predictions%3A%20%7Blen(y_rolling_proba)%7D%20rows%22)%0A%20%20%20%20return%20(y_rolling_proba%2C)%0A%0A%0A%40app.cell%0Adef%20_(y_rolling_proba)%3A%0A%20%20%20%20y_rolling_proba%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_forecast%2C%20y_rolling_proba%2C%20y_test)%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_rolling_proba%2C%0A%20%20%20%20%20%20%20%20title%3D%22Rolling%20Probability%20Forecast%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%23%20Score%20Evolution%20Over%20Time%0A%0A%20%20%20%20Per-timestep%20LogLoss%20and%20BrierScore%20reveal%20when%20the%20model%20is%20most%0A%20%20%20%20uncertain.%20Spikes%20indicate%20time%20steps%20where%20predictions%20deviated%0A%20%20%20%20most%20from%20reality.%0A%0A%20%20%20%20%5B%60plot_score_time_series%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.evaluation.plot_score_time_series%2F)%0A%20%20%20%20shows%20how%20forecast%20quality%20varies%20across%20time%20steps.%20Spikes%20reveal%20periods%0A%20%20%20%20where%20the%20model%20struggles%2C%20helping%20diagnose%20whether%20errors%20are%20random%20or%0A%20%20%20%20systematic.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(LogLoss%2C%20plot_score_time_series%2C%20y_rolling_proba%2C%20y_test)%3A%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20LogLoss()%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20y_rolling_proba%2C%0A%20%20%20%20%20%20%20%20title%3D%22Log%20Loss%20Over%20Time%20(Rolling%20Predictions)%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(BrierScore%2C%20plot_score_time_series%2C%20y_rolling_proba%2C%20y_test)%3A%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20BrierScore()%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20y_rolling_proba%2C%0A%20%20%20%20%20%20%20%20title%3D%22Brier%20Score%20Over%20Time%20(Rolling%20Predictions)%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(Accuracy%2C%20plot_score_time_series%2C%20y_rolling_proba%2C%20y_test)%3A%0A%20%20%20%20plot_score_time_series(%0A%20%20%20%20%20%20%20%20Accuracy()%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20y_rolling_proba%2C%0A%20%20%20%20%20%20%20%20title%3D%22Accuracy%20Over%20Time%20(Rolling%20Predictions)%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%208.%20Calibration%20Plot%0A%0A%20%20%20%20%5B%60plot_calibration%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.plotting.evaluation.plot_calibration%2F)%0A%20%20%20%20automatically%20detects%20class-probability%20columns%20and%20renders%20a%20calibration%0A%20%20%20%20plot.%20Points%20near%20the%20diagonal%20indicate%20good%20calibration%3B%20points%20below%0A%20%20%20%20mean%20the%20model%20is%20overconfident%20for%20that%20class.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(plot_calibration%2C%20y_rolling_proba%2C%20y_test)%3A%0A%20%20%20%20plot_calibration(%0A%20%20%20%20%20%20%20%20y_rolling_proba%2C%0A%20%20%20%20%20%20%20%20y_test%2C%0A%20%20%20%20%20%20%20%20n_bins%3D8%2C%0A%20%20%20%20%20%20%20%20title%3D%22Calibration%20Plot%20(Rolling%20Predictions)%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.%20Alternative%20Dataset%3A%20Demand%20Classification%0A%0A%20%20%20%20%5B%60fetch_demand_classification%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.datasets._fetchers.fetch_demand_classification%2F)%0A%20%20%20%20provides%20a%20binary%20electricity%20demand%20classification%20target%20derived%20from%0A%20%20%20%20smart%20meter%20readings.%20It%20follows%20the%20same%20API%20as%20%5B%60fetch_air_quality_classification%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.datasets._fetchers.fetch_air_quality_classification%2F)%0A%20%20%20%20and%20works%20with%20%5B%60ClassProbaReductionForecaster%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.class_proba.reduction.ClassProbaReductionForecaster%2F)%20without%20any%20code%20changes.%0A%20%20%20%20%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(fetch_demand_classification)%3A%0A%20%20%20%20demand_data%20%3D%20fetch_demand_classification()%0A%20%20%20%20print(f%22Classes%3A%20%7Bdemand_data.classes%7D%22)%0A%20%20%20%20print(f%22Dataset%3A%20%7Blen(demand_data.y)%7D%20observations%20from%20%7Bdemand_data.y%5B'time'%5D.min()%7D%20to%20%7Bdemand_data.y%5B'time'%5D.max()%7D%22)%0A%20%20%20%20demand_data.y.head(5)%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-%20Try%20different%20classifiers%3A%20%5B%60LogisticRegression%60%5D(https%3A%2F%2Fscikit-learn.org%2Fstable%2Fmodules%2Fgenerated%2Fsklearn.linear_model.LogisticRegression.html)%2C%20%5B%60RandomForestClassifier%60%5D(https%3A%2F%2Fscikit-learn.org%2Fstable%2Fmodules%2Fgenerated%2Fsklearn.ensemble.RandomForestClassifier.html)%2C%20%5B%60GradientBoostingClassifier%60%5D(https%3A%2F%2Fscikit-learn.org%2Fstable%2Fmodules%2Fgenerated%2Fsklearn.ensemble.GradientBoostingClassifier.html)%0A%20%20%20%20-%20Experiment%20with%20%60reduction_strategy%3D%22direct%22%60%20for%20independent%20step%20classifiers%0A%20%20%20%20-%20Add%20more%20lag%20features%20with%20%5B%60LagTransformer%60%5D(%2Fpages%2Fapi%2Fgenerated%2Fyohou.preprocessing.window.LagTransformer%2F)%0A%20%20%20%20-%20Explore%20%5BMetrics%5D(%2Fexamples%2F%23metrics)%20for%20more%20evaluation%20options%0A%20%20%20%20-%20See%20%5B%60reduction_forecaster.py%60%5D(%2Fexamples%2Fgetting-started%2Freduction_forecaster%2F)%20for%20the%20regression%20equivalent%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
643ad630d1c153585bfb9c2c925cafa3