{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Tutorial - Time series forecasting\n", "\n", "## Introduction\n", "\n", "Time series are an ubiquitous type of data in all types of processes. Producing forecasts for them can be highly valuable in domains like retail or industrial manufacture, among many others.\n", "\n", "Lightwood supports time series forecasting (both univariate and multivariate inputs), handling many of the pain points commonly associated with setting up a manual time series predictive pipeline. \n", "\n", "In this tutorial, we will train a lightwood predictor and analyze its forecasts for the task of counting sunspots in monthly intervals.\n", "\n", "## Load data\n", "\n", "Let's begin by loading the dataset and looking at it:" ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:14.342783Z", "iopub.status.busy": "2024-05-07T17:15:14.342325Z", "iopub.status.idle": "2024-05-07T17:15:14.884075Z", "shell.execute_reply": "2024-05-07T17:15:14.883399Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
MonthSunspots
01749-0158.0
11749-0262.6
21749-0370.0
31749-0455.7
41749-0585.0
.........
28151983-0871.8
28161983-0950.3
28171983-1055.8
28181983-1133.3
28191983-1233.4
\n", "

2820 rows × 2 columns

\n", "
" ], "text/plain": [ " Month Sunspots\n", "0 1749-01 58.0\n", "1 1749-02 62.6\n", "2 1749-03 70.0\n", "3 1749-04 55.7\n", "4 1749-05 85.0\n", "... ... ...\n", "2815 1983-08 71.8\n", "2816 1983-09 50.3\n", "2817 1983-10 55.8\n", "2818 1983-11 33.3\n", "2819 1983-12 33.4\n", "\n", "[2820 rows x 2 columns]" ] }, "execution_count": 1, "metadata": {}, "output_type": "execute_result" } ], "source": [ "import pandas as pd\n", "\n", "df = pd.read_csv(\"https://raw.githubusercontent.com/mindsdb/benchmarks/main/benchmarks/datasets/monthly_sunspots/data.csv\")\n", "df" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "This is a very simple dataset. It's got a single column that specifies the month in which the measurement was done, and then in the 'Sunspots' column we have the actual quantity we are interested in forecasting. As such, we can characterize this as a univariate time series problem.\n", "\n", "## Define the predictive task\n", "\n", "We will use Lightwood high level methods to state what we want to predict. As this is a time series task (because we want to leverage the notion of time to predict), we need to specify a set of arguments that will activate Lightwood's time series pipeline:" ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:14.919664Z", "iopub.status.busy": "2024-05-07T17:15:14.919201Z", "iopub.status.idle": "2024-05-07T17:15:17.382878Z", "shell.execute_reply": "2024-05-07T17:15:17.382217Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:No torchvision detected, image helpers not supported.\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:No torchvision/pillow detected, image encoder not supported\u001b[0m\n" ] } ], "source": [ "from lightwood.api.high_level import ProblemDefinition" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:17.385947Z", "iopub.status.busy": "2024-05-07T17:15:17.385553Z", "iopub.status.idle": "2024-05-07T17:15:17.389110Z", "shell.execute_reply": "2024-05-07T17:15:17.388504Z" } }, "outputs": [], "source": [ "tss = {'horizon': 6, # the predictor will learn to forecast what the next semester counts will look like (6 data points at monthly intervals -> 6 months)\n", " 'order_by': 'Month', # what column is used to order the entire datset\n", " 'window': 12 # how many past values to consider for emitting predictions\n", " }\n", "\n", "pdef = ProblemDefinition.from_dict({'target': 'Sunspots', # specify the column to forecast\n", " 'timeseries_settings': tss # pass along all time series specific parameters\n", " })" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Now, let's do a very simple train-test split, leaving 10% of the data to check the forecasts that our predictor will produce:" ] }, { "cell_type": "code", "execution_count": 4, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:17.391428Z", "iopub.status.busy": "2024-05-07T17:15:17.391229Z", "iopub.status.idle": "2024-05-07T17:15:17.395522Z", "shell.execute_reply": "2024-05-07T17:15:17.394859Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "(2538, 2) (282, 2)\n" ] } ], "source": [ "cutoff = int(len(df)*0.9)\n", "\n", "train = df[:cutoff]\n", "test = df[cutoff:]\n", "\n", "print(train.shape, test.shape)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Generate the predictor object\n", "\n", "Now, we can generate code for a machine learning model by using our problem definition and the data:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:17.397741Z", "iopub.status.busy": "2024-05-07T17:15:17.397547Z", "iopub.status.idle": "2024-05-07T17:15:21.486719Z", "shell.execute_reply": "2024-05-07T17:15:21.486032Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:type_infer-2879:Analyzing a sample of 2467\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:type_infer-2879:from a total population of 2820, this is equivalent to 87.5% of your data.\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:type_infer-2879:Infering type for: Month\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:type_infer-2879:Column Month has data type date\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:type_infer-2879:Infering type for: Sunspots\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:type_infer-2879:Column Sunspots has data type float\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Starting statistical analysis\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/dataprep_ml/cleaners.py:163: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.\n", " result = pd.to_datetime(element,\n", "\u001b[32mINFO:dataprep_ml-2879:Finished statistical analysis\u001b[0m\n" ] } ], "source": [ "from lightwood.api.high_level import (\n", " json_ai_from_problem,\n", " code_from_json_ai,\n", " predictor_from_code\n", ")\n", "\n", "json_ai = json_ai_from_problem(df, problem_definition=pdef)\n", "code = code_from_json_ai(json_ai)\n", "predictor = predictor_from_code(code)\n", "\n", "# uncomment this to see the generated code:\n", "# print(code)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Train\n", "\n", "Okay, everything is ready now for our predictor to learn based on the training data we will provide.\n", "\n", "Internally, lightwood cleans and reshapes the data, featurizes measurements and timestamps, and comes up with a handful of different models that will be evaluated to keep the one that produces the best forecasts.\n", "\n", "Let's train the predictor. This should take a couple of minutes, at most:" ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:21.490176Z", "iopub.status.busy": "2024-05-07T17:15:21.489500Z", "iopub.status.idle": "2024-05-07T17:15:23.396695Z", "shell.execute_reply": "2024-05-07T17:15:23.396028Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Learn phase 1/8] - Statistical analysis\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Starting statistical analysis\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/dataprep_ml/cleaners.py:163: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.\n", " result = pd.to_datetime(element,\n", "\u001b[32mINFO:dataprep_ml-2879:Finished statistical analysis\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `analyze_data` runtime: 0.05 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Learn phase 2/8] - Data preprocessing\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Cleaning the data\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/dataprep_ml/cleaners.py:163: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.\n", " result = pd.to_datetime(element,\n", "\u001b[32mINFO:dataprep_ml-2879:Transforming timeseries data\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `preprocess` runtime: 0.09 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Learn phase 3/8] - Data splitting\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Splitting the data into train/test\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `split` runtime: 0.0 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Learn phase 4/8] - Preparing encoders\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:dataprep_ml-2879:Preparing sequentially...\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `prepare` runtime: 0.05 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Learn phase 5/8] - Feature generation\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Featurizing the data\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `featurize` runtime: 0.05 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Learn phase 6/8] - Mixer training\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Training the mixers\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[33mWARNING:lightwood-2879:XGBoost running on CPU\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[33mWARNING:lightwood-2879:XGBoost running on CPU\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[33mWARNING:lightwood-2879:XGBoost running on CPU\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[33mWARNING:lightwood-2879:XGBoost running on CPU\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[33mWARNING:lightwood-2879:XGBoost running on CPU\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[33mWARNING:lightwood-2879:XGBoost running on CPU\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/torch/amp/grad_scaler.py:131: UserWarning: torch.cuda.amp.GradScaler is enabled, but CUDA is not available. Disabling.\n", " warnings.warn(\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[17:15:21] WARNING: ../src/learner.cc:339: No visible GPU is found, setting `gpu_id` to -1\n", "[17:15:21] WARNING: ../src/learner.cc:339: No visible GPU is found, setting `gpu_id` to -1\n", "[17:15:21] WARNING: ../src/learner.cc:339: No visible GPU is found, setting `gpu_id` to -1\n", "[17:15:21] WARNING: ../src/learner.cc:339: No visible GPU is found, setting `gpu_id` to -1\n", "[17:15:21] WARNING: ../src/learner.cc:339: No visible GPU is found, setting `gpu_id` to -1\n", "[17:15:21] WARNING: ../src/learner.cc:339: No visible GPU is found, setting `gpu_id` to -1\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/pytorch_ranger/ranger.py:172: UserWarning: This overload of addcmul_ is deprecated:\n", "\taddcmul_(Number value, Tensor tensor1, Tensor tensor2)\n", "Consider using one of the following signatures instead:\n", "\taddcmul_(Tensor tensor1, Tensor tensor2, *, Number value) (Triggered internally at ../torch/csrc/utils/python_arg_parser.cpp:1578.)\n", " exp_avg_sq.mul_(beta2).addcmul_(1 - beta2, grad, grad)\n", "\u001b[32mINFO:lightwood-2879:Loss of 9.051180630922318 with learning rate 0.0001\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss of 9.014871209859848 with learning rate 0.0005\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss of 8.969509482383728 with learning rate 0.001\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss of 8.879052013158798 with learning rate 0.002\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss of 8.788950502872467 with learning rate 0.003\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss of 8.611965209245682 with learning rate 0.005\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss of 8.195775926113129 with learning rate 0.01\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss of 6.255893141031265 with learning rate 0.05\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Found learning rate of: 0.05\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 1: 0.5818348675966263\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 2: 0.4797109067440033\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 3: 0.48386093974113464\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 4: 0.49511992931365967\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 5: 0.39475560188293457\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 6: 0.39592696726322174\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 7: 0.3622782379388809\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 8: 0.38170479238033295\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 9: 0.5138543993234634\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 10: 0.6360723078250885\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 1: 0.29868809472430835\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 2: 0.30318967591632495\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `fit_mixer` runtime: 0.86 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Started fitting LGBM models for array prediction\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Started fitting XGBoost model\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:42.76798\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:A single GBM iteration takes 0.1 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Training XGBoost with 57023 iterations given 7127.987008333206 seconds constraint\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:42.76798\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[1]\tvalidation_0-rmse:31.72661\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[2]\tvalidation_0-rmse:24.49596\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[3]\tvalidation_0-rmse:20.38592\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[4]\tvalidation_0-rmse:18.09356\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[5]\tvalidation_0-rmse:16.88080\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[6]\tvalidation_0-rmse:16.21734\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[7]\tvalidation_0-rmse:15.95640\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[8]\tvalidation_0-rmse:15.80745\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[9]\tvalidation_0-rmse:15.76428\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[10]\tvalidation_0-rmse:15.89176\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[11]\tvalidation_0-rmse:15.89176\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[12]\tvalidation_0-rmse:15.87901\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[13]\tvalidation_0-rmse:15.87505\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[14]\tvalidation_0-rmse:16.06330\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Started fitting XGBoost model\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:42.95930\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:A single GBM iteration takes 0.1 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Training XGBoost with 57023 iterations given 7127.988311052322 seconds constraint\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:42.95930\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[1]\tvalidation_0-rmse:32.27936\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[2]\tvalidation_0-rmse:25.47815\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[3]\tvalidation_0-rmse:21.37610\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[4]\tvalidation_0-rmse:19.25243\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[5]\tvalidation_0-rmse:18.03199\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[6]\tvalidation_0-rmse:17.67706\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[7]\tvalidation_0-rmse:17.57516\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[8]\tvalidation_0-rmse:17.51227\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[9]\tvalidation_0-rmse:17.51216\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[10]\tvalidation_0-rmse:17.55192\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[11]\tvalidation_0-rmse:17.56609\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[12]\tvalidation_0-rmse:17.71702\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[13]\tvalidation_0-rmse:17.75939\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[14]\tvalidation_0-rmse:17.84796\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Started fitting XGBoost model\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:43.14000\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:A single GBM iteration takes 0.1 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Training XGBoost with 57023 iterations given 7127.988361358643 seconds constraint\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:43.14000\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[1]\tvalidation_0-rmse:32.50446\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[2]\tvalidation_0-rmse:25.73040\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[3]\tvalidation_0-rmse:22.16599\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[4]\tvalidation_0-rmse:20.28726\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[5]\tvalidation_0-rmse:19.46406\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[6]\tvalidation_0-rmse:19.07306\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[7]\tvalidation_0-rmse:19.00714\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[8]\tvalidation_0-rmse:19.13990\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[9]\tvalidation_0-rmse:19.12589\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[10]\tvalidation_0-rmse:19.34977\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[11]\tvalidation_0-rmse:19.43217\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Started fitting XGBoost model\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:44.19079\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:A single GBM iteration takes 0.1 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Training XGBoost with 57023 iterations given 7127.988099575043 seconds constraint\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:44.19079\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[1]\tvalidation_0-rmse:34.13289\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[2]\tvalidation_0-rmse:27.40621\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[3]\tvalidation_0-rmse:23.82532\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[4]\tvalidation_0-rmse:22.03399\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[5]\tvalidation_0-rmse:21.07010\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[6]\tvalidation_0-rmse:20.74813\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[7]\tvalidation_0-rmse:20.81255\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[8]\tvalidation_0-rmse:20.69303\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[9]\tvalidation_0-rmse:20.71044\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[10]\tvalidation_0-rmse:20.79641\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[11]\tvalidation_0-rmse:20.78759\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[12]\tvalidation_0-rmse:20.83998\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[13]\tvalidation_0-rmse:20.77980\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Started fitting XGBoost model\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:44.24747\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:A single GBM iteration takes 0.1 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Training XGBoost with 57023 iterations given 7127.988680124283 seconds constraint\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:44.24747\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[1]\tvalidation_0-rmse:34.37446\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[2]\tvalidation_0-rmse:27.88767\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[3]\tvalidation_0-rmse:24.63817\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[4]\tvalidation_0-rmse:22.84209\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[5]\tvalidation_0-rmse:22.35045\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[6]\tvalidation_0-rmse:22.11300\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[7]\tvalidation_0-rmse:22.16132\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[8]\tvalidation_0-rmse:22.21348\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[9]\tvalidation_0-rmse:22.10747" ] }, { "name": "stdout", "output_type": "stream", "text": [ "\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[10]\tvalidation_0-rmse:22.20352\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[11]\tvalidation_0-rmse:22.25761\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[12]\tvalidation_0-rmse:22.25308\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[13]\tvalidation_0-rmse:22.31415\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Started fitting XGBoost model\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:44.48913\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:A single GBM iteration takes 0.1 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Training XGBoost with 57023 iterations given 7127.988005399704 seconds constraint\u001b[0m\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[0]\tvalidation_0-rmse:44.48913\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[1]\tvalidation_0-rmse:34.69001\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[2]\tvalidation_0-rmse:28.87323\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[3]\tvalidation_0-rmse:25.32567\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[4]\tvalidation_0-rmse:23.09943\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[5]\tvalidation_0-rmse:22.12203\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[6]\tvalidation_0-rmse:21.71523\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[7]\tvalidation_0-rmse:21.70934\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[8]\tvalidation_0-rmse:21.74380\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[9]\tvalidation_0-rmse:21.61157\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[10]\tvalidation_0-rmse:21.73507\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[11]\tvalidation_0-rmse:21.84587\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[12]\tvalidation_0-rmse:21.78099\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[13]\tvalidation_0-rmse:21.68890\n" ] }, { "name": "stdout", "output_type": "stream", "text": [ "[14]\tvalidation_0-rmse:21.70025\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `fit_mixer` runtime: 0.49 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Ensembling the mixer\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Mixer: NeuralTs got accuracy: 0.875\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[33mWARNING:lightwood-2879:This model does not output probability estimates\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Mixer: XGBoostArrayMixer got accuracy: 0.869\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Picked best mixer: NeuralTs\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `fit` runtime: 1.4 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Learn phase 7/8] - Ensemble analysis\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Analyzing the ensemble of mixers\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:The block ICP is now running its analyze() method\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:The block ConfStats is now running its analyze() method\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:The block AccStats is now running its analyze() method\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:The block PermutationFeatureImportance is now running its analyze() method\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[33mWARNING:lightwood-2879:Block 'PermutationFeatureImportance' does not support time series nor text encoding, skipping...\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `analyze_ensemble` runtime: 0.16 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Learn phase 8/8] - Adjustment on validation requested\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Updating the mixers\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/torch/amp/grad_scaler.py:131: UserWarning: torch.cuda.amp.GradScaler is enabled, but CUDA is not available. Disabling.\n", " warnings.warn(\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 1: 0.29626286526521045\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Loss @ epoch 2: 0.2954987535874049\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:Updating array of LGBM models...\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:XGBoost mixer does not have a `partial_fit` implementation\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:XGBoost mixer does not have a `partial_fit` implementation\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:XGBoost mixer does not have a `partial_fit` implementation\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:XGBoost mixer does not have a `partial_fit` implementation\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:XGBoost mixer does not have a `partial_fit` implementation\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:XGBoost mixer does not have a `partial_fit` implementation\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `adjust` runtime: 0.09 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `learn` runtime: 1.9 seconds\u001b[0m\n" ] } ], "source": [ "predictor.learn(train)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Predict\n", "\n", "Once the predictor has trained, we can use it to generate 6-month forecasts for each of the test set data points:" ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:23.400033Z", "iopub.status.busy": "2024-05-07T17:15:23.399633Z", "iopub.status.idle": "2024-05-07T17:15:23.626063Z", "shell.execute_reply": "2024-05-07T17:15:23.625426Z" } }, "outputs": [ { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Predict phase 1/4] - Data preprocessing\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/tmp/dcd5321def984b95f7ef126337f7cb3dd9c39250d1d319a417151021214801152.py:587: SettingWithCopyWarning: \n", "A value is trying to be set on a copy of a slice from a DataFrame.\n", "Try using .loc[row_indexer,col_indexer] = value instead\n", "\n", "See the caveats in the documentation: https://pandas.pydata.org/pandas-docs/stable/user_guide/indexing.html#returning-a-view-versus-a-copy\n", " data[col] = [None] * len(data)\n", "\u001b[32mINFO:dataprep_ml-2879:Cleaning the data\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "/opt/hostedtoolcache/Python/3.9.19/x64/lib/python3.9/site-packages/dataprep_ml/cleaners.py:163: UserWarning: The argument 'infer_datetime_format' is deprecated and will be removed in a future version. A strict version of it is now the default, see https://pandas.pydata.org/pdeps/0004-consistent-to-datetime-parsing.html. You can safely remove this argument.\n", " result = pd.to_datetime(element,\n", "\u001b[32mINFO:dataprep_ml-2879:Transforming timeseries data\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `preprocess` runtime: 0.02 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Predict phase 2/4] - Feature generation\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:Featurizing the data\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `featurize` runtime: 0.01 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Predict phase 3/4] - Calling ensemble\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `_timed_call` runtime: 0.09 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:dataprep_ml-2879:[Predict phase 4/4] - Analyzing output\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:The block ICP is now running its explain() method\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:The block ConfStats is now running its explain() method\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:ConfStats.explain() has not been implemented, no modifications will be done to the data insights.\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:The block AccStats is now running its explain() method\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:AccStats.explain() has not been implemented, no modifications will be done to the data insights.\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:The block PermutationFeatureImportance is now running its explain() method\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[32mINFO:lightwood-2879:PermutationFeatureImportance.explain() has not been implemented, no modifications will be done to the data insights.\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `explain` runtime: 0.09 seconds\u001b[0m\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "\u001b[37mDEBUG:lightwood-2879: `predict` runtime: 0.22 seconds\u001b[0m\n" ] } ], "source": [ "forecasts = predictor.predict(test)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Let's check how a single row might look:" ] }, { "cell_type": "code", "execution_count": 8, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:23.628682Z", "iopub.status.busy": "2024-05-07T17:15:23.628360Z", "iopub.status.idle": "2024-05-07T17:15:23.639399Z", "shell.execute_reply": "2024-05-07T17:15:23.638764Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", "\n", "\n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", " \n", "
original_indexpredictionorder_Monthconfidencelowerupperanomalyprediction_sumlower_sumupper_sumconfidence_mean
1010[50.51358374451768, 53.78975402923053, 51.0303...[-273628800.0, -270950400.0, -268272000.0, -26...[0.79, 0.02, 0.9991, 0.9991, 0.9991, 0.9991][30.14139795091352, 32.97332333016865, 0.0, 0....[70.88576953812185, 74.60618472829242, 137.289...False294.4940880.0209.0758650.801067
\n", "
" ], "text/plain": [ " original_index prediction \\\n", "10 10 [50.51358374451768, 53.78975402923053, 51.0303... \n", "\n", " order_Month \\\n", "10 [-273628800.0, -270950400.0, -268272000.0, -26... \n", "\n", " confidence \\\n", "10 [0.79, 0.02, 0.9991, 0.9991, 0.9991, 0.9991] \n", "\n", " lower \\\n", "10 [30.14139795091352, 32.97332333016865, 0.0, 0.... \n", "\n", " upper anomaly \\\n", "10 [70.88576953812185, 74.60618472829242, 137.289... False \n", "\n", " prediction_sum lower_sum upper_sum confidence_mean \n", "10 294.494088 0.0 209.075865 0.801067 " ] }, "execution_count": 8, "metadata": {}, "output_type": "execute_result" } ], "source": [ "forecasts.iloc[[10]]" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "You'll note that the point `prediction` has associated `lower` and `upper` bounds that are a function of the estimated `confidence` the model has on its own output. Apart from this, `order_Month` yields the timestamps of each prediction, the `anomaly` tag will let you know if the observed value falls outside of the predicted region. \n", "\n", "\n", "## Visualizing a forecast\n", "\n", "Okay, time series are much easier to appreciate through plots. Let's make one:\n", "\n", "NOTE: We will use `matplotlib` to generate a simple plot of these forecasts. If you want to run this notebook locally, you will need to `pip install matplotlib` for the following code to work." ] }, { "cell_type": "code", "execution_count": 9, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:23.641944Z", "iopub.status.busy": "2024-05-07T17:15:23.641597Z", "iopub.status.idle": "2024-05-07T17:15:24.035334Z", "shell.execute_reply": "2024-05-07T17:15:24.034722Z" } }, "outputs": [], "source": [ "import matplotlib.pyplot as plt" ] }, { "cell_type": "code", "execution_count": 10, "metadata": { "execution": { "iopub.execute_input": "2024-05-07T17:15:24.038299Z", "iopub.status.busy": "2024-05-07T17:15:24.038005Z", "iopub.status.idle": "2024-05-07T17:15:24.208442Z", "shell.execute_reply": "2024-05-07T17:15:24.207775Z" } }, "outputs": [ { "data": { "image/png": "iVBORw0KGgoAAAANSUhEUgAAA+0AAAK9CAYAAABRvo1QAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguNCwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8fJSN1AAAACXBIWXMAAA9hAAAPYQGoP6dpAACaHElEQVR4nOzdeXxU1f3/8ffMZLJvBLIAScgCCMimQfYdEUXABUFAUHBr3Zdaq+23Cm3Vtv5atVbrt99atIALUvddhIAgoKgg+5qwkwRC9mW2+/uDcstAgAQS7iR5PR+PPMjcc+fez72ZDHnPOfdcm2EYhgAAAAAAQMCxW10AAAAAAACoGaEdAAAAAIAARWgHAAAAACBAEdoBAAAAAAhQhHYAAAAAAAIUoR0AAAAAgABFaAcAAAAAIEAR2gEAAAAACFCEdgAAAAAAAhShHQBwRjabTTNnzrS6jCbv6aefVkZGhhwOh3r27Gl1OU1WWVmZbr31ViUlJclms+n++++3pI6ZM2fKZrPp0KFDluwfANA4ENoBNBmvvPKKbDZbjV+PPPKI1eU1uNdee03PPvus1WU0eQ11nj///HM9/PDDGjBggGbPnq0nn3yy3vfRGH388cf1/oHRk08+qVdeeUV33HGH5syZo2nTptXr9mva37vvvtug+whEFRUVmjlzprKzs60uxVKcBwDnKsjqAgCgvv3mN79Renq637KuXbtaVM3589prr2n9+vWW9Ro2Fw11nhctWiS73a6XX35ZwcHB9brtxuzjjz/WCy+8UK/BfdGiRerbt68ef/zxetvm6Tz55JO67rrrdPXVV5+X/QWKiooKzZo1S5I0dOhQa4uxEOcBwLkitANocq644gr16tWr3rdbXl6uiIiIet8uIEn5+fkKCwsjsJ8H+fn56tKlS71tz+PxyOfz8bPDecX/SUDzwfB4AM3OokWLNGjQIEVERCg2NlZXXXWVNm3a5LfOsWtNN27cqClTpqhFixYaOHCg2T537lxlZWUpLCxMcXFxmjRpkvbs2XPSvlatWqXRo0erRYsWioiIUPfu3fXcc8+Z7T/++KOmT5+ujIwMhYaGKikpSTfffLMOHz7st53S0lLdf//9SktLU0hIiBISEjRy5Eh9//33ko723nz00UfatWuXeUlAWlqa+fzq6mo9/vjjat++vUJCQpSSkqKHH35Y1dXVfvuprq7WAw88oPj4eEVFRWncuHHau3dvrc6ry+XSY489pqysLMXExCgiIkKDBg3S4sWL/dbLzc2VzWbT//t//08vvPCCMjIyFB4erssuu0x79uyRYRj67W9/q+TkZIWFhemqq65SYWHhSft78cUXdeGFFyokJERt2rTRXXfdpaKiIr910tLSNH369JOeO3ToUL8er+zsbNlsNs2fP19PPPGEkpOTFRoaqhEjRmj79u1+zzvdea6Jx+PRb3/7W2VmZiokJERpaWn65S9/6XfubTabZs+erfLycnO7r7zyyim3uW3bNo0fP15JSUkKDQ1VcnKyJk2apOLiYr9zXNM2Tpyf4Nhrffv27Zo+fbpiY2MVExOjGTNmqKKiwu+5X3zxhQYOHKjY2FhFRkbqggsu0C9/+cuTzuObb76pX/7yl0pKSlJERITGjRtX4+/HW2+9Zf4etWrVSlOnTtW+ffvM9unTp+uFF14w6z72dcwbb7yhrKwsRUVFKTo6Wt26dfP7/TrRsfpycnL00UcfmdvLzc2VdDTM33LLLUpMTFRoaKh69OihV1991W8bx79+n332WfPnunHjxhr3abPZVF5erldffdXc34mvyaKiojOee6n27zsnqsvPuDb7mT17tmw2m/75z3/6Pe/JJ5+UzWbTxx9/rNzcXMXHx0uSZs2aZR776UZMuN1uzZo1Sx06dFBoaKhatmypgQMH6osvvvBbb/PmzbruuusUFxen0NBQ9erVS++//77fOscul1q2bJnuvfdexcfHKzY2Vj/5yU/kcrlUVFSkG2+8US1atFCLFi308MMPyzAMv234fD49++yzuvDCCxUaGqrExET95Cc/0ZEjR/zWW716tUaNGqVWrVopLCxM6enpuvnmmyWpVuehLsezZMkS3XnnnUpISFBycvIpzyWApoWedgBNTnFx8UkTO7Vq1UqStHDhQl1xxRXKyMjQzJkzVVlZqeeff14DBgzQ999/f1IAmzBhgjp06KAnn3zS/IPuiSee0K9//WtNnDhRt956qwoKCvT8889r8ODB+uGHHxQbGyvpaMAZM2aMWrdurfvuu09JSUnatGmTPvzwQ913333mOjt37tSMGTOUlJSkDRs26O9//7s2bNiglStXmgHlpz/9qRYsWKC7775bXbp00eHDh7Vs2TJt2rRJF198sX71q1+puLhYe/fu1TPPPCNJioyMlHT0D89x48Zp2bJluv3229W5c2etW7dOzzzzjLZu3ep3re2tt96quXPnasqUKerfv78WLVqkK6+8slbnvaSkRP/4xz80efJk3XbbbSotLdXLL7+sUaNG6ZtvvjlpYrV58+bJ5XLpnnvuUWFhof74xz9q4sSJGj58uLKzs/WLX/xC27dv1/PPP6+HHnrILyDMnDlTs2bN0qWXXqo77rhDW7Zs0d/+9jd9++23Wr58uZxOZ61qPtHvf/972e12PfTQQyouLtYf//hH3XDDDVq1apUknfY8n8qtt96qV199Vdddd51+9rOfadWqVXrqqae0adMmvfPOO5KkOXPm6O9//7u++eYb/eMf/5Ak9e/fv8btuVwujRo1StXV1brnnnuUlJSkffv26cMPP1RRUZFiYmLO6tgnTpyo9PR0PfXUU/r+++/1j3/8QwkJCfrDH/4gSdqwYYPGjBmj7t276ze/+Y1CQkK0fft2LV++/KRtPfHEE7LZbPrFL36h/Px8Pfvss7r00ku1Zs0ahYWFSToaQmbMmKFLLrlETz31lPLy8vTcc89p+fLl5u/RT37yE+3fv19ffPGF5syZ47ePL774QpMnT9aIESPMGjdt2qTly5ebv18n6ty5s+bMmaMHHnhAycnJ+tnPfiZJio+PV2VlpYYOHart27fr7rvvVnp6ut566y1Nnz5dRUVFJ21z9uzZqqqq0u23366QkBDFxcXVuM85c+bo1ltvVe/evXX77bdLkjIzM+t07o+d09q875xOfe1nxowZevvtt/Xggw9q5MiRSklJ0bp16zRr1izdcsstGj16tMrLy/W3v/1Nd9xxh6655hpde+21kqTu3bufsr6ZM2fqqaeeMs9XSUmJVq9ere+//14jR46UdPR1OGDAALVt21aPPPKIIiIiNH/+fF199dX697//rWuuucZvm8d+R2bNmqWVK1fq73//u2JjY/X1118rNTVVTz75pD7++GM9/fTT6tq1q2688UbzuT/5yU/M1+m9996rnJwc/fWvf9UPP/xgvs/k5+frsssuU3x8vB555BHFxsYqNzdXb7/9tqSjr63TnYe6Hs+dd96p+Ph4PfbYYyovLz/jzxxAE2EAQBMxe/ZsQ1KNX8f07NnTSEhIMA4fPmwuW7t2rWG3240bb7zRXPb4448bkozJkyf77SM3N9dwOBzGE0884bd83bp1RlBQkLnc4/EY6enpRrt27YwjR474revz+czvKyoqTjqO119/3ZBkLF261FwWExNj3HXXXac9/iuvvNJo167dScvnzJlj2O1246uvvvJb/tJLLxmSjOXLlxuGYRhr1qwxJBl33nmn33pTpkwxJBmPP/74affv8XiM6upqv2VHjhwxEhMTjZtvvtlclpOTY0gy4uPjjaKiInP5o48+akgyevToYbjdbnP55MmTjeDgYKOqqsowDMPIz883goODjcsuu8zwer3men/9618NScY///lPc1m7du2Mm2666aRahwwZYgwZMsR8vHjxYkOS0blzZ79jeO655wxJxrp168xlpzrPNTl2Tm+99Va/5Q899JAhyVi0aJG57KabbjIiIiLOuM0ffvjBkGS89dZbp1zn2DmePXv2SW0n/iyPvdaP/xkZhmFcc801RsuWLc3HzzzzjCHJKCgoOOV+j53Htm3bGiUlJeby+fPnG5KM5557zjAMw3C5XEZCQoLRtWtXo7Ky0lzvww8/NCQZjz32mLnsrrvuMmr6c+W+++4zoqOjDY/Hc8p6TqVdu3bGlVde6bfs2WefNSQZc+fONZe5XC6jX79+RmRkpHk8x85tdHS0kZ+fX6v9RURE1Pg6rO25r+37zqk0xH4OHDhgxMXFGSNHjjSqq6uNiy66yEhNTTWKi4vNdQoKCmr13nFMjx49Tvq5nGjEiBFGt27dzPcDwzj6ntq/f3+jQ4cO5rJj/x+MGjXK7z23X79+hs1mM37605+ayzwej5GcnOz3nvDVV18Zkox58+b57f/TTz/1W/7OO+8Ykoxvv/32lDWf7jzU9XgGDhx4Vq95AI0bw+MBNDkvvPCCvvjiC78vSTpw4IDWrFmj6dOn+/WKde/eXSNHjtTHH3980rZ++tOf+j1+++235fP5NHHiRB06dMj8SkpKUocOHcyh4D/88INycnJ0//33n9QDdvzw3mO9jpJUVVWlQ4cOqW/fvpJkDn2XpNjYWK1atUr79++v8/l466231LlzZ3Xq1Mmv5uHDh0uSWfOx47/33nv9nl/bCdccDod5Ta/P51NhYaE8Ho969erldyzHTJgwwa9XuE+fPpKkqVOnKigoyG+5y+Uyh00vXLhQLpdL999/v+z2//43dttttyk6OlofffRRreqtyYwZM/yuSx40aJAkaefOnWe1vWPn9MEH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pLbKykrzkoBj4f8vf/nLaes5lZqOZ9WqVVqxYkWtnl9bl156qYKDg/WXv/zFb18vv/yyiouL/Wa7z8zM1MqVK+VyucxlH374Ya1uk3UqpzrPNTn2mjrxHB4b9VDbmfmPV1JSIo/H47esW7dustvt5ushOjparVq10tKlS/3We/HFF+u8v2Nquu3esTsCnDgU+F//+pdKS0vNxwsWLNCBAwfM11ivXr2UkJCgl156ye+5n3zyiTZt2uR3Xo59kHbi79GJt0W02+3mhwK1GZp8otGjR+vgwYN68803zWUej0fPP/+8IiMjNWTIkDpv85iIiIgaPzyqrdq+75yruuxnwYIFevPNN/X73/9ejzzyiCZNmqT/+Z//0datW811wsPDJZ38szuVE48jMjJS7du3N3+eCQkJGjp0qP73f/9XBw4cOOn5BQUFtdpPbUycOFFer1e//e1vT2rzeDzmMR05cuSkc3Xi78WpzsP5PB4AjRs97QCalaefflpXXHGF+vXrp1tuucW85VtMTMxp7x98TGZmpn73u9/p0UcfVW5urq6++mpFRUUpJydH77zzjm6//XY99NBDstvt+tvf/qaxY8eqZ8+emjFjhlq3bq3Nmzdrw4YN+uyzzxQdHa3Bgwfrj3/8o9xut9q2bavPP/9cOTk5fvssLS1VcnKyrrvuOvXo0UORkZFauHChvv32W/3pT38y18vKytKbb76pBx98UJdccokiIyM1duxYTZs2TfPnz9dPf/pTLV68WAMGDJDX69XmzZs1f/58ffbZZ+rVq5d69uypyZMn68UXX1RxcbH69++vL7/80u8+5aczZswYvf3227rmmmt05ZVXKicnRy+99JK6dOmisrKyOv2cTic+Pl6PPvqoZs2apcsvv1zjxo3Tli1b9OKLL+qSSy7R1KlTzXVvvfVWLViwQJdffrkmTpyoHTt2aO7cuSddt18XpzrPNenRo4duuukm/f3vf1dRUZGGDBmib775Rq+++qquvvpqDRs2rM77X7Roke6++25NmDBBHTt2lMfj0Zw5c+RwODR+/Hi/Y//973+vW2+9Vb169dLSpUv9AlVd/eY3v9HSpUt15ZVXql27dsrPz9eLL76o5ORkDRw40G/duLg4DRw4UDNmzFBeXp6effZZtW/fXrfddpukoz2Lf/jDHzRjxgwNGTJEkydPNm/5lpaWpgceeMDcVlZWlqSjEySOGjVKDodDkyZN0q233qrCwkINHz5cycnJ2rVrl55//nn17NnTb1RDbd1+++363//9X02fPl3fffed0tLStGDBAi1fvlzPPvus38R6dZWVlaWFCxfqz3/+s9q0aaP09HRz4sXaqO37zrmq7X7y8/N1xx13aNiwYbr77rslSX/961+1ePFiTZ8+XcuWLZPdbldYWJi6dOmiN998Ux07dlRcXJy6du16yrk+unTpoqFDhyorK0txcXFavXq1eavLY1544QUNHDhQ3bp102233aaMjAzl5eVpxYoV2rt3r9auXXvO50E6eq36T37yEz311FNas2aNLrvsMjmdTm3btk1vvfWWnnvuOV133XV69dVX9eKLL+qaa65RZmamSktL9X//93+Kjo42P7Q73Xk4X8cDoJE7T7PUA0CDO3ZLnNPdescwDGPhwoXGgAEDjLCwMCM6OtoYO3assXHjRr91jt0i6VS3t/r3v/9tDBw40IiIiDAiIiKMTp06GXfddZexZcsWv/WWLVtmjBw50oiKijIiIiKM7t27G88//7zZvnfvXuOaa64xYmNjjZiYGGPChAnG/v37/W4PVF1dbfz85z83evToYW6nR48exosvvui3r7KyMmPKlClGbGysIcnvtmQul8v4wx/+YFx44YVGSEiI0aJFCyMrK8uYNWuW3y2aKisrjXvvvddo2bKlERERYYwdO9bYs2dPrW7b5PP5jCeffNJo166dERISYlx00UXGhx9+aNx0001+tRy7ZdbTTz/t9/xjtws78VZmp/q5/vWvfzU6depkOJ1OIzEx0bjjjjtOur2eYRjGn/70J6Nt27ZGSEiIMWDAAGP16tWnvOXbifuu6dZppzvPNXG73casWbOM9PR0w+l0GikpKcajjz7qd4snw6j9Ld927txp3HzzzUZmZqYRGhpqxMXFGcOGDTMWLlzot15FRYVxyy23GDExMUZUVJQxceJEIz8//5S3fDvxtX7svOfk5BiGYRhffvmlcdVVVxlt2rQxgoODjTZt2hiTJ082tm7daj7n2Hl8/fXXjUcffdRISEgwwsLCjCuvvNLYtWvXScfy5ptvGhdddJEREhJixMXFGTfccIOxd+9ev3U8Ho9xzz33GPHx8YbNZjNv/7ZgwQLjsssuMxISEozg4GAjNTXV+MlPfmIcOHDgjOewplu+GYZh5OXlGTNmzDBatWplBAcHG926dTvptnmnev2ezubNm43BgwcbYWFhhiTz9m+1PffH1PZ950T1vZ9rr73WiIqKMnJzc/2e99577xmSjD/84Q/msq+//trIysoygoODz/g+8rvf/c7o3bu3ERsba4SFhRmdOnUynnjiCcPlcvmtt2PHDuPGG280kpKSDKfTabRt29YYM2aMsWDBgpOO7cT3jVOdi1P9/v397383srKyjLCwMCMqKsro1q2b8fDDDxv79+83DMMwvv/+e2Py5MlGamqqERISYiQkJBhjxowxVq9e7bed052HczkeAM2DzTDOcXYdAAAASdnZ2Ro2bJjeeustXXfddVaXAwBAk8A17QAAAAAABChCOwAAAAAAAYrQDgAAAABAgOKadgAAAAAAAhQ97QAAAAAABChCOwAAAAAAASrI6gICgc/n0/79+xUVFSWbzWZ1OQAAAACAJs4wDJWWlqpNmzay20/dn05ol7R//36lpKRYXQYAAAAAoJnZs2ePkpOTT9lOaJcUFRUl6ejJio6OtrgaAAAAAEBTV1JSopSUFDOPngqhXTKHxEdHRxPaAQAAAADnzZku0WYiOgAAAAAAAhShHQAAAACAAEVoBwAAAAAgQHFNey15vV653W6ry0Az4nQ65XA4rC4DAAAAgIUI7bVQVlamvXv3yjAMq0tBM2Kz2ZScnKzIyEirSwEAAABgEUL7GXi9Xu3du1fh4eGKj48/48x+QH0wDEMFBQXau3evOnToQI87AAAA0EwR2s/A7XbLMAzFx8crLCzM6nLQjMTHxys3N1dut5vQDgAAADRTTERXS/Sw43zjNQcAAACA0A4AAAAAQIAitAMAAAAAEKAI7TilV155RbGxsVaXUS9sNpveffddSVJubq5sNpvWrFlz1turj20AAAAAwJkQ2nFK119/vbZu3Vqn5wwdOlT3339/wxRUT1JSUnTgwAF17dq1VutPnz5dV1999TltAwAAAADOBrPH45TCwsICasZ8t9stp9N5zttxOBxKSkqyfBsAAAAAcCb0tNeRYRhylbss+TIMo9Z1Dh06VHfffbfuvvtuxcTEqFWrVvr1r3/tt40jR47oxhtvVIsWLRQeHq4rrrhC27ZtM9tPHB4/c+ZM9ezZU3PmzFFaWppiYmI0adIklZaWSjraI71kyRI999xzstlsstlsys3NrbG+tLQ0/fa3v9XkyZMVERGhtm3b6oUXXvBbx2az6W9/+5vGjRuniIgIPfHEE5Kk9957TxdffLFCQ0OVkZGhWbNmyePxmM/btm2bBg8erNDQUHXp0kVffPGF33ZrGtq+YcMGjRkzRtHR0YqKitKgQYO0Y8cOzZw5U6+++qree+8985iys7Nr3MaSJUvUu3dvhYSEqHXr1nrkkUf86ho6dKjuvfdePfzww4qLi1NSUpJmzpx52p8jAAAAgOaNnvY6cle49VTkU5bs+9GyRxUcEVzr9V999VXdcsst+uabb7R69WrdfvvtSk1N1W233SbpaMjetm2b3n//fUVHR+sXv/iFRo8erY0bN56yR3vHjh1699139eGHH+rIkSOaOHGifv/73+uJJ57Qc889p61bt6pr1676zW9+I+novcZP5emnn9Yvf/lLzZo1S5999pnuu+8+dezYUSNHjjTXmTlzpn7/+9/r2WefVVBQkL766ivdeOON+stf/mIG69tvv12S9Pjjj8vn8+naa69VYmKiVq1apeLi4jMO19+3b58GDx6soUOHatGiRYqOjtby5cvl8Xj00EMPadOmTSopKdHs2bMlSXFxcdq/f/9J2xg9erSmT5+uf/3rX9q8ebNuu+02hYaG+gXzV199VQ8++KBWrVqlFStWaPr06RowYIDfMQMAAADAMYT2JiwlJUXPPPOMbDabLrjgAq1bt07PPPOMbrvtNjOsL1++XP3795ckzZs3TykpKXr33Xc1YcKEGrfp8/n0yiuvKCoqSpI0bdo0ffnll3riiScUExOj4OBghYeH12ro+IABA/TII49Ikjp27Kjly5frmWee8QuwU6ZM0YwZM8zHN998sx555BHddNNNkqSMjAz99re/1cMPP6zHH39cCxcu1ObNm/XZZ5+pTZs2kqQnn3xSV1xxxSnreOGFFxQTE6M33njD/LCiY8eOZntYWJiqq6tPe0wvvviiUlJS9Ne//lU2m02dOnXS/v379Ytf/EKPPfaY7Pajg1q6d++uxx9/XJLUoUMH/fWvf9WXX35JaAcAAABQI0J7HTnDnXq07FHL9l0Xffv2lc1mMx/369dPf/rTn+T1erVp0yYFBQWpT58+ZnvLli11wQUXaNOmTafcZlpamhnYJal169bKz8+vU13H13Pi42effdZvWa9evfwer127VsuXLzeHykuS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sx544AH96le/qvcCAQBnr7q6WvPmzdPWrVsVFBSk66+/Xt26dbO6LAAAANRSnUP7oUOHlJSUJEn6+OOPNWHCBHXs2FE333yz1q1bV+8FAgDOTnl5uV599VXt2rVLISEhmjp1qjp27Gh1WQAAAKiDOof2xMREbdy4UV6vV59++qlGjhwpSaqoqJDD4aj3AgEAdVdcXKxXXnlFBw4cUHh4uG666Sa1a9fO6rIAAABQR3WePX7GjBmaOHGiWrduLZvNpksvvVSStGrVKnXq1KneCwQA1M3hw4c1Z84cFRcXKzo6WtOmTVOrVq2sLgsAAABnoc6hfebMmeratav27NmjCRMmKCQkRJLkcDj0yCOP1HuBAIDaO3jwoObOnavy8nK1bNlS06ZNU0xMjNVlAQAA4CzVObT/61//0vXXX2+G9WMmT56sN954o94KAwDUze7du/Xaa6+purpaSUlJmjp1qiIiIqwuCwAAAOfAZhiGUZcnOBwOHThwQAkJCX7LDx8+rISEBHm93not8HwoKSlRTEyMOZQUABqbbdu2af78+fJ4PEpNTdXkyZMVGhpqdVkAAAA4hdrm0Dr3tBuGIZvNdtLyvXv3MgQTACywfv16vfPOO/L5fOrQoYMmTJggp9NpdVkAAACoB7UO7RdddJFsNptsNptGjBihoKD/PtXr9SonJ0eXX355gxQJAKjZ6tWr9dFHH0mSunbtqquvvpo7eQAAADQhtQ7tV199tSRpzZo1GjVqlCIjI8224OBgpaWlafz48fVeIACgZsuWLdOXX34pSerVq5dGjx5d40goAAAANF61Du2PP/64JCktLU3XX38910oCgEUMw9DChQv19ddfS5IGDRqkYcOGEdgBAACaoDpf037TTTdJkr777jtt2rRJknThhRfqoosuqt/KAAAn8fl8+vDDD/XDDz9IkkaOHKn+/ftbXBUAAAAaSp1De35+viZNmqTs7GzFxsZKkoqKijRs2DC98cYbio+Pr+8aAQA6On/I22+/rY0bN8pms2ns2LF8YAoAANDE2ev6hHvuuUelpaXasGGDCgsLVVhYqPXr16ukpET33ntvQ9QIAM2ey+XS66+/ro0bN8put+u6664jsAMAADQDdb5Pe0xMjBYuXKhLLrnEb/k333yjyy67TEVFRfVZ33nBfdoBBLLKykq9/vrr2rNnj5xOp66//npl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", "text/plain": [ "
" ] }, "metadata": {}, "output_type": "display_data" } ], "source": [ "plt.figure(figsize=(12, 8))\n", "plt.plot([None for _ in range(forecasts.shape[0])] + forecasts.iloc[-1]['prediction'], color='purple', label='point prediction')\n", "plt.plot([None for _ in range(forecasts.shape[0])] + forecasts.iloc[-1]['lower'], color='grey')\n", "plt.plot([None for _ in range(forecasts.shape[0])] + forecasts.iloc[-1]['upper'], color='grey')\n", "plt.xlabel('timestep')\n", "plt.ylabel('# sunspots')\n", "plt.title(\"Forecasted amount of sunspots for the next semester\")\n", "plt.legend()\n", "plt.show()" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Conclusion\n", "\n", "In this tutorial, we have gone through how you can train a machine learning model with Lightwood to produce forecasts for a univariate time series task.\n", "\n", "There are additional parameters to further customize your timeseries settings and/or prediction insights, so be sure to check the rest of the documentation." ] } ], "metadata": { "interpreter": { "hash": "31f2aee4e71d21fbe5cf8b01ff0e069b9275f58929596ceb00d14d90e3e16cd6" }, "kernelspec": { "display_name": "Python 3", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.9.19" } }, "nbformat": 4, "nbformat_minor": 4 }