Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion docs/changelogs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

Welcome to the TimeCopilot Changelog. Here, you will find a comprehensive list of all the changes, updates, and improvements made to the TimeCopilot project. This section is designed to keep you informed about the latest features, bug fixes, and enhancements as we continue to develop and refine the TimeCopilot experience. Stay tuned for regular updates and feel free to explore the details of each release below.


- [v0.0.26](v0.0.26.md)
- [v0.0.25](v0.0.25.md)
- [v0.0.24](v0.0.24.md)
- [v0.0.23](v0.0.23.md)
Expand Down
12 changes: 9 additions & 3 deletions docs/changelogs/v0.0.26.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
### Features

* **New neural models**: Added 3 new auto neural models: `AutoNBEATS`, `AutoDeepAR`, and `AutoPatchTST`. All support `quantiles` for probabilistic forecasts trained with `MQLoss` and follow the same interface as the existing `AutoNHITS` and `AutoTFT`.
* **New neural models**: Added 3 new auto neural models: `AutoNBEATS`, `AutoDeepAR`, and `AutoPatchTST`. All support `quantiles` for probabilistic forecasts trained with `MQLoss` and follow the same interface as the existing `AutoNHITS` and `AutoTFT`. See [#338](https://github.com/TimeCopilot/timecopilot/pull/338).

```python
import pandas as pd
Expand All @@ -15,7 +15,7 @@
fcst_df = model.forecast(df, h=12, quantiles=[0.1, 0.5, 0.9])
```

* **New ML models**: Added 7 new auto ML models: `AutoLinearRegression`, `AutoXGBoost`, `AutoRidge`, `AutoLasso`, `AutoElasticNet`, `AutoRandomForest`, and `AutoCatboost`. All models support `quantiles` for probabilistic forecasts via conformal prediction and follow the same interface as the existing `AutoLGBM`.
* **New ML models**: Added 7 new auto ML models: `AutoLinearRegression`, `AutoXGBoost`, `AutoRidge`, `AutoLasso`, `AutoElasticNet`, `AutoRandomForest`, and `AutoCatboost`. All models support `quantiles` for probabilistic forecasts via conformal prediction and follow the same interface as the existing `AutoLGBM`. See [#337](https://github.com/TimeCopilot/timecopilot/pull/337).

```python
import pandas as pd
Expand All @@ -38,7 +38,7 @@
fcst_df = model.forecast(df, h=12, quantiles=[0.1, 0.5, 0.9])
```

* **Quantile forecasts for AutoLGBM, AutoNHITS, and AutoTFT**: These models now support quantile forecasts via the `quantiles` parameter. Pass a list of floats between 0 and 1 to receive additional output columns named `model-q-{percentile}`. Note that `level` is not supported for these models; use `quantiles` instead.
* **Quantile forecasts for AutoLGBM, AutoNHITS, and AutoTFT**: These models now support quantile forecasts via the `quantiles` parameter. Pass a list of floats between 0 and 1 to receive additional output columns named `model-q-{percentile}`. Note that `level` is not supported for these models; use `quantiles` instead. See [#336](https://github.com/TimeCopilot/timecopilot/pull/336).

- `AutoLGBM` computes prediction intervals via conformal prediction using cross-validation residuals.
- `AutoNHITS` and `AutoTFT` are trained with [`MQLoss`](https://nixtla.github.io/neuralforecast/losses.pytorch.html) when quantiles are requested.
Expand All @@ -58,6 +58,12 @@
# columns: unique_id, ds, AutoLGBM, AutoLGBM-q-10, AutoLGBM-q-50, AutoLGBM-q-90
```

### Documentation

* **Custom ensembles example**: Added the [Custom Ensembles](https://timecopilot.dev/examples/custom-ensembles/) notebook, showing how to combine multiple models into custom ensembles. See [#340](https://github.com/TimeCopilot/timecopilot/pull/340).

* **Explaining foundation models and ensembles example**: Added the [Explaining Foundation Models and Ensembles](https://timecopilot.dev/examples/explaining-foundation-models-and-ensembles/) notebook. See [#340](https://github.com/TimeCopilot/timecopilot/pull/340).

---

**Full Changelog**: https://github.com/TimeCopilot/timecopilot/compare/v0.0.25...v0.0.26
536 changes: 536 additions & 0 deletions docs/examples/custom-ensembles.ipynb

Large diffs are not rendered by default.

314 changes: 314 additions & 0 deletions docs/examples/explaining-foundation-models-and-ensembles.ipynb
Original file line number Diff line number Diff line change
@@ -0,0 +1,314 @@
{
"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",
Comment on lines +70 to +88
" <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": 3,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.read_csv(\"https://timecopilot.s3.amazonaws.com/public/data/air_passengers.csv\")\n",
"df.head()"
Comment on lines +147 to +148
]
},
{
"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",
")"
Comment on lines +197 to +201
]
},
{
"cell_type": "markdown",
"id": "e1f2a3b4",
"metadata": {},
"source": [
"## Generate forecast"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f2a3b4c5",
"metadata": {},
"outputs": [],
"source": [
"result = tc.forecast(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",
")"
Comment on lines +286 to +289
]
}
],
"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
}
10 changes: 4 additions & 6 deletions mkdocs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,11 +31,9 @@ nav:
- examples/finetuning.ipynb
- examples/cryptocurrency-quickstart.ipynb
- examples/sktime.ipynb
- examples/patchtst-fm.ipynb
- examples/pandas_baseline.ipynb
- examples/dask.ipynb
- examples/pyspark.ipynb
- examples/ray.ipynb
- examples/custom-ensembles.ipynb
- examples/explaining-foundation-models-and-ensembles.ipynb

- Experiments:
- experiments/gift-eval.md
- experiments/fev.md
Expand Down Expand Up @@ -172,4 +170,4 @@ plugins:
- griffe_inherited_docstrings:
merge: true

copyright: 2025 - TimeCopilot
copyright: 2026 - TimeCopilot
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ license = "MIT"
name = "timecopilot"
readme = "README.md"
requires-python = ">=3.10"
version = "0.0.25"
version = "0.0.26"

[project.optional-dependencies]
distributed = [
Expand Down
Loading
Loading