import%20marimo%0A%0A__generated_with%20%3D%20%220.13.6%22%0Aapp%20%3D%20marimo.App(app_title%3D%22Intermittent%20Forecasting%22)%0A%0A%0A%40app.cell%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%22Import%20required%20libraries%20for%20data%20analysis%2C%20forecasting%2C%20and%20evaluation%20metrics.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%0A%20%20%20%20import%20numpy%20as%20np%0A%20%20%20%20import%20pandas%20as%20pd%0A%20%20%20%20from%20nixtla%20import%20NixtlaClient%0A%20%20%20%20from%20utilsforecast.evaluation%20import%20evaluate%0A%20%20%20%20from%20utilsforecast.losses%20import%20mae%0A%20%20%20%20return%20NixtlaClient%2C%20evaluate%2C%20mae%2C%20np%2C%20pd%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Prerequisites%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%22Initialize%20Nixtla%20client%20with%20API%20key%20from%20environment%20variables.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(NixtlaClient)%3A%0A%20%20%20%20import%20os%0A%0A%20%20%20%20NIXTLA_API_KEY%20%3D%20os.environ%5B%22NIXTLA_API_KEY%22%5D%0A%20%20%20%20client%20%3D%20NixtlaClient(api_key%3DNIXTLA_API_KEY)%0A%20%20%20%20return%20(client%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Data%20Preparation%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%22Load%20and%20preprocess%20the%20M5%20sales%20dataset%20with%20exogenous%20variables.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(pd)%3A%0A%20%20%20%20sales_data%20%3D%20pd.read_csv(%0A%20%20%20%20%20%20%20%20%22https%3A%2F%2Fraw.githubusercontent.com%2FNixtla%2Ftransfer-learning-time-series%2Fmain%2Fdatasets%2Fm5_sales_exog_small.csv%22%0A%20%20%20%20)%0A%20%20%20%20sales_data%5B%22ds%22%5D%20%3D%20pd.to_datetime(sales_data%5B%22ds%22%5D)%0A%20%20%20%20sales_data.head()%0A%20%20%20%20return%20(sales_data%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22Visualize%20the%20sales%20data%20for%20the%20first%20365%20days.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(client%2C%20sales_data)%3A%0A%20%20%20%20sales_plot%20%3D%20client.plot(%0A%20%20%20%20%20%20%20%20sales_data%2C%0A%20%20%20%20%20%20%20%20max_insample_length%3D365%2C%0A%20%20%20%20)%0A%0A%20%20%20%20sales_plot%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%23%23%20Bounded%20Forecasts%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%22Apply%20log%20transformation%20to%20handle%20the%20intermittent%20nature%20of%20the%20data.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(np%2C%20sales_data)%3A%0A%20%20%20%20log_transformed_data%20%3D%20sales_data.copy()%0A%20%20%20%20log_transformed_data%5B%22y%22%5D%20%3D%20np.log(log_transformed_data%5B%22y%22%5D%20%2B%201)%0A%20%20%20%20log_transformed_data.head()%0A%20%20%20%20return%20(log_transformed_data%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22Compare%20original%20and%20log-transformed%20data%20for%20a%20specific%20product.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(client%2C%20log_transformed_data%2C%20sales_data)%3A%0A%20%20%20%20import%20matplotlib.pyplot%20as%20plt%0A%0A%20%20%20%20%23%20Create%20a%20figure%20and%20axis%20for%20Matplotlib%0A%20%20%20%20_%2C%20ax%20%3D%20plt.subplots(figsize%3D(10%2C%205))%0A%0A%20%20%20%20%23%20Plot%20the%20original%20data%0A%20%20%20%20client.plot(%0A%20%20%20%20%20%20%20%20sales_data%2C%0A%20%20%20%20%20%20%20%20max_insample_length%3D30%2C%0A%20%20%20%20%20%20%20%20unique_ids%3D%5B%22FOODS_1_001%22%5D%2C%0A%20%20%20%20%20%20%20%20engine%3D%22matplotlib%22%2C%0A%20%20%20%20%20%20%20%20ax%3Dax%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Plot%20the%20transformed%20data%20on%20the%20same%20axes%0A%20%20%20%20client.plot(%0A%20%20%20%20%20%20%20%20log_transformed_data%2C%0A%20%20%20%20%20%20%20%20max_insample_length%3D30%2C%0A%20%20%20%20%20%20%20%20unique_ids%3D%5B%22FOODS_1_001%22%5D%2C%0A%20%20%20%20%20%20%20%20engine%3D%22matplotlib%22%2C%0A%20%20%20%20%20%20%20%20ax%3Dax%2C%0A%20%20%20%20)%0A%0A%20%20%20%20%23%20Manually%20change%20the%20color%20of%20the%20second%20line%20plot%0A%20%20%20%20lines%20%3D%20ax.get_lines()%0A%20%20%20%20if%20len(lines)%20%3E%201%3A%0A%20%20%20%20%20%20%20%20lines%5B1%5D.set_color(%22%23006400%22)%20%20%23%20New%20color%20for%20transformed%20data%0A%20%20%20%20%20%20%20%20lines%5B1%5D.set_linestyle(%22--%22)%0A%0A%20%20%20%20%23%20Add%20legend%20with%20custom%20labels%0A%20%20%20%20handles%2C%20labels%20%3D%20ax.get_legend_handles_labels()%0A%20%20%20%20labels%20%3D%20%5B%22Original%20Sales%22%2C%20%22Transformed%20Sales%22%5D%0A%20%20%20%20ax.legend(handles%2C%20labels)%0A%0A%20%20%20%20ax%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%22Split%20data%20into%20training%20and%20test%20sets%20(last%2028%20days%20for%20testing).%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(log_transformed_data)%3A%0A%20%20%20%20%23%20Select%20the%20last%2028%20observations%20for%20each%20unique_id%20%E2%80%94%20used%20as%20test%20data%0A%20%20%20%20test_data%20%3D%20log_transformed_data.groupby(%22unique_id%22).tail(28)%0A%0A%20%20%20%20%23%20Drop%20the%20test%20set%20indices%20from%20the%20original%20dataset%20to%20form%20the%20training%20set%0A%20%20%20%20train_data%20%3D%20log_transformed_data.drop(test_data.index).reset_index(drop%3DTrue)%0A%20%20%20%20return%20test_data%2C%20train_data%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Generating%20Forecasts%20with%20TimeGPT%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%22Generate%20forecasts%20using%20the%20base%20TimeGPT%20model%20with%2080%25%20confidence%20interval.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(client%2C%20train_data)%3A%0A%20%20%20%20log_forecast%20%3D%20client.forecast(%0A%20%20%20%20%20%20%20%20df%3Dtrain_data%2C%0A%20%20%20%20%20%20%20%20h%3D28%2C%0A%20%20%20%20%20%20%20%20level%3D%5B80%5D%2C%0A%20%20%20%20%20%20%20%20model%3D%22timegpt-1-long-horizon%22%2C%0A%20%20%20%20%20%20%20%20time_col%3D%22ds%22%2C%0A%20%20%20%20%20%20%20%20target_col%3D%22y%22%2C%0A%20%20%20%20%20%20%20%20id_col%3D%22unique_id%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(log_forecast%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(%0A%20%20%20%20%20%20%20%20r%22%22%22%0A%20%20%20%20%23%23%20Reverse%20Transformation%0A%0A%20%20%20%20After%20obtaining%20predictions%2C%20we%20reverse%20the%20log%20transformation%20to%20return%20to%20the%20original%20scale.%0A%20%20%20%20%22%22%22%0A%20%20%20%20)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(log_forecast%2C%20np)%3A%0A%20%20%20%20def%20reverse_log_transform(df)%3A%0A%20%20%20%20%20%20%20%20df%20%3D%20df.copy()%0A%20%20%20%20%20%20%20%20value_cols%20%3D%20%5Bcol%20for%20col%20in%20df%20if%20col%20not%20in%20%5B%22ds%22%2C%20%22unique_id%22%5D%5D%0A%20%20%20%20%20%20%20%20df%5Bvalue_cols%5D%20%3D%20np.exp(df%5Bvalue_cols%5D)%20-%201%0A%20%20%20%20%20%20%20%20return%20df%0A%0A%20%20%20%20base_forecast%20%3D%20reverse_log_transform(log_forecast)%0A%20%20%20%20base_forecast.head()%0A%20%20%20%20return%20base_forecast%2C%20reverse_log_transform%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Evaluation%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%22Define%20functions%20to%20merge%20forecasts%20with%20real%20data%20and%20calculate%20MAE.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(evaluate%2C%20mae%2C%20pd)%3A%0A%20%20%20%20def%20merge_forecast(real_data%2C%20forecast)%3A%0A%20%20%20%20%20%20%20%20merged_results%20%3D%20pd.merge(%0A%20%20%20%20%20%20%20%20%20%20%20%20real_data%2C%20forecast%2C%20%22left%22%2C%20%5B%22unique_id%22%2C%20%22ds%22%5D%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20return%20merged_results%0A%0A%20%20%20%20def%20get_mean_mae(real_data%2C%20forecast)%3A%0A%20%20%20%20%20%20%20%20merged_results%20%3D%20merge_forecast(real_data%2C%20forecast)%0A%20%20%20%20%20%20%20%20model_evaluation%20%3D%20evaluate(%0A%20%20%20%20%20%20%20%20%20%20%20%20merged_results%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20metrics%3D%5Bmae%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20models%3D%5B%22TimeGPT%22%5D%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20target_col%3D%22y%22%2C%0A%20%20%20%20%20%20%20%20%20%20%20%20id_col%3D%22unique_id%22%2C%0A%20%20%20%20%20%20%20%20)%0A%20%20%20%20%20%20%20%20return%20model_evaluation.groupby(%22metric%22)%5B%22TimeGPT%22%5D.mean()%5B%22mae%22%5D%0A%20%20%20%20return%20(get_mean_mae%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22Calculate%20MAE%20for%20the%20base%20model%20forecasts.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(base_forecast%2C%20get_mean_mae%2C%20test_data)%3A%0A%20%20%20%20base_mae%20%3D%20get_mean_mae(test_data%2C%20base_forecast)%0A%20%20%20%20print(base_mae)%0A%20%20%20%20return%20(base_mae%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Finetuning%20the%20Model%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%22Generate%20forecasts%20using%20a%20fine-tuned%20TimeGPT%20model%20with%2010%20finetuning%20steps.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(client%2C%20train_data)%3A%0A%20%20%20%20log_finetuned_forecast%20%3D%20client.forecast(%0A%20%20%20%20%20%20%20%20df%3Dtrain_data%2C%0A%20%20%20%20%20%20%20%20h%3D28%2C%0A%20%20%20%20%20%20%20%20level%3D%5B80%5D%2C%0A%20%20%20%20%20%20%20%20finetune_steps%3D10%2C%0A%20%20%20%20%20%20%20%20finetune_loss%3D%22mae%22%2C%0A%20%20%20%20%20%20%20%20model%3D%22timegpt-1-long-horizon%22%2C%0A%20%20%20%20%20%20%20%20time_col%3D%22ds%22%2C%0A%20%20%20%20%20%20%20%20target_col%3D%22y%22%2C%0A%20%20%20%20%20%20%20%20id_col%3D%22unique_id%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(log_finetuned_forecast%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22Calculate%20MAE%20for%20the%20fine-tuned%20model%20forecasts.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(get_mean_mae%2C%20log_finetuned_forecast%2C%20reverse_log_transform%2C%20test_data)%3A%0A%20%20%20%20finetuned_forecast%20%3D%20reverse_log_transform(log_finetuned_forecast)%0A%20%20%20%20finedtune_mae%20%3D%20get_mean_mae(test_data%2C%20finetuned_forecast)%0A%20%20%20%20print(finedtune_mae)%0A%20%20%20%20return%20(finedtune_mae%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Incorporating%20Exogenous%20Variables%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%22Prepare%20exogenous%20variables%20for%20forecasting%20by%20removing%20target%20and%20price%20columns.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(test_data)%3A%0A%20%20%20%20non_exogenous_variables%20%3D%20%5B%22y%22%2C%20%22sell_price%22%5D%0A%20%20%20%20futr_exog_data%20%3D%20test_data.drop(non_exogenous_variables%2C%20axis%3D1)%0A%20%20%20%20futr_exog_data.head()%0A%20%20%20%20return%20(futr_exog_data%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22Generate%20forecasts%20using%20TimeGPT%20with%20exogenous%20variables%20and%20fine-tuning.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(client%2C%20futr_exog_data%2C%20train_data)%3A%0A%20%20%20%20log_exogenous_forecast%20%3D%20client.forecast(%0A%20%20%20%20%20%20%20%20df%3Dtrain_data%2C%0A%20%20%20%20%20%20%20%20X_df%3Dfutr_exog_data%2C%0A%20%20%20%20%20%20%20%20h%3D28%2C%0A%20%20%20%20%20%20%20%20level%3D%5B80%5D%2C%0A%20%20%20%20%20%20%20%20finetune_steps%3D10%2C%0A%20%20%20%20%20%20%20%20finetune_loss%3D%22mae%22%2C%0A%20%20%20%20%20%20%20%20model%3D%22timegpt-1-long-horizon%22%2C%0A%20%20%20%20%20%20%20%20time_col%3D%22ds%22%2C%0A%20%20%20%20%20%20%20%20target_col%3D%22y%22%2C%0A%20%20%20%20%20%20%20%20id_col%3D%22unique_id%22%2C%0A%20%20%20%20)%0A%20%20%20%20return%20(log_exogenous_forecast%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22Calculate%20MAE%20for%20the%20model%20with%20exogenous%20variables.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(get_mean_mae%2C%20log_exogenous_forecast%2C%20reverse_log_transform%2C%20test_data)%3A%0A%20%20%20%20exogenous_forecast%20%3D%20reverse_log_transform(log_exogenous_forecast)%0A%20%20%20%20exogenous_mae%20%3D%20get_mean_mae(test_data%2C%20exogenous_forecast)%0A%20%20%20%20print(exogenous_mae)%0A%20%20%20%20return%20(exogenous_mae%2C)%0A%0A%0A%40app.cell(hide_code%3DTrue)%0Adef%20_(mo)%3A%0A%20%20%20%20mo.md(r%22%22%22%23%23%20Comparing%20MAE%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%22Create%20a%20comparison%20table%20of%20MAE%20values%20for%20all%20three%20model%20variants.%22%22%22)%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_(base_mae%2C%20exogenous_mae%2C%20finedtune_mae%2C%20pd)%3A%0A%20%20%20%20%23%20Define%20the%20mean%20absolute%20error%20(MAE)%20values%20for%20different%20TimeGPT%20variants%0A%20%20%20%20mae_values%20%3D%20%7B%0A%20%20%20%20%20%20%20%20%22Model%20Variant%22%3A%20%5B%22Base%20TimeGPT%22%2C%20%22Fine-Tuned%20TimeGPT%22%2C%20%22TimeGPT%20with%20Exogenous%22%5D%2C%0A%20%20%20%20%20%20%20%20%22MAE%22%3A%20%5Bbase_mae%2C%20finedtune_mae%2C%20exogenous_mae%5D%0A%20%20%20%20%7D%0A%0A%20%20%20%20mae_table%20%3D%20pd.DataFrame(mae_values)%0A%20%20%20%20mae_table%0A%0A%20%20%20%20return%0A%0A%0A%40app.cell%0Adef%20_()%3A%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
c0e0109a491c1124d79a0a5f57cb450696e65f50f5fa82f5de191d332ce13d81