-
-
Notifications
You must be signed in to change notification settings - Fork 69
feat: add new tutorials #340
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
4 commits
Select commit
Hold shift + click to select a range
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Oops, something went wrong.
317 changes: 317 additions & 0 deletions
317
docs/examples/explaining-foundation-models-and-ensembles.ipynb
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,317 @@ | ||
| { | ||
| "cells": [ | ||
| { | ||
| "cell_type": "markdown", | ||
| "id": "a1b2c3d4", | ||
| "metadata": {}, | ||
| "source": [ | ||
| "# Explaining Foundation Models & Ensembles\n", | ||
| "\n", | ||
| "This example shows how to give the `TimeCopilot` agent your own foundation models and an ensemble, and then ask plain-English questions to understand and compare them." | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": 1, | ||
| "id": "b2c3d4e5", | ||
| "metadata": {}, | ||
| "outputs": [], | ||
| "source": [ | ||
| "import nest_asyncio\n", | ||
| "\n", | ||
| "nest_asyncio.apply()" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "id": "c3d4e5f6", | ||
| "metadata": {}, | ||
| "source": [ | ||
| "## Import libraries" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": null, | ||
| "id": "d4e5f6a7", | ||
| "metadata": {}, | ||
| "outputs": [], | ||
| "source": [ | ||
| "import pandas as pd\n", | ||
| "\n", | ||
| "from timecopilot import TimeCopilot\n", | ||
| "from timecopilot.models.foundation.chronos import Chronos\n", | ||
| "from timecopilot.models.ensembles.median import MedianEnsemble\n", | ||
| "from timecopilot.models.stats import SeasonalNaive" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "id": "e5f6a7b8", | ||
| "metadata": {}, | ||
| "source": [ | ||
| "## Load the dataset\n", | ||
| "\n", | ||
| "The DataFrame must include at least the following columns:\n", | ||
| "- unique_id: Unique identifier for each time series (string)\n", | ||
| "- ds: Date column (datetime format)\n", | ||
| "- y: Target variable for forecasting (float format)\n", | ||
| "\n", | ||
| "The pandas frequency will be inferred from the ds column, if not provided.\n", | ||
| "If the seasonality is not provided, it will be inferred based on the frequency.\n", | ||
| "If the horizon is not set, it will default to 2 times the inferred seasonality." | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": 3, | ||
| "id": "f6a7b8c9", | ||
| "metadata": {}, | ||
| "outputs": [ | ||
| { | ||
| "data": { | ||
| "text/html": [ | ||
| "<div>\n", | ||
| "<style scoped>\n", | ||
| " .dataframe tbody tr th:only-of-type {\n", | ||
| " vertical-align: middle;\n", | ||
| " }\n", | ||
| "\n", | ||
| " .dataframe tbody tr th {\n", | ||
| " vertical-align: top;\n", | ||
| " }\n", | ||
| "\n", | ||
| " .dataframe thead th {\n", | ||
| " text-align: right;\n", | ||
| " }\n", | ||
| "</style>\n", | ||
| "<table border=\"1\" class=\"dataframe\">\n", | ||
| " <thead>\n", | ||
| " <tr style=\"text-align: right;\">\n", | ||
| " <th></th>\n", | ||
| " <th>unique_id</th>\n", | ||
| " <th>ds</th>\n", | ||
| " <th>y</th>\n", | ||
| " </tr>\n", | ||
| " </thead>\n", | ||
| " <tbody>\n", | ||
| " <tr>\n", | ||
| " <th>0</th>\n", | ||
| " <td>AirPassengers</td>\n", | ||
| " <td>1949-01-01</td>\n", | ||
| " <td>112</td>\n", | ||
| " </tr>\n", | ||
| " <tr>\n", | ||
| " <th>1</th>\n", | ||
| " <td>AirPassengers</td>\n", | ||
| " <td>1949-02-01</td>\n", | ||
| " <td>118</td>\n", | ||
| " </tr>\n", | ||
| " <tr>\n", | ||
| " <th>2</th>\n", | ||
| " <td>AirPassengers</td>\n", | ||
| " <td>1949-03-01</td>\n", | ||
| " <td>132</td>\n", | ||
| " </tr>\n", | ||
| " <tr>\n", | ||
| " <th>3</th>\n", | ||
| " <td>AirPassengers</td>\n", | ||
| " <td>1949-04-01</td>\n", | ||
| " <td>129</td>\n", | ||
| " </tr>\n", | ||
| " <tr>\n", | ||
| " <th>4</th>\n", | ||
| " <td>AirPassengers</td>\n", | ||
| " <td>1949-05-01</td>\n", | ||
| " <td>121</td>\n", | ||
| " </tr>\n", | ||
| " </tbody>\n", | ||
| "</table>\n", | ||
| "</div>" | ||
| ], | ||
| "text/plain": [ | ||
| " unique_id ds y\n", | ||
| "0 AirPassengers 1949-01-01 112\n", | ||
| "1 AirPassengers 1949-02-01 118\n", | ||
| "2 AirPassengers 1949-03-01 132\n", | ||
| "3 AirPassengers 1949-04-01 129\n", | ||
| "4 AirPassengers 1949-05-01 121" | ||
| ] | ||
| }, | ||
| "execution_count": null, | ||
| "metadata": {}, | ||
| "output_type": "execute_result" | ||
| } | ||
| ], | ||
| "source": [ | ||
| "df = pd.read_csv(\n", | ||
| " \"https://timecopilot.s3.amazonaws.com/public/data/air_passengers.csv\",\n", | ||
| " parse_dates=[\"ds\"],\n", | ||
| ")\n", | ||
| "df.head()" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "id": "a7b8c9d0", | ||
| "metadata": {}, | ||
| "source": [ | ||
| "## Build foundation models and an ensemble\n", | ||
| "\n", | ||
| "Every model in TimeCopilot is a `Forecaster`, including foundation models and ensembles. Here we instantiate two lightweight, CPU-friendly Chronos checkpoints and a `SeasonalNaive` baseline.\n", | ||
| "\n", | ||
| "We then wrap them in a `MedianEnsemble`, which combines its members by taking the per-step median of their forecasts, a simple and robust way to blend models." | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": 4, | ||
| "id": "b8c9d0e1", | ||
| "metadata": {}, | ||
| "outputs": [], | ||
| "source": [ | ||
| "chronos_bolt = Chronos(repo_id=\"amazon/chronos-bolt-tiny\", alias=\"Chronos-Bolt\")\n", | ||
| "chronos_t5 = Chronos(repo_id=\"amazon/chronos-t5-tiny\", alias=\"Chronos-T5\")\n", | ||
| "seasonal_naive = SeasonalNaive()\n", | ||
| "\n", | ||
| "ensemble = MedianEnsemble(\n", | ||
| " models=[chronos_bolt, chronos_t5, seasonal_naive],\n", | ||
| " alias=\"MedianEnsemble\",\n", | ||
| ")" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "id": "c9d0e1f2", | ||
| "metadata": {}, | ||
| "source": [ | ||
| "## Initialize the agent with your models\n", | ||
| "\n", | ||
| "Pass your foundation models and the ensemble to the agent through the `forecasters` parameter. The agent exposes them to the LLM by their `alias`, so it can cross-validate, select, and reason about each one when you ask questions." | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": 5, | ||
| "id": "d0e1f2a3", | ||
| "metadata": {}, | ||
| "outputs": [], | ||
| "source": [ | ||
| "tc = TimeCopilot(\n", | ||
| " llm=\"openai:gpt-4o\",\n", | ||
| " forecasters=[chronos_bolt, chronos_t5, seasonal_naive, ensemble],\n", | ||
| " retries=3,\n", | ||
| ")" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "id": "e1f2a3b4", | ||
| "metadata": {}, | ||
| "source": [ | ||
| "## Generate forecast" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": null, | ||
| "id": "f2a3b4c5", | ||
| "metadata": {}, | ||
| "outputs": [], | ||
| "source": [ | ||
| "result = tc.analyze(df=df)" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "markdown", | ||
| "id": "a3b4c5d6", | ||
| "metadata": {}, | ||
| "source": [ | ||
| "## Ask questions about the models\n", | ||
| "\n", | ||
| "Now you can interrogate the analysis in natural language. The agent grounds its answers in the cross-validation results of the models you provided." | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": 7, | ||
| "id": "b4c5d6e7", | ||
| "metadata": {}, | ||
| "outputs": [ | ||
| { | ||
| "name": "stdout", | ||
| "output_type": "stream", | ||
| "text": [ | ||
| "The model that performed best is the \"Chronos-Bolt\" model, which achieved the lowest MASE score of 1.2913, as reflected in the evaluation results. The Mean Absolute Scaled Error (MASE) is used to evaluate the performance of forecasting models, and lower scores indicate better performance.\n", | ||
| "\n", | ||
| "Reasons for Chronos-Bolt's superior performance could include:\n", | ||
| "\n", | ||
| "1. **Capability to Capture Trends**: The \"AirPassengers\" time series exhibits a strong trend component, with a trend strength of approximately 0.9972. Chronos-Bolt might be better at capturing trends due to its model architecture or feature selection.\n", | ||
| "\n", | ||
| "2. **Handling Seasonality**: The series has a marked seasonality with a seasonal period of 12 months. The model likely captures this effectively, indicated by the strong seasonal strength of approximately 0.9815 in the series.\n", | ||
| "\n", | ||
| "3. **Robustness to Anomalies**: Although anomalies were detected within the data, Chronos-Bolt's performance suggests it effectively handles such irregularities without much degradation in accuracy.\n", | ||
| "\n", | ||
| "These characteristics might have contributed to the Chronos-Bolt model's superior performance in forecasting this time series.\n" | ||
| ] | ||
| } | ||
| ], | ||
| "source": [ | ||
| "print(tc.query(\"Which model performed best and why?\").output)" | ||
| ] | ||
| }, | ||
| { | ||
| "cell_type": "code", | ||
| "execution_count": 8, | ||
| "id": "c5d6e7f8", | ||
| "metadata": {}, | ||
| "outputs": [ | ||
| { | ||
| "name": "stdout", | ||
| "output_type": "stream", | ||
| "text": [ | ||
| "The \"MedianEnsemble\" model combines the forecasts from multiple foundational models by taking the median of their predicted values for each time point. This ensemble approach is often used to enhance the stability and accuracy of forecast predictions by leveraging the strengths while minimizing the weaknesses of the individual models.\n", | ||
| "\n", | ||
| "Here's how the MedianEnsemble likely combines the forecasts:\n", | ||
| "\n", | ||
| "1. **Aggregate Predictions**: At each time point for which a forecast is needed, the ensemble collects the forecasted values from the different base models used within the ensemble. For instance, models like Chronos-Bolt, Chronos-T5, and SeasonalNaive might all provide predictions for the same month.\n", | ||
| "\n", | ||
| "2. **Calculate Median**: The median value of these predictions is calculated. The median is a measure of central tendency that is less sensitive to outliers and individual model extremes than the mean. This can be especially beneficial if one or more models produce predictions that are significantly off-mark for certain points, potentially due to anomalies or model-specific biases.\n", | ||
| "\n", | ||
| "3. **Generate Final Forecast**: The median value at each time point is then used as the final forecast from the MedianEnsemble model.\n", | ||
| "\n", | ||
| "This approach helps in providing a consensual forecast that is deemed robust, as it somewhat averages out the idiosyncrasies and noise from individual models. It's particularly advantageous in situations where there's variability in forecast reliability across time points or when handling data with anomalies, as it tends to smooth out inconsistency from individual forecasts.\n" | ||
| ] | ||
| } | ||
| ], | ||
| "source": [ | ||
| "print(\n", | ||
| " tc.query(\n", | ||
| " \"Explain how the MedianEnsemble combines the foundation models' forecasts.\"\n", | ||
| " ).output\n", | ||
| ")" | ||
| ] | ||
| } | ||
| ], | ||
| "metadata": { | ||
| "kernelspec": { | ||
| "display_name": ".venv", | ||
| "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.11.12" | ||
| } | ||
| }, | ||
| "nbformat": 4, | ||
| "nbformat_minor": 5 | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.