diff --git a/nbs/core.ipynb b/nbs/core.ipynb index 737a12420..a4f164ed5 100644 --- a/nbs/core.ipynb +++ b/nbs/core.ipynb @@ -87,7 +87,7 @@ " TFT, VanillaTransformer,\n", " Informer, Autoformer, FEDformer,\n", " StemGNN, PatchTST, TimesNet, TimeLLM, TSMixer, TSMixerx,\n", - " MLPMultivariate\n", + " MLPMultivariate, iTransformer\n", ")" ] }, @@ -228,6 +228,7 @@ " 'tsmixer': TSMixer, 'autotsmixer': TSMixer,\n", " 'tsmixerx': TSMixerx, 'autotsmixerx': TSMixerx,\n", " 'mlpmultivariate': MLPMultivariate, 'automlpmultivariate': MLPMultivariate,\n", + " 'itransformer': iTransformer, 'autoitransformer': iTransformer\n", "}" ] }, diff --git a/nbs/imgs_models/iTransformer.png b/nbs/imgs_models/iTransformer.png new file mode 100644 index 000000000..01605df9a Binary files /dev/null and b/nbs/imgs_models/iTransformer.png differ diff --git a/nbs/models.ipynb b/nbs/models.ipynb index 0dafa2598..82331c3b2 100644 --- a/nbs/models.ipynb +++ b/nbs/models.ipynb @@ -60,6 +60,7 @@ "from neuralforecast.models.fedformer import FEDformer\n", "from neuralforecast.models.patchtst import PatchTST\n", "from neuralforecast.models.timesnet import TimesNet\n", + "from neuralforecast.models.itransformer import iTransformer\n", "\n", "from neuralforecast.models.stemgnn import StemGNN\n", "from neuralforecast.models.hint import HINT\n", @@ -2706,6 +2707,157 @@ "model.fit(dataset=dataset)" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "a61c3be9", + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "class AutoiTransformer(BaseAuto):\n", + "\n", + " default_config = {\n", + " \"input_size_multiplier\": [1, 2, 3, 4, 5],\n", + " \"h\": None,\n", + " \"n_series\": None,\n", + " \"hidden_size\": tune.choice([64, 128, 256]),\n", + " \"n_heads\": tune.choice([4, 8]),\n", + " \"learning_rate\": tune.loguniform(1e-4, 1e-1),\n", + " \"scaler_type\": tune.choice([None, 'robust', 'standard']),\n", + " \"max_steps\": tune.choice([500, 1000, 2000]),\n", + " \"batch_size\": tune.choice([32, 64, 128, 256]),\n", + " \"loss\": None,\n", + " \"random_seed\": tune.randint(1, 20),\n", + " }\n", + "\n", + " def __init__(self,\n", + " h,\n", + " n_series,\n", + " loss=MAE(),\n", + " valid_loss=None,\n", + " config=None, \n", + " search_alg=BasicVariantGenerator(random_state=1),\n", + " num_samples=10,\n", + " refit_with_val=False,\n", + " cpus=cpu_count(),\n", + " gpus=torch.cuda.device_count(),\n", + " verbose=False,\n", + " alias=None,\n", + " backend='ray',\n", + " callbacks=None):\n", + " \n", + " # Define search space, input/output sizes\n", + " if config is None:\n", + " config = self.get_default_config(h=h, backend=backend, n_series=n_series) \n", + "\n", + " # Always use n_series from parameters, raise exception with Optuna because we can't enforce it\n", + " if backend == 'ray':\n", + " config['n_series'] = n_series\n", + " elif backend == 'optuna':\n", + " mock_trial = MockTrial()\n", + " if ('n_series' in config(mock_trial) and config(mock_trial)['n_series'] != n_series) or ('n_series' not in config(mock_trial)):\n", + " raise Exception(f\"config needs 'n_series': {n_series}\") \n", + "\n", + " super(AutoiTransformer, self).__init__(\n", + " cls_model=iTransformer, \n", + " h=h,\n", + " loss=loss,\n", + " valid_loss=valid_loss,\n", + " config=config,\n", + " search_alg=search_alg,\n", + " num_samples=num_samples, \n", + " refit_with_val=refit_with_val,\n", + " cpus=cpus,\n", + " gpus=gpus,\n", + " verbose=verbose,\n", + " alias=alias,\n", + " backend=backend,\n", + " callbacks=callbacks, \n", + " )\n", + "\n", + " @classmethod\n", + " def get_default_config(cls, h, backend, n_series):\n", + " config = cls.default_config.copy() \n", + " config['input_size'] = tune.choice([h * x \\\n", + " for x in config[\"input_size_multiplier\"]])\n", + "\n", + " # Rolling windows with step_size=1 or step_size=h\n", + " # See `BaseWindows` and `BaseRNN`'s create_windows\n", + " config['step_size'] = tune.choice([1, h])\n", + " del config[\"input_size_multiplier\"]\n", + " if backend == 'optuna':\n", + " # Always use n_series from parameters\n", + " config['n_series'] = n_series\n", + " config = cls._ray_config_to_optuna(config) \n", + "\n", + " return config " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "8f416fa0", + "metadata": {}, + "outputs": [], + "source": [ + "show_doc(AutoiTransformer, title_level=3)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ffd40db", + "metadata": {}, + "outputs": [], + "source": [ + "%%capture\n", + "# Use your own config or AutoiTransformer.default_config\n", + "config = dict(max_steps=1, val_check_steps=1, input_size=12, hidden_size=16)\n", + "model = AutoiTransformer(h=12, n_series=1, config=config, num_samples=1, cpus=1)\n", + "\n", + "# Fit and predict\n", + "model.fit(dataset=dataset)\n", + "y_hat = model.predict(dataset=dataset)\n", + "\n", + "# Optuna\n", + "model = AutoiTransformer(h=12, n_series=1, config=None, backend='optuna')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7a2052de", + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "# Check Optuna\n", + "assert model.config(MockTrial())['h'] == 12\n", + "\n", + "# Unit test to test that Auto* model contains all required arguments from BaseAuto\n", + "test_args(AutoiTransformer, exclude_args=['cls_model']) \n", + "\n", + "# Unit test for situation: Optuna with updated default config\n", + "my_config = AutoiTransformer.get_default_config(h=12, n_series=1, backend='optuna')\n", + "def my_config_new(trial):\n", + " config = {**my_config(trial)}\n", + " config.update({'max_steps': 1, 'val_check_steps': 1, 'input_size': 12, 'hidden_size': 16})\n", + " return config\n", + "\n", + "model = AutoiTransformer(h=12, n_series=1, config=my_config_new, backend='optuna', num_samples=1, cpus=1)\n", + "model.fit(dataset=dataset)\n", + "\n", + "# Unit test for situation: Ray with updated default config\n", + "my_config = AutoiTransformer.get_default_config(h=12, n_series=1, backend='ray')\n", + "my_config['max_steps'] = 1\n", + "my_config['val_check_steps'] = 1\n", + "my_config['input_size'] = 12\n", + "my_config['hidden_size'] = 16\n", + "model = AutoiTransformer(h=12, n_series=1, config=my_config, backend='ray', num_samples=1, cpus=1)\n", + "model.fit(dataset=dataset)" + ] + }, { "attachments": {}, "cell_type": "markdown", diff --git a/nbs/models.itransformer.ipynb b/nbs/models.itransformer.ipynb new file mode 100644 index 000000000..16f223d3f --- /dev/null +++ b/nbs/models.itransformer.ipynb @@ -0,0 +1,1170 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| default_exp models.itransformer" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| hide\n", + "from fastcore.test import test_eq\n", + "from nbdev.showdoc import show_doc" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# iTransformer" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The iTransformer model simply takes the Transformer architecture but it applies the attention and feed-forward network on the inverted dimensions. This means that time points of each individual series are embedded into tokens. That way, the attention mechanisms learn multivariate correlation and the feed-forward network learns non-linear relationships.\n", + "\n", + "**References**\n", + "- [Yong Liu, Tengge Hu, Haoran Zhang, Haixu Wu, Shiyu Wang, Lintao Ma, Mingsheng Long. \"iTransformer: Inverted Transformers Are Effective for Time Series Forecasting\"](https://arxiv.org/abs/2310.06625)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "![Figure 1. Architecture of iTransformer.](imgs_models/itransformer.png)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "import torch\n", + "import torch.nn as nn\n", + "import torch.nn.functional as F\n", + "\n", + "import numpy as np\n", + "\n", + "from typing import Optional\n", + "from math import sqrt\n", + "\n", + "from neuralforecast.losses.pytorch import MAE\n", + "from neuralforecast.common._base_multivariate import BaseMultivariate\n", + "\n", + "from neuralforecast.common._modules import TransEncoder, TransEncoderLayer, AttentionLayer" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 1. Auxiliary functions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1.1 Attention" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| exporti\n", + "\n", + "class TriangularCausalMask():\n", + " def __init__(self, B, L, device=\"cpu\"):\n", + " mask_shape = [B, 1, L, L]\n", + " with torch.no_grad():\n", + " self._mask = torch.triu(torch.ones(mask_shape, dtype=torch.bool), diagonal=1).to(device)\n", + "\n", + " @property\n", + " def mask(self):\n", + " return self._mask\n", + "\n", + "class FullAttention(nn.Module):\n", + " def __init__(self, mask_flag=True, factor=5, scale=None, attention_dropout=0.1, output_attention=False):\n", + " super(FullAttention, self).__init__()\n", + " self.scale = scale\n", + " self.mask_flag = mask_flag\n", + " self.output_attention = output_attention\n", + " self.dropout = nn.Dropout(attention_dropout)\n", + "\n", + " def forward(self, queries, keys, values, attn_mask, tau=None, delta=None):\n", + " B, L, H, E = queries.shape\n", + " _, S, _, D = values.shape\n", + " scale = self.scale or 1. / sqrt(E)\n", + "\n", + " scores = torch.einsum(\"blhe,bshe->bhls\", queries, keys)\n", + "\n", + " if self.mask_flag:\n", + " if attn_mask is None:\n", + " attn_mask = TriangularCausalMask(B, L, device=queries.device)\n", + "\n", + " scores.masked_fill_(attn_mask.mask, -np.inf)\n", + "\n", + " A = self.dropout(torch.softmax(scale * scores, dim=-1))\n", + " V = torch.einsum(\"bhls,bshd->blhd\", A, values)\n", + "\n", + " if self.output_attention:\n", + " return (V.contiguous(), A)\n", + " else:\n", + " return (V.contiguous(), None) " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 1.2 Inverted embedding" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| exporti\n", + "\n", + "class DataEmbedding_inverted(nn.Module):\n", + " def __init__(self, c_in, hidden_size, dropout=0.1):\n", + " super(DataEmbedding_inverted, self).__init__()\n", + " self.value_embedding = nn.Linear(c_in, hidden_size)\n", + " self.dropout = nn.Dropout(p=dropout)\n", + "\n", + " def forward(self, x, x_mark):\n", + " x = x.permute(0, 2, 1)\n", + " # x: [Batch Variate Time]\n", + " if x_mark is None:\n", + " x = self.value_embedding(x)\n", + " else:\n", + " # the potential to take covariates (e.g. timestamps) as tokens\n", + " x = self.value_embedding(torch.cat([x, x_mark.permute(0, 2, 1)], 1)) \n", + " # x: [Batch Variate hidden_size]\n", + " return self.dropout(x)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 2. Model" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "#| export\n", + "\n", + "class iTransformer(BaseMultivariate):\n", + "\n", + " \"\"\" iTransformer\n", + "\n", + " **Parameters:**
\n", + " `h`: int, Forecast horizon.
\n", + " `input_size`: int, autorregresive inputs size, y=[1,2,3,4] input_size=2 -> y_[t-2:t]=[1,2].
\n", + " `n_series`: int, number of time-series.
\n", + " `futr_exog_list`: str list, future exogenous columns.
\n", + " `hist_exog_list`: str list, historic exogenous columns.
\n", + " `stat_exog_list`: str list, static exogenous columns.
\n", + " `hidden_size`: int, dimension of the model.
\n", + " `n_heads`: int, number of heads.
\n", + " `e_layers`: int, number of encoder layers.
\n", + " `d_layers`: int, number of decoder layers.
\n", + " `d_ff`: int, dimension of fully-connected layer.
\n", + " `factor`: int, attention factor.
\n", + " `dropout`: float, dropout rate.
\n", + " `use_norm`: bool, whether to normalize or not.
\n", + " `loss`: PyTorch module, instantiated train loss class from [losses collection](https://nixtla.github.io/neuralforecast/losses.pytorch.html).
\n", + " `valid_loss`: PyTorch module=`loss`, instantiated valid loss class from [losses collection](https://nixtla.github.io/neuralforecast/losses.pytorch.html).
\n", + " `max_steps`: int=1000, maximum number of training steps.
\n", + " `learning_rate`: float=1e-3, Learning rate between (0, 1).
\n", + " `num_lr_decays`: int=-1, Number of learning rate decays, evenly distributed across max_steps.
\n", + " `early_stop_patience_steps`: int=-1, Number of validation iterations before early stopping.
\n", + " `val_check_steps`: int=100, Number of training steps between every validation loss check.
\n", + " `batch_size`: int=32, number of different series in each batch.
\n", + " `step_size`: int=1, step size between each window of temporal data.
\n", + " `scaler_type`: str='identity', type of scaler for temporal inputs normalization see [temporal scalers](https://nixtla.github.io/neuralforecast/common.scalers.html).
\n", + " `random_seed`: int=1, random_seed for pytorch initializer and numpy generators.
\n", + " `num_workers_loader`: int=os.cpu_count(), workers to be used by `TimeSeriesDataLoader`.
\n", + " `drop_last_loader`: bool=False, if True `TimeSeriesDataLoader` drops last non-full batch.
\n", + " `alias`: str, optional, Custom name of the model.
\n", + " `optimizer`: Subclass of 'torch.optim.Optimizer', optional, user specified optimizer instead of the default choice (Adam).
\n", + " `optimizer_kwargs`: dict, optional, list of parameters used by the user specified `optimizer`.
\n", + " `**trainer_kwargs`: int, keyword trainer arguments inherited from [PyTorch Lighning's trainer](https://pytorch-lightning.readthedocs.io/en/stable/api/pytorch_lightning.trainer.trainer.Trainer.html?highlight=trainer).
\n", + " \n", + " **References**
\n", + " - [Yong Liu, Tengge Hu, Haoran Zhang, Haixu Wu, Shiyu Wang, Lintao Ma, Mingsheng Long. \"iTransformer: Inverted Transformers Are Effective for Time Series Forecasting\"](https://arxiv.org/abs/2310.06625)\n", + " \"\"\"\n", + "\n", + " # Class attributes\n", + " SAMPLING_TYPE = 'multivariate'\n", + "\n", + " def __init__(self,\n", + " h,\n", + " input_size,\n", + " n_series,\n", + " futr_exog_list = None,\n", + " hist_exog_list = None,\n", + " stat_exog_list = None,\n", + " hidden_size: int = 512,\n", + " n_heads: int = 8,\n", + " e_layers: int = 2,\n", + " d_layers: int = 1,\n", + " d_ff: int = 2048,\n", + " factor: int = 1,\n", + " dropout: float = 0.1,\n", + " use_norm: bool = True,\n", + " loss = MAE(),\n", + " valid_loss = None,\n", + " max_steps: int = 1000,\n", + " learning_rate: float = 1e-3,\n", + " num_lr_decays: int = -1,\n", + " early_stop_patience_steps: int =-1,\n", + " val_check_steps: int = 100,\n", + " batch_size: int = 32,\n", + " step_size: int = 1,\n", + " scaler_type: str = 'identity',\n", + " random_seed: int = 1,\n", + " num_workers_loader: int = 0,\n", + " drop_last_loader: bool = False,\n", + " optimizer = None,\n", + " optimizer_kwargs = None,\n", + " **trainer_kwargs):\n", + " \n", + " super(iTransformer, self).__init__(h=h,\n", + " input_size=input_size,\n", + " n_series=n_series,\n", + " stat_exog_list = None,\n", + " futr_exog_list = None,\n", + " hist_exog_list = None,\n", + " loss=loss,\n", + " valid_loss=valid_loss,\n", + " max_steps=max_steps,\n", + " learning_rate=learning_rate,\n", + " num_lr_decays=num_lr_decays,\n", + " early_stop_patience_steps=early_stop_patience_steps,\n", + " val_check_steps=val_check_steps,\n", + " batch_size=batch_size,\n", + " step_size=step_size,\n", + " scaler_type=scaler_type,\n", + " random_seed=random_seed,\n", + " num_workers_loader=num_workers_loader,\n", + " drop_last_loader=drop_last_loader,\n", + " optimizer=optimizer,\n", + " optimizer_kwargs=optimizer_kwargs,\n", + " **trainer_kwargs)\n", + " \n", + " # Asserts\n", + " if stat_exog_list is not None:\n", + " raise Exception(\"iTransformer does not support static exogenous variables\")\n", + " if futr_exog_list is not None:\n", + " raise Exception(\"iTransformer does not support future exogenous variables\")\n", + " if hist_exog_list is not None:\n", + " raise Exception(\"iTransformer does not support historical exogenous variables\")\n", + " \n", + " self.enc_in = n_series\n", + " self.dec_in = n_series\n", + " self.c_out = n_series\n", + " self.hidden_size = hidden_size\n", + " self.n_heads = n_heads\n", + " self.e_layers = e_layers\n", + " self.d_layers = d_layers\n", + " self.d_ff = d_ff\n", + " self.factor = factor\n", + " self.dropout = dropout\n", + " self.use_norm = use_norm\n", + "\n", + " # Architecture\n", + " self.enc_embedding = DataEmbedding_inverted(input_size, self.hidden_size, self.dropout)\n", + "\n", + " self.encoder = TransEncoder(\n", + " [\n", + " TransEncoderLayer(\n", + " AttentionLayer(\n", + " FullAttention(False, self.factor, attention_dropout=self.dropout), self.hidden_size, self.n_heads),\n", + " self.hidden_size,\n", + " self.d_ff,\n", + " dropout=self.dropout,\n", + " activation=F.gelu\n", + " ) for l in range(self.e_layers)\n", + " ],\n", + " norm_layer=torch.nn.LayerNorm(self.hidden_size)\n", + " )\n", + "\n", + " self.projector = nn.Linear(self.hidden_size, h, bias=True)\n", + " \n", + " def forecast(self, x_enc):\n", + " if self.use_norm:\n", + " # Normalization from Non-stationary Transformer\n", + " means = x_enc.mean(1, keepdim=True).detach()\n", + " x_enc = x_enc - means\n", + " stdev = torch.sqrt(torch.var(x_enc, dim=1, keepdim=True, unbiased=False) + 1e-5)\n", + " x_enc /= stdev\n", + "\n", + " _, _, N = x_enc.shape # B L N\n", + " # B: batch_size; E: hidden_size; \n", + " # L: input_size; S: horizon(h);\n", + " # N: number of variate (tokens), can also includes covariates\n", + "\n", + " # Embedding\n", + " # B L N -> B N E (B L N -> B L E in the vanilla Transformer)\n", + " enc_out = self.enc_embedding(x_enc, None) # covariates (e.g timestamp) can be also embedded as tokens\n", + " \n", + " # B N E -> B N E (B L E -> B L E in the vanilla Transformer)\n", + " # the dimensions of embedded time series has been inverted, and then processed by native attn, layernorm and ffn modules\n", + " enc_out, attns = self.encoder(enc_out, attn_mask=None)\n", + "\n", + " # B N E -> B N S -> B S N \n", + " dec_out = self.projector(enc_out).permute(0, 2, 1)[:, :, :N] # filter the covariates\n", + "\n", + " if self.use_norm:\n", + " # De-Normalization from Non-stationary Transformer\n", + " dec_out = dec_out * (stdev[:, 0, :].unsqueeze(1).repeat(1, self.h, 1))\n", + " dec_out = dec_out + (means[:, 0, :].unsqueeze(1).repeat(1, self.h, 1))\n", + "\n", + " return dec_out\n", + " \n", + " def forward(self, windows_batch):\n", + " insample_y = windows_batch['insample_y']\n", + "\n", + " y_pred = self.forecast(insample_y)\n", + " y_pred = y_pred[:, -self.h:, :]\n", + " y_pred = self.loss.domain_map(y_pred)\n", + "\n", + " # domain_map might have squeezed the last dimension in case n_series == 1\n", + " if y_pred.ndim == 2:\n", + " return y_pred.unsqueeze(-1)\n", + " else:\n", + " return y_pred\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "---\n", + "\n", + "[source](https://github.com/Nixtla/neuralforecast/blob/main/neuralforecast/models/itransformer.py#L94){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", + "\n", + "### iTransformer\n", + "\n", + "> iTransformer (h, input_size, n_series, futr_exog_list=None,\n", + "> hist_exog_list=None, stat_exog_list=None,\n", + "> hidden_size:int=512, n_heads:int=8, e_layers:int=2,\n", + "> d_layers:int=1, d_ff:int=2048, factor:int=1,\n", + "> dropout:float=0.1, use_norm:bool=True, loss=MAE(),\n", + "> valid_loss=None, max_steps:int=1000,\n", + "> learning_rate:float=0.001, num_lr_decays:int=-1,\n", + "> early_stop_patience_steps:int=-1, val_check_steps:int=100,\n", + "> batch_size:int=32, step_size:int=1,\n", + "> scaler_type:str='identity', random_seed:int=1,\n", + "> num_workers_loader:int=0, drop_last_loader:bool=False,\n", + "> optimizer=None, optimizer_kwargs=None, **trainer_kwargs)\n", + "\n", + "iTransformer\n", + "\n", + "**Parameters:**
\n", + "`h`: int, Forecast horizon.
\n", + "`input_size`: int, autorregresive inputs size, y=[1,2,3,4] input_size=2 -> y_[t-2:t]=[1,2].
\n", + "`n_series`: int, number of time-series.
\n", + "`futr_exog_list`: str list, future exogenous columns.
\n", + "`hist_exog_list`: str list, historic exogenous columns.
\n", + "`stat_exog_list`: str list, static exogenous columns.
\n", + "`hidden_size`: int, dimension of the model.
\n", + "`n_heads`: int, number of heads.
\n", + "`e_layers`: int, number of encoder layers.
\n", + "`d_layers`: int, number of decoder layers.
\n", + "`d_ff`: int, dimension of fully-connected layer.
\n", + "`factor`: int, attention factor.
\n", + "`dropout`: float, dropout rate.
\n", + "`use_norm`: bool, whether to normalize or not.
\n", + "`loss`: PyTorch module, instantiated train loss class from [losses collection](https://nixtla.github.io/neuralforecast/losses.pytorch.html).
\n", + "`valid_loss`: PyTorch module=`loss`, instantiated valid loss class from [losses collection](https://nixtla.github.io/neuralforecast/losses.pytorch.html).
\n", + "`max_steps`: int=1000, maximum number of training steps.
\n", + "`learning_rate`: float=1e-3, Learning rate between (0, 1).
\n", + "`num_lr_decays`: int=-1, Number of learning rate decays, evenly distributed across max_steps.
\n", + "`early_stop_patience_steps`: int=-1, Number of validation iterations before early stopping.
\n", + "`val_check_steps`: int=100, Number of training steps between every validation loss check.
\n", + "`batch_size`: int=32, number of different series in each batch.
\n", + "`step_size`: int=1, step size between each window of temporal data.
\n", + "`scaler_type`: str='identity', type of scaler for temporal inputs normalization see [temporal scalers](https://nixtla.github.io/neuralforecast/common.scalers.html).
\n", + "`random_seed`: int=1, random_seed for pytorch initializer and numpy generators.
\n", + "`num_workers_loader`: int=os.cpu_count(), workers to be used by `TimeSeriesDataLoader`.
\n", + "`drop_last_loader`: bool=False, if True `TimeSeriesDataLoader` drops last non-full batch.
\n", + "`alias`: str, optional, Custom name of the model.
\n", + "`optimizer`: Subclass of 'torch.optim.Optimizer', optional, user specified optimizer instead of the default choice (Adam).
\n", + "`optimizer_kwargs`: dict, optional, list of parameters used by the user specified `optimizer`.
\n", + "`**trainer_kwargs`: int, keyword trainer arguments inherited from [PyTorch Lighning's trainer](https://pytorch-lightning.readthedocs.io/en/stable/api/pytorch_lightning.trainer.trainer.Trainer.html?highlight=trainer).
\n", + "\n", + "**References**
\n", + "- [Yong Liu, Tengge Hu, Haoran Zhang, Haixu Wu, Shiyu Wang, Lintao Ma, Mingsheng Long. \"iTransformer: Inverted Transformers Are Effective for Time Series Forecasting\"](https://arxiv.org/abs/2310.06625)" + ], + "text/plain": [ + "---\n", + "\n", + "[source](https://github.com/Nixtla/neuralforecast/blob/main/neuralforecast/models/itransformer.py#L94){target=\"_blank\" style=\"float:right; font-size:smaller\"}\n", + "\n", + "### iTransformer\n", + "\n", + "> iTransformer (h, input_size, n_series, futr_exog_list=None,\n", + "> hist_exog_list=None, stat_exog_list=None,\n", + "> hidden_size:int=512, n_heads:int=8, e_layers:int=2,\n", + "> d_layers:int=1, d_ff:int=2048, factor:int=1,\n", + "> dropout:float=0.1, use_norm:bool=True, loss=MAE(),\n", + "> valid_loss=None, max_steps:int=1000,\n", + "> learning_rate:float=0.001, num_lr_decays:int=-1,\n", + "> early_stop_patience_steps:int=-1, val_check_steps:int=100,\n", + "> batch_size:int=32, step_size:int=1,\n", + "> scaler_type:str='identity', random_seed:int=1,\n", + "> num_workers_loader:int=0, drop_last_loader:bool=False,\n", + "> optimizer=None, optimizer_kwargs=None, **trainer_kwargs)\n", + "\n", + "iTransformer\n", + "\n", + "**Parameters:**
\n", + "`h`: int, Forecast horizon.
\n", + "`input_size`: int, autorregresive inputs size, y=[1,2,3,4] input_size=2 -> y_[t-2:t]=[1,2].
\n", + "`n_series`: int, number of time-series.
\n", + "`futr_exog_list`: str list, future exogenous columns.
\n", + "`hist_exog_list`: str list, historic exogenous columns.
\n", + "`stat_exog_list`: str list, static exogenous columns.
\n", + "`hidden_size`: int, dimension of the model.
\n", + "`n_heads`: int, number of heads.
\n", + "`e_layers`: int, number of encoder layers.
\n", + "`d_layers`: int, number of decoder layers.
\n", + "`d_ff`: int, dimension of fully-connected layer.
\n", + "`factor`: int, attention factor.
\n", + "`dropout`: float, dropout rate.
\n", + "`use_norm`: bool, whether to normalize or not.
\n", + "`loss`: PyTorch module, instantiated train loss class from [losses collection](https://nixtla.github.io/neuralforecast/losses.pytorch.html).
\n", + "`valid_loss`: PyTorch module=`loss`, instantiated valid loss class from [losses collection](https://nixtla.github.io/neuralforecast/losses.pytorch.html).
\n", + "`max_steps`: int=1000, maximum number of training steps.
\n", + "`learning_rate`: float=1e-3, Learning rate between (0, 1).
\n", + "`num_lr_decays`: int=-1, Number of learning rate decays, evenly distributed across max_steps.
\n", + "`early_stop_patience_steps`: int=-1, Number of validation iterations before early stopping.
\n", + "`val_check_steps`: int=100, Number of training steps between every validation loss check.
\n", + "`batch_size`: int=32, number of different series in each batch.
\n", + "`step_size`: int=1, step size between each window of temporal data.
\n", + "`scaler_type`: str='identity', type of scaler for temporal inputs normalization see [temporal scalers](https://nixtla.github.io/neuralforecast/common.scalers.html).
\n", + "`random_seed`: int=1, random_seed for pytorch initializer and numpy generators.
\n", + "`num_workers_loader`: int=os.cpu_count(), workers to be used by `TimeSeriesDataLoader`.
\n", + "`drop_last_loader`: bool=False, if True `TimeSeriesDataLoader` drops last non-full batch.
\n", + "`alias`: str, optional, Custom name of the model.
\n", + "`optimizer`: Subclass of 'torch.optim.Optimizer', optional, user specified optimizer instead of the default choice (Adam).
\n", + "`optimizer_kwargs`: dict, optional, list of parameters used by the user specified `optimizer`.
\n", + "`**trainer_kwargs`: int, keyword trainer arguments inherited from [PyTorch Lighning's trainer](https://pytorch-lightning.readthedocs.io/en/stable/api/pytorch_lightning.trainer.trainer.Trainer.html?highlight=trainer).
\n", + "\n", + "**References**
\n", + "- [Yong Liu, Tengge Hu, Haoran Zhang, Haixu Wu, Shiyu Wang, Lintao Ma, Mingsheng Long. \"iTransformer: Inverted Transformers Are Effective for Time Series Forecasting\"](https://arxiv.org/abs/2310.06625)" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "show_doc(iTransformer)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "---\n", + "\n", + "### iTransformer.fit\n", + "\n", + "> iTransformer.fit (dataset, val_size=0, test_size=0, random_seed=None)\n", + "\n", + "Fit.\n", + "\n", + "The `fit` method, optimizes the neural network's weights using the\n", + "initialization parameters (`learning_rate`, `windows_batch_size`, ...)\n", + "and the `loss` function as defined during the initialization.\n", + "Within `fit` we use a PyTorch Lightning `Trainer` that\n", + "inherits the initialization's `self.trainer_kwargs`, to customize\n", + "its inputs, see [PL's trainer arguments](https://pytorch-lightning.readthedocs.io/en/stable/api/pytorch_lightning.trainer.trainer.Trainer.html?highlight=trainer).\n", + "\n", + "The method is designed to be compatible with SKLearn-like classes\n", + "and in particular to be compatible with the StatsForecast library.\n", + "\n", + "By default the `model` is not saving training checkpoints to protect\n", + "disk memory, to get them change `enable_checkpointing=True` in `__init__`.\n", + "\n", + "**Parameters:**
\n", + "`dataset`: NeuralForecast's `TimeSeriesDataset`, see [documentation](https://nixtla.github.io/neuralforecast/tsdataset.html).
\n", + "`val_size`: int, validation size for temporal cross-validation.
\n", + "`test_size`: int, test size for temporal cross-validation.
" + ], + "text/plain": [ + "---\n", + "\n", + "### iTransformer.fit\n", + "\n", + "> iTransformer.fit (dataset, val_size=0, test_size=0, random_seed=None)\n", + "\n", + "Fit.\n", + "\n", + "The `fit` method, optimizes the neural network's weights using the\n", + "initialization parameters (`learning_rate`, `windows_batch_size`, ...)\n", + "and the `loss` function as defined during the initialization.\n", + "Within `fit` we use a PyTorch Lightning `Trainer` that\n", + "inherits the initialization's `self.trainer_kwargs`, to customize\n", + "its inputs, see [PL's trainer arguments](https://pytorch-lightning.readthedocs.io/en/stable/api/pytorch_lightning.trainer.trainer.Trainer.html?highlight=trainer).\n", + "\n", + "The method is designed to be compatible with SKLearn-like classes\n", + "and in particular to be compatible with the StatsForecast library.\n", + "\n", + "By default the `model` is not saving training checkpoints to protect\n", + "disk memory, to get them change `enable_checkpointing=True` in `__init__`.\n", + "\n", + "**Parameters:**
\n", + "`dataset`: NeuralForecast's `TimeSeriesDataset`, see [documentation](https://nixtla.github.io/neuralforecast/tsdataset.html).
\n", + "`val_size`: int, validation size for temporal cross-validation.
\n", + "`test_size`: int, test size for temporal cross-validation.
" + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "show_doc(iTransformer.fit, name='iTransformer.fit')" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "text/markdown": [ + "---\n", + "\n", + "### iTransformer.predict\n", + "\n", + "> iTransformer.predict (dataset, test_size=None, step_size=1,\n", + "> random_seed=None, **data_module_kwargs)\n", + "\n", + "Predict.\n", + "\n", + "Neural network prediction with PL's `Trainer` execution of `predict_step`.\n", + "\n", + "**Parameters:**
\n", + "`dataset`: NeuralForecast's `TimeSeriesDataset`, see [documentation](https://nixtla.github.io/neuralforecast/tsdataset.html).
\n", + "`test_size`: int=None, test size for temporal cross-validation.
\n", + "`step_size`: int=1, Step size between each window.
\n", + "`**data_module_kwargs`: PL's TimeSeriesDataModule args, see [documentation](https://pytorch-lightning.readthedocs.io/en/1.6.1/extensions/datamodules.html#using-a-datamodule)." + ], + "text/plain": [ + "---\n", + "\n", + "### iTransformer.predict\n", + "\n", + "> iTransformer.predict (dataset, test_size=None, step_size=1,\n", + "> random_seed=None, **data_module_kwargs)\n", + "\n", + "Predict.\n", + "\n", + "Neural network prediction with PL's `Trainer` execution of `predict_step`.\n", + "\n", + "**Parameters:**
\n", + "`dataset`: NeuralForecast's `TimeSeriesDataset`, see [documentation](https://nixtla.github.io/neuralforecast/tsdataset.html).
\n", + "`test_size`: int=None, test size for temporal cross-validation.
\n", + "`step_size`: int=1, Step size between each window.
\n", + "`**data_module_kwargs`: PL's TimeSeriesDataModule args, see [documentation](https://pytorch-lightning.readthedocs.io/en/1.6.1/extensions/datamodules.html#using-a-datamodule)." + ] + }, + "execution_count": null, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "show_doc(iTransformer.predict, name='iTransformer.predict')" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 3. Usage example" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import pytorch_lightning as pl\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from neuralforecast import NeuralForecast\n", + "from neuralforecast.utils import AirPassengersPanel, AirPassengersStatic\n", + "from neuralforecast.losses.pytorch import MSE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/marcopeix/miniconda3/envs/neuralforecast/lib/python3.10/site-packages/pytorch_lightning/utilities/parsing.py:198: Attribute 'loss' is an instance of `nn.Module` and is already saved during checkpointing. It is recommended to ignore them using `self.save_hyperparameters(ignore=['loss'])`.\n", + "/Users/marcopeix/miniconda3/envs/neuralforecast/lib/python3.10/site-packages/pytorch_lightning/utilities/parsing.py:198: Attribute 'valid_loss' is an instance of `nn.Module` and is already saved during checkpointing. It is recommended to ignore them using `self.save_hyperparameters(ignore=['valid_loss'])`.\n", + "Seed set to 1\n", + "GPU available: True (mps), used: True\n", + "TPU available: False, using: 0 TPU cores\n", + "IPU available: False, using: 0 IPUs\n", + "HPU available: False, using: 0 HPUs\n", + "\n", + " | Name | Type | Params\n", + "---------------------------------------------------------\n", + "0 | padder | ConstantPad1d | 0 \n", + "1 | loss | MSE | 0 \n", + "2 | valid_loss | MAE | 0 \n", + "3 | scaler | TemporalNorm | 0 \n", + "4 | enc_embedding | DataEmbedding_inverted | 3.2 K \n", + "5 | encoder | TransEncoder | 135 K \n", + "6 | projector | Linear | 1.5 K \n", + "---------------------------------------------------------\n", + "140 K Trainable params\n", + "0 Non-trainable params\n", + "140 K Total params\n", + "0.562 Total estimated model params size (MB)\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "db2340a0a0ea4ab79a8f3c3fbc5e8962", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Sanity Checking: | | 0/? [00:00]. Skipping setting a default `ModelSummary` callback.\n", + "GPU available: True (mps), used: True\n", + "TPU available: False, using: 0 TPU cores\n", + "IPU available: False, using: 0 IPUs\n", + "HPU available: False, using: 0 HPUs\n", + "/Users/marcopeix/miniconda3/envs/neuralforecast/lib/python3.10/site-packages/pytorch_lightning/trainer/connectors/data_connector.py:441: The 'predict_dataloader' does not have many workers which may be a bottleneck. Consider increasing the value of the `num_workers` argument` to `num_workers=10` in the `DataLoader` to improve performance.\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "b61339b3642d44bfb953a7b2becf4cc4", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Predicting: | | 0/? [00:00=AirPassengersPanel['ds'].values[-12]].reset_index(drop=True) # 12 test\n", + "\n", + "model = iTransformer(h=12,\n", + " input_size=24,\n", + " n_series=2,\n", + " hidden_size=128,\n", + " n_heads=2,\n", + " e_layers=2,\n", + " d_layers=1,\n", + " d_ff=4,\n", + " factor=1,\n", + " dropout=0.1,\n", + " use_norm=True,\n", + " loss=MSE(),\n", + " valid_loss=MAE(),\n", + " early_stop_patience_steps=3,\n", + " batch_size=32)\n", + "\n", + "fcst = NeuralForecast(models=[model], freq='M')\n", + "fcst.fit(df=Y_train_df, static_df=AirPassengersStatic, val_size=12)\n", + "forecasts = fcst.predict(futr_df=Y_test_df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAABmcAAAKHCAYAAAB0L5wRAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjguMywgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/H5lhTAAAACXBIWXMAAA9hAAAPYQGoP6dpAAEAAElEQVR4nOzdd3hUZfrG8e+kk5CEnkLvvfcivVgQsSBWUNwVxZXFXrDg4mJZQazrDwXBXlBEERFEQOrSeycJkEYIBNL7+f0xnjEhnZnMJOH+XFcuJ3POec8z5USde573tRiGYSAiIiIiIiIiIiIiIiJO4ebqAkRERERERERERERERK4kCmdEREREREREREREREScSOGMiIiIiIiIiIiIiIiIEymcERERERERERERERERcSKFMyIiIiIiIiIiIiIiIk6kcEZERERERERERERERMSJFM6IiIiIiIiIiIiIiIg4kcIZERERERERERERERERJ1I4IyIiIiIiIiIiIiIi4kQKZ0RERESkylu7di0WiwWLxcKMGTNcXY6IiIiIiIhc4RTOiIiIiEilMGfOHFvAYrFY+Oqrr1xdUr56Lv2pXr06jRo1YvTo0bz33nskJia6ulyREkVERBT7vi7sZ+zYsa4uW0owY8YMZsyYwcKFC11dioiIiIj8SeGMiIiIiFQKCxYsyPf7/PnzXVRJ6aSkpHD69Gl+/vln/vGPf9CqVSt+/fVXV5clIlegl156iZdeeknhjIiIiEgF4uHqAkRERERESrJlyxYOHDiQ777Vq1cTERFBkyZNSjx+8ODBGIZRTtVZLVmyJN/vSUlJ7N69m08++YT4+HjOnDnDDTfcwLp16+jdu3e51iLiCHXr1mXevHkl7hcSEuKEakREREREqhaLUd7/lyoiIiIiYqe///3vfPTRRwDce++9fPzxxwC88MILvPTSSy6ry2Kx2G4X9Z/V586d45prrmHbtm0A9OnTh82bNzulPpGyioiIoGnTpgA0btyYiIgI1xYkDmH+rRo0aBBr1651bTEiIiIiAmhaMxERERGp4FJSUvj6668BaNq0KW+99RbVq1cH4OOPPyY3N9eV5ZWodu3aLFq0yPb7li1bOHXqlAsrEhEREREREVdTOCMiIiIiFdo333xDUlISAHfffTf+/v7cfPPNAJw+fZpVq1aVOMbatWtti5fPmDGj0H2aNGmCxWKxTZOWkZHBe++9x+DBgwkJCcHd3b1UU6gVpm3btrRs2dL2+759+2y309PTWbp0KVOnTqVfv37UrVsXT09P/P39admyJXfffXepHiNAYmIis2fPZsiQIQQFBeHl5UVAQADNmzenX79+PProo6xYsYLMzMxCj4+NjeWll16if//+1KlTB09PT2rUqEGrVq0YOHAg06dPZ+3atSUGYrt37+af//wnnTt3platWnh7exMaGsp1113HggULyM7OLvZ487UaPHiw7Tl6++236du3L7Vr16ZatWo0b96cyZMnExYWVqrnJiUlhVmzZtG9e3cCAwPx9/enQ4cOTJ8+nZiYGADuuece27lL6hi5ePEis2fPZvjw4YSGhuLt7U2tWrXo3r07zzzzDFFRUcUeX9i5fvjhB2666SYaN26Mt7d3oXWsX7+eSZMm0bZtW/z9/fHy8iI4OJiOHTty44038t577xEeHl6q56S8ZWRk8N///perr74633PUtWtXnnzyyRLrLOy6PXbsGI899hjt27enRo0aRV7T6enp/N///R+jR4+mYcOG+Pj4EBgYSIcOHZg6dSpHjx4t9eOIj4/n1VdfZdiwYbbH4evrS8uWLRk3bhzz588nMTGx0GOPHj3KnDlzuPHGG2nZsiXVq1fHy8uLevXqMXDgQF5++WXi4+NLVcflvPbm82dat26d7b68P1qLRkRERMQFDBERERGRCqx///4GYADG8ePHDcMwjN9//91237hx40ocY82aNbb9X3zxxUL3ady4sQEYjRs3NsLDw40OHTrYjjF/GjdunO+YvNtK0q9fP9u+n3/+ue3+pk2bFjhPYT833HCDkZSUVOT427dvN4KDg0s11rZt2wocv3z5csPf379Ux589e7bQGtLT041JkyYZFoul2OPbt29vnDhxosjHYu43aNAgIywszOjYsWORY/n5+Rm//fZbsc/9oUOHbK9vYT9169Y1/vjjD2PixIm2+8LDw4sc75tvvjFq1apV7GP08fExFi5cWOQYec915MgR4+abby50HLOOnJwcY/LkyaV6fa677rpin4/ihIeHF/l+L4sdO3YU+5wDhpeXl/Gf//ynyDEuvW4//fRTo1q1agXGufSaXrt2rVG/fv1iz+3u7m7MmjWrxMfxzjvvGH5+fiU+5/fcc0+BYxctWlSq1ysgIMBYtmxZkTXY89qX5hjA+Pjjj0t8LkRERETEsTwQEREREamgjhw5wsaNGwEYMGAAzZs3B2Dw4ME0adKEiIgIli5dSnx8PHXq1HHIOTMyMrjpppvYv38/ffr04ZZbbqFhw4ZcuHAhX8dLWcXFxdlu16hRw3Y7NTWVGjVqMHToULp27Urjxo3x9fUlMTGRvXv38vXXXxMTE8PSpUuZNGkS33zzTYGxU1NTGTt2LLGxsQB0796dG2+8kfr16+Pn50dCQgKHDh1izZo17Nmzp8Dx0dHR3HrrrSQnJwPWdSmuu+46goOD8fb2Jj4+nv3797N69eoiOw6ys7O5+uqrbetZBAUFcdttt9GlSxf8/PyIiopiyZIl/PHHHxw4cICBAweya9cu6tatW+RzlpiYyHXXXcehQ4cYOXIko0ePJjg4mNjYWD755BO2b99OSkoKt99+O4cPH6ZWrVoFxjh79ixDhw61dcc0atSISZMm0bp1a5KTk1m5ciWLFy/mpptuonPnzkXWYvrwww+ZPHkyhmHg4eHB6NGjGTp0KMHBwaSkpLBx40Y+//xz0tLSuOeee/Dy8uL2228vdsxp06bxyy+/0LhxYyZMmECbNm3IzMxk69ateHt7A/Duu+/yf//3fwD4+/tzyy230L17d+rWrUtmZiaRkZFs376d3377rcTHUN7279/PoEGDbO+n1q1bc/fdd9OiRQsuXrzI8uXLWbp0KZmZmTzxxBNkZGQwffr0YsfctGkT//73v7FYLEycOJGrrrqK6tWrExYWRoMGDWz7/fLLL9xwww1kZWVhsVgYPnw4o0aNokGDBmRmZrJ9+3Y++eQTLly4wLPPPgvAM888U+g5n376aV577TXb7wMGDGD06NE0btyY3NxcTp06xcaNG1m1alWha06lpqZisVjo3LkzAwcOpE2bNrb3aGRkJL/99hsrVqwgMTGRm2++mU2bNtGtW7cC49jz2i9ZsgSAG2+8EYD27dvz8ssvF9ivsPOKiIiISDlzdTokIiIiIlKUJ554wvbN7g8//DDftueff9627c033yx2nLJ0zpg/r776aon15d2/OAcPHsy376lTp2zbli9fbmRmZhZ5bEpKinHjjTfajl2/fn2Bfb799lvb9scee6zYWg4cOGDExcXlu+8///mP7fh33nmn2OP/97//GWlpaQXuf/rpp21j3H777UZycnKhx7/77ru2/e68885C98n7XHl4eBjffPNNgX2ys7ON66+/3rbfG2+8UehYEyZMsO0zdOjQQutatmyZ4eXlVWjHSl579uwxvL29DcBo2LChsXv37kLPefjwYaNBgwYGYPj7+xvnzp0rsE/ezhnAGDt2bKHPq6l9+/YGYNSqVcs4efJkkfulp6cbW7ZsKXJ7SeztnMnNzTU6depkG2PixImFvr+///57w9PT09bFsn379gL75L1uAaNevXrGnj17ijx3dHS0raMpMDDQWL16dZH7mTW6u7sbhw4dKrDPDz/8YDuvn5+f8f333xd53nPnzhlr1qwpcP/+/fuNY8eOFXmcYRjGb7/9Zvj6+hqAMWzYsEL3ccRrbz6WQYMGFVuPiIiIiDiPwhkRERERqZCysrKMoKAgA6xTRF24cCHf9uPHj9s+cOzQoUOxY5U1nLnhhhtKVWNpwpnz588bvXv3tu3Xp0+fUo2d18WLF21TK/3tb38rsP2VV16xjX/gwIEyj593yqSUlJQyH3/mzBnDx8fHAIwePXoY2dnZxe5/55132j4Yj4yMLLA97/P6/PPPFznOkSNHbPsV9sF2bGysLQAIDAw0zpw5U+RYzz33XInhjBmSubu7Gzt37iz2Ma5atarYoC9vOFO/fv1ip6wzDMMWCpVmGj975A1nSvNz6Yf9y5Yty3ddZmVlFXmul156ybbvrbfeWmD7peHMkiVLiq39kUcese27dOnSYvc9fPiw4e7ubgDGAw88kG9bbm6uLRABjK+++qrYseyVN2gu7HpwxGuvcEZERESk4nFDRERERKQC+umnnzhz5gwAY8eOJTAwMN/25s2bM2DAAMA6jdLWrVsddu6pU6eW+Zgffvgh389nn33GE088QZs2bfjf//4HgJeXF3PmzCnz2AEBAXTs2BGALVu2FNju5+dnu71jx44yj2/v8V9//TXp6ekAPP7447i7uxe7/4QJEwDIyclh9erVRe7n5ubGP//5zyK3t2rVioYNGwJw4MCBAtt//vlnsrKyALjzzjupV69ekWM9/PDDeHgUPevzhQsXWLp0KQAjRoyga9euRe4LMHz4cEJDQwH49ddfi9130qRJVK9evdh9zNdo3759ZGZmFruvK3333Xe2248//nixz+m0adPw9fUFrNe7+VoVplGjRtxwww1FbjcMg08//RSwTqM2ZsyYYuts3bo1vXr1Agq+Pjt37rS9n7p27cr48eOLHcte/fv3t90u7vqu6K+9iIiIiJSN1pwRERERkQpp/vz5ttsTJ04sdJ977rmHDRs2ALBgwQLbh632cHd3p1+/fmU+zlzToSh169Zl4cKF9O3bt8C2hIQEPv/8c1asWMH+/fs5d+4cKSkpha5jERkZWeC+4cOHY7FYMAyDBx98kGPHjnHbbbfRrl27UtU+cuRIW2h000038dRTT3HzzTfTtGnTUh3/xx9/5HssP/zwQ7H7R0VF2W4fPHiwyP1at25N7dq1ix2rfv36nD59moSEhALbtm3bZrs9ZMiQYsepV68e7dq1Y+/evYVu37hxI7m5uYB13Y+SHiNgC1yKe4wAV111VYljjRw5kq+++orDhw8zbNgwHnnkEUaOHFliqGOPunXrMm/evGL3uXStp7zhwqhRo4o9NiAggH79+vHbb7+RlpbGnj176NGjR6H7DhgwAIvFUuRYBw8eJD4+HoDg4OBSvT5miBgeHk56ejo+Pj4ArF+/3rbP2LFjSxynJBs2bODLL79k69athIWFkZSUVGQQVdj17YrXXkRERETKn8IZEREREalwoqOjWbFiBQAhISGMGDGi0P1uvfVWpk6dSmpqKl9++SVz5syxfRP/ctWuXdv2Ia09qlWrRu3atenYsSPXXHMNd999NzVq1Ciw39KlS7nvvvs4d+5cqcZNTEwscF/btm157rnnmDlzJikpKcycOZOZM2dSr149BgwYwMCBA7n66qtp3bp1oWOOGjWKCRMm8MknnxAfH88TTzzBE088QaNGjejfvz+DBg3i2muvtXWpXCoiIsJ2+8EHHyzV4zCdP3++yG2XfvBfGG9vbwAyMjIKbIuOjrbdbt68eYljNW/evMhwJu9j/Pbbb/n2229LHM9U3GME8i1oX5TXXnuNDRs2EBkZyYYNG9iwYQMeHh506dKFq666isGDBzNy5EiHvHdNvr6+ZQ4nYmJiAGuAFRwcXOL+rVu3ti1kn/f1ulRJz1He12fdunWsW7euFNX+5fz587ZOp9OnT9vuL23AWZjk5GTuvvvuUgVFpsKub1e89iIiIiJS/hTOiIiIiEiFs3DhQnJycgDrdFRFTZPl7+/PjTfeyOeff05iYiKLFy+2TZl1uapVq3ZZxxXW5VKSzZs3c8stt5CdnQ1Ap06dGD58OC1atKBmzZp4e3vbugWee+45Dhw4YOveuNS//vUvevXqxauvvsrGjRsBiIuL4/vvv+f7778HrNMnzZ49m969exc4ftGiRQwbNow333yT3bt3A3Dq1ClOnTrFl19+icVi4ZprrmHOnDkFQp4LFy6U+bGbipumyc3NvlmYU1JSbLdLE9oVt489j7G46bqgdO+5Ro0asWvXLmbNmsUnn3zCuXPnyM7OZvv27Wzfvp0333yTgIAA/vnPfzJ9+nRbaOVsSUlJQP6p8oqTt/vDPLYwJT1H9rw+kP99mDcgsac7Zfz48SxfvhywPh/XXXcdXbt2JTQ0FF9fX9uUb/v37+f5558HsP3dy6uyvPYiIiIiUjYKZ0RERESkQjEMgwULFth+f+ONN3jjjTdKdez8+fPtDmec6YUXXrAFM++99x5Tpkwpct9///vfJY43evRoRo8ezZkzZ1i/fj2bN29m3bp17Ny5E8Mw2LhxI1dddRXLly9n+PDhBY6fMGECEyZM4NSpU7bj16xZw8GDBzEMg+XLl7N+/Xo2btxoWwMH8n+AnZCQUGiHkCvkDQhSU1NL3D9vmHOpvI9x7ty5xa6FU17q1KnDnDlz+M9//sOOHTvYtGkTGzdu5Pfff+f8+fMkJiYyc+ZMNm7cyKpVq+wOty6Hv78/Fy5cKPa5zCs5OTnfsZcr7+szbdo03nzzzcseKyAgwHY7b31lsXHjRlsw07FjR1auXFlkJ5Gnp2eJ41WG115EREREykb/xSYiIiIiFcq6des4ceLEZR37xx9/cOzYMQdXVD6ysrJYu3YtAN27dy82mIH80zaVJCgoiFtuuYXZs2ezfft2IiIiuOWWW2znfeSRR4o9vlGjRtx55528++67HDhwgAMHDjBo0CDA2t3w7LPP5ts/75RT5kLqFYE5TRVQqvdUWFhYkdvyPsb9+/fbV5id3N3d6dWrF9OmTePbb7/lzJkzfPPNNwQGBgLw+++/s2TJEpfUFhISAljfJ7GxsSXuf/ToUdvtvK9XWTny9ck7VknrBRVl5cqVttuzZs0qdoq38PDwUo9bkV97ERERESkbdc6IiIiISIUyf/582+0bb7yRTp06lXjM1q1b+eWXXwBYsGABr7zySrnV5yjx8fG2rpkWLVoUu+/WrVtti51fjkaNGvHFF1+wbt06zp49y/79+7lw4UKpO1zatWvH999/T926dcnNzc23YDrA4MGDWbZsGQDff/89/fv3v+xaHalnz5588MEHAKxZs8YWUBUmLi6u2GBp0KBBWCwWDMNg2bJlZGZm4uXl5fCaL4eHhwfjxo0jKirKFrytX7+em2++2em19OnTh0OHDgHw66+/MnHixCL3TUpKYtOmTYB12rLOnTtf9nm7dOlCjRo1uHDhAuvXryc+Pr5UaxYVZuDAgbbbP/zwAy+88EKZx8gbTJV0fZsdNpejtK+9+d69nOkXRURERKR8qHNGRERERCqMixcv8t133wHWb4i///77zJgxo8SfuXPn2sZYtGhRoes2VDR5p9w6fvx4sfu++OKLdp/P09OT+vXr2343g6HSqlWrlm26p0vXULntttts61x88MEHJT4eZ7nuuutsU0Z9/vnnnD17tsh933nnnWLfN3Xq1OG6664DrB+8z54927HFOkDTpk1tt8v6+jpK3gBs9uzZxdbx1ltv2aY/GzNmTKmm9yqKu7s7d911FwAZGRlMnz79ssfq1q0b7du3B2DXrl18/fXXZR6jtNf3pk2bWLFiRdmLvERJr7057Vtpp5sTERERkfKncEZEREREKowvvviCtLQ0AEaOHFnsVEB5tWrVij59+gAQExNj1zfRnSUgIIBWrVoBsGPHDhYvXlxgn5ycHB555JESP7x9++23+fbbb/Mtan6p9evXs3fvXsA6bVPeroKXXnqJX3/9ldzc3CKP/+KLL2yLrnft2jXftvr169u+tZ+amsqoUaPYtWtXsTXv37+fBx54oNh97BUUFMTtt98OWIO/2267rdAPp3/++Wdef/31Esd7+eWXbSHUc889x1tvvVVsJ8LFixeZO3cuv/3222U+AquYmBgee+yxYqdmy8rKYt68ebbfu3TpYtc5L9c111xj64DZt28f999/f4EwD+DHH39k5syZgDVYefLJJ+0+97PPPkutWrUAmDdvHk899VSh5zalpaXx8ccf89VXX+W732Kx8PLLL9t+v++++/jhhx+KHCchIcE2RaGpZ8+ettsvvfQS6enpBY7bu3cv48aNK/Y95KjX3gxvDh8+bPsbKyIiIiKupWnNRERERKTCyDul2YQJE8p07IQJE9iyZYttnOuvv96htZWHadOm2daaufXWWxk/fjyDBg2iZs2aHD9+nM8//5xDhw7RoUMHvL292bFjR6Hj7Ny5k0WLFhEYGMioUaPo1q0bDRo0wMPDg7i4ONasWcOyZcts4cula8asWbOGGTNmUK9ePUaNGkWXLl0ICQnBYrEQExPDL7/8ki9guPR4sAYXe/bs4ZdffiEsLIwePXpw9dVXM3ToUOrXr4/FYuHcuXPs37+ftWvXcujQIdzd3W3TjpWXN954g1WrVhETE8Pvv/9Ou3btmDRpEm3atCE5OZmVK1fy7bffUqtWLbp06cLq1asBCl1QvXPnznz00UdMnDiR3Nxcpk2bxvvvv8+NN95I27Zt8fPzIykpiRMnTrB161bWrVtHZmYmn376qV2PISMjgzlz5jBnzhy6d+/OVVddRbt27ahRowbJycmcOHGCL7/80rZmTrNmzbjtttvsOuflslgsfP755/Tp04fk5GQ+/vhjNm/ezIQJE2jWrBmJiYn88ssv+dZFeemll+jWrZvd5w4JCeHbb7/luuuuIz09nddff53PP/+ccePG0alTJ/z9/UlJSeHkyZNs376d1atXk5qaaguJ8ho7diyPPfYYs2fPJiUlhRtvvJEBAwYwevRoGjdujGEYnD59ms2bN7NixQrGjx/P4MGDbcffdNNNNGrUiFOnTrF9+3Zat27N3/72N1q0aEFqairr1q3jq6++Iisri4kTJ7Jo0aJCH5OjXvvhw4ezd+9eUlJSuP7665kwYQJ169bFYrEA0LFjx3yddSIiIiLiBIaIiIiISAWwe/duAzAAIzAw0EhLSyvT8efPnze8vb0NwPDw8DBiY2Nt29asWWMb+8UXXyz0+MaNGxuA0bhx41Kf0xzzcv+zOjc315g0aVK+cS796dixoxEWFmYMGjSoyHPde++9xY5h/nh6ehovv/xygeOHDBlSquP9/PyMBQsWFPl4srKyjCeeeMLw9PQs1XhFPdfm9kGDBpX4HBb3vJgOHjxoNGrUqMg6ateubaxdu9a48847bfedP3++yPFWrlxpNGjQoFSP0dvb2/jll18KjDFx4kTbPuHh4cU+xoiIiFKdCzA6dOhgHD9+vMTnrSjh4eElvj6lsX37dts1VdSPl5eX8dprrxU5Rmmu28Ls3LnTaNOmTameL3d3d+PDDz8scqw33njD8PHxKXGce++9t9DnoE6dOsWe+9VXXy32cTrqtY+KijKCgoKKPPbjjz8u9fMrIiIiIo6hzhkRERERqRDyds2MGzcOHx+fMh1fs2ZNrr/+ehYvXkx2djaLFi1yyFRJ5clisTB//nyuu+465s2bx/bt20lMTKR27dq0bt2acePGcd9995X4XHzwwQfcc889rFmzhg0bNnDkyBHOnj1LdnY2AQEBtGzZksGDB3PffffRsmXLAscvW7aMDRs2sGbNGjZt2sTx48eJj4/HMAxq1KhBmzZtGD58OH/7298IDQ0tsg4PDw9ef/11/vGPf7BgwQJ+//13jh07xvnz53Fzc6N27dq0atWK3r17M2rUqHwLr5entm3bcvDgQd566y0WL17M8ePHMQyDhg0bcv311zN16lTq16/Pq6++ansc5vo6hRkxYoStY+Hnn39m+/btnD17lvT0dPz9/WnSpAmdO3dm6NChXH/99dSoUcOu+hs3bsypU6dYs2YNa9asYefOnZw6dYqkpCS8vLwIDg6ma9eu3Hzzzdx66614eLj+f/O6d+/OkSNHmD9/PkuXLmXv3r2cO3cOPz8/GjduzIgRI5gyZUq+tVIcpWvXrhw4cIAlS5awdOlStmzZwpkzZ0hJSaF69eo0bNiQjh07MmTIEK6//vpip0987LHHuOOOO5g3bx4rV67k2LFjJCQk4OXlRf369enWrRvXXHNNvrV28j4He/fuZfbs2SxbtoyTJ0/i4eFBaGgoQ4YM4f7776dbt24FpkTLy1GvfWhoKDt37mT27Nn89ttvhIeHk5ycXOyUaiIiIiJSviyG/mtMRERERESucLm5uQQHB3P27Fk6d+7M7t27XV2SiIiIiIhUYQUnUhYREREREbnCfP3115w9exaAIUOGuLgaERERERGp6hTOiIiIiIhIlbZlyxbS09OL3L5hwwYeeughANzc3Lj//vudVZqIiIiIiFyhXD8ZsYiIiIiISDl69dVX+eOPP7jmmmvo0aOHbd2cqKgofvvtN1asWGFbe+PJJ5+kbdu2rixXRERERESuAFpzRkREREREqrSxY8eydOnSYvexWCw89thjvPbaa7i5aYIBEREREREpXwpnRERERESkSjt+/Dg//vgjq1at4sSJE5w7d47ExET8/f1p1KgRgwYN4v7776d9+/auLlVERERERK4QCmdEREREREREREREREScSGvO2CE3N5fo6Gj8/f2xWCyuLkdERERERERERERERFzIMAySkpIIDQ0tdspkhTN2iI6OpmHDhq4uQ0REREREREREREREKpDTp0/ToEGDIrcrnLGDv78/YH2SAwICXFyNyOXLyspi5cqVjBw5Ek9PT1eXIyLF0PUqUrnomhWpPHS9ilQuumZFKg9dr3KlSUxMpGHDhrb8oCgKZ+xgTmUWEBCgcEYqtaysLHx9fQkICNC/JEUqOF2vIpWLrlmRykPXq0jlomtWpPLQ9SpXqpKWQil6wjMRERERERERERERERFxOIUzIiIiIiIiIiIiIiIiTqRwRkRERERERERERERExIkUzoiIiIiIiIiIiIiIiDiRwhkREREREREREREREREnUjgjIiIiIiIiIiIiIiLiRB6uLuBKlJWVRU5OjqvLkCuIu7s7np6eri5DRERERERERERERFA441SJiYnEx8eTkZHh6lLkCuTt7U2dOnUICAhwdSkiIiIiIiIiIiIiVzSFM06SmJhIVFQU1atXp06dOnh6emKxWFxdllwBDMMgKyuLixcvEhUVBaCARkRERERERERERMSFFM44SXx8PNWrV6dBgwYKZcTpqlWrhr+/P5GRkcTHxyucEREREREREREREXEhN1cXcCXIysoiIyODwMBABTPiMhaLhcDAQDIyMsjKynJ1OSIiIiIiIiIiIiJXLIUzTpCTkwOgBdnF5cz3oPmeFBERERERERERERHnUzjjROqaEVfTe1BERERERERERETE9RTOiIiIiIiIiIiIiIiIOJHCGRERERERERERERERESdSOCMiIiIiIiIiIiIiIuJECmfE6SwWS5l+mjRp4uqSRUREREREREREREQcxsPVBciVZ+LEiQXu27BhAydOnKBz58506dIl37Y6deo4qTIRERERERERERERkfKncEacbuHChQXuu+eeezhx4gRjx45lxowZTq9JRERERERERERERMRZNK2ZiIiIiIiIiIiIiIiIEymckQpt7dq1WCwW7rnnHmJjY/nb3/5GgwYN8PDwYO7cuQAMHjwYi8VCREREgeMjIiKwWCwMHjy40PF/+uknRo0aRe3atfHx8aFVq1Y8//zzJCcnl9+DEhERERERERERkStSbm4uf//733n++ecxDMPV5YgLaVozqRTOnj1Lz549yc7OZsCAAaSnp+Pr62vXmI899hhz5szBx8eHXr16UadOHXbs2MHLL7/ML7/8wrp16/Dz83PQIxAREREREREREZEr3YEDB/joo48A6NChA+PHjy90v3374OGHoWlT+PhjZ1YozqJwpgIwDIPU1FRXl1Fqvr6+WCwWp55z+fLl3HjjjXzxxRf4+PjYPd4333zDnDlz6Nq1K99//z1NmjQBICsri3/84x/MmzePGTNm8J///Mfuc4mIiIiIiIiIiIgA+Wb/eeihhxgyZAj16tWz3ZeTA3PmwHPPQWYmrFsH770Hdn5PXSoghTMVQGpqKtWrV3d1GaWWnJzs9I4Sb29v3nnnHYcEMwCzZs0C4Msvv7QFMwCenp689dZb/Pjjj3z00Ue89tpruLlp9j8RERERERERERGx38mTJ223z507x0MPPcS3334LQHg4TJwI69fnPyYyElq1cmaV4gz61FkqhW7dulG/fn2HjBUXF8eePXto27YtrVu3LrDdx8eHHj16cOHCBY4dO+aQc4qIiIiIiIiIiIiY4czQoUPx8PBg8eLFfPPNt8yfD506WYOZ6tVh/nxo1856zKlTLixYyo06ZyoAX1/fSrUAvb1rvVyORo0aOWws8w/goUOHSpyeLT4+vtAAR0RERERERERERKSszM8mr7/+evr378/Mmf/H3Xf7k5lp3X7VVbBokXWtmW++gYMH4fRpFxYs5UbhTAVgsVi08HwJLnc6s9zc3AL35eTkABASEsLIkSOLPb527dqXdV4RERERERERERGRS5lrzjRu3JjQ0Idwd59GZmYt3NyyeO01Tx55BNzdrfs2bGj9p8KZqknhjFR6Xl5eAIV2H50u5C9XgwYNAAgODmbhwoXlWpuIiIiIiIiIiIiIydo5E8CCBQNZtswTqAXsJjf3bpo2nYG7+822fRXOVG1ac0YqvZCQEACOHj1aYNvKlSsL3NegQQNat27N3r17CQ8PL/f6RERERERERERERNLS0oiLuwBsZtmy2ri5wTPPwFNPLQH2M2XKFOLj4237K5yp2hTOSKU3aNAgAGbPnk1qaqrt/t9++425c+cWesxzzz1HTk4ON998M/v37y+w/cSJEyxYsKBc6hUREREREREREZErz6lTp4DOQDsCAgz++ANmzYKXXnqW9u3bExcXx9SpU237K5yp2hTOSKV3++2307p1azZt2kTbtm255ZZb6N27N6NGjWLKlCmFHnPXXXfx5JNPsmvXLrp06ULPnj259dZbufrqq2nbti0tWrTg7bffdvIjERERERERERERkarKOqVZKwC6dbPQv7/1fm9vbz7+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5euvv+bWW2+1jZebm8vy5cvznfv+++/nzTffJCQkJN9+L7/8Mi+++CLPPfccCxYssG17++23SUtL47vvvuOmm27KN9ahQ4ds9f/tb3+jRYsW/PrrrwwYMEBr9oiIiIiIiIiIiFRQhmFw/nwdANq39yrz8eaXu93do4Dm6pypQjStWQVgGJCSUnl+DMOxjz/vtFx5fy5cuADA2rVr2bdvH02bNmXmzJm2EAXglltuYezYsSQlJfHxxx8XOv7bb7+dL5gB+Omnn9i/fz+33347U6dOzTdm165def7550lJSeGzzz6z3f/mm2+Snp7O5MmT8wUzAG5ubowePTrffUOHDs0XzJj7vfDCC9SvX5+lS5fm2xYXF2c77lJt27YtMJaIiIiIiIiIiIhUbPHx8eTkNAOgR4+AMh9vds5kZ0cAcOqUw0oTF1PnTAWQmgrVq7u6itJLTgY/P8eNN3HixELv9/KyJsnr168HYPz48bi7uxfY7+677+b7779n/fr1PP300/m2hYSE0KNHjwLHrFq1CoCxY8cWem5zqrC869n89ttvAEyePLm4h5PPuXPn+PHHH9m/fz8XLlwgJycHgKysLM6fP8/58+epVasWAN27d+eXX35hwoQJPPfcc/To0QM3N+WnIiIiIiIiIiIildXJkyeBlgC0b+9Z5uPNcCY9/QigNWeqEoUz4nIlTcsVHR0NQJMmTQrdbt5v7pdXo0aNCj0mIiICsAY+48ePL/Lc8fHxttun//zL16xZs2LrNX355Zfcf//9JCcnF7lPUlKSLZx54okn2LBhAz/99BM//fQTgYGB9O7dm9GjR3PPPffg7+9fqvOKiIiIiIiIiIhIxXDwYBRg/fJ4y5ZlP94MZxITDwIKZ6oShTMVgK+vtRulsvD1dc158049VtrtPj4+he5rdrBcc801tjVlCtOmTZsC5yipDrAm4vfccw+GYTB37lyuu+466tevT7Vq1QDo168fmzdvxsgzR1xAQAC///47Gzdu5KeffmLt2rWsXr2alStX8sorr7B+/XqaN29e4rlFRERERERERESkYti1y/rBr49PAgEBNct8fL169XB3dycn5ySgcKYqUThTAVgsjp0mrKoxF70KDw8vdLu1NZAyrcnSoEEDAB544AHGjBlTqmMaNmzIsWPHOHHiBB06dCh23+XLl5OZmcljjz3GP//5zwLb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D8cwDFeXIn/auzcDgBo14nBzc9xH8GY44+UVCyicqewUzoiIiIiIiIiIiIhUQllZWdxyyy00a9aML774wtXlyJ+OH7d+7B4amuzQcc1wxjCsqYzCmcpN4YyIiIiIiIiIiIhIJZOTk8OECRP4/vvvAdi6dauLKxJTVJQfAM2b5zh03NDQUAAyM08AcOqUQ4cXJ1M4IyIiIiIiIiIiIlKJ5Obmct999/HVV1/Z7ouKinJhRWJKSoLkZH8A2rf3cujYZudMUtJBQJ0zlZ3CGREREREREREREZFKwjAMHnroIRYtWoS7uzsTJ04EFM5UFMeOmbfO0KZNsEPHNsOZ8+f3ABAZCVpqqPJSOCMiIiIiIiIiIiJSCRiGwaOPPsoHH3yAxWLh008/5cEHHwQgMjLSxdUJ5A1njtGkSROHjv1X58whLBaDjAw4e9ahpxAnUjgjIiIiIiIiIiIiUsEZhsH06dOZO3cuAPPnz+f222+nQYMGAMTExJCT49g1TqTsjhzJ/fPWURo3buzQsQMCAvDz8wOyqFvX+lprarPKS+GMiIiIiIiIiIiISAX38ssv88orrwDw3nvvce+99wIQFBSEm5sbOTk5xMXFubJEAfbsSQfAYjlOaGioQ8e2WCy2MWvVSgUUzlRmCmdEREREREREREREKrA33niDF154AYDZs2czZcoU2zYPDw+Cg61rm2hqM9c7fNja0VKnzjk8PDwcPr45tZm//wVA4UxlpnBGREREREREREREpIJ69913eeKJJwBr98yjjz5aYB9zarOoqCin1ib5GQZERHgD0KhRRrmcwwxnvL2tXVIKZyovhTMiIiIiIiIiIiIiFdBHH33Eww8/DMD06dOZPn16ofuZH9irc8a14uMhNdULyKV1a8d3zcBfr7XFYn2tFc5UXgpnRERERERERERERCqYZcuWcf/99wPw6KOPMnPmzCL3VedMxXDsmHnrFM2bO3a9GZMZzmRlnQAUzlRmCmdEREREREREREREKpj58+djGAb33HMPb7zxBhaLpch9zQ/sFc641tGj5q1jNG7cuFzOYb7WycmHATh1qlxOI06gcEZERERERERERESkgjl+/DgAt912W7HBDGhas4rir3DmaLmFM6Gh1o6c8+f3ABAdDTk55XIqKWcKZ0REREREREREREQqkNzcXE6csE5b1aJFixL317RmFcPR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7bi7G2RmetCly7XUr+/qyq485oxbJbErnJkyZQoLFy4kPDycZs2a0apVKw4ePEh2dja1atVi/PjxBY75/fffsVgsdOnSxZ5T5+Pn50fHjh05duwYY8eOBazdMWbrHkBcXJytmyY4OJjMzEwSEhLydc/ExcXZFk8qjLe3N97e3gXu9/T0rBJ/WET0XhapPHS9ilQuumZFKg9dryKVi67ZgjIzM7nzzjtJSEigV69ezJ492/YcNWzYELB+WJ6YmGhbw1lcx+xmat68ucPfy40aNQIgJiamQlwnVeV6PXQoC3AHjtCx480V5jH1798fgLCwIzRpkkNEhAcnT3rSpIlr67oSlfY9YVc83q1bN/7zn/9gsVhITk5m586dpKen4+npyYcffoi/v3++/S9evMjPP/8MwIgRI+w5dT4ZGRkcOnSIkJAQmjZtSnBwcL42uczMTNatW2cLXrp3746np2e+fWJiYti/f3+x4YyIiIiIiIiIiEhF9sQTT7Bt2zZq1qzJN998g5eXl22bp6cn9erVAyA6OtpVJUoeJ06cAKBFixYOH7tBgwYAREZGOnzsK9m+fdbp4mrWPEuNGjVcW0weNWrUoH379gDUrHkOgOPHXVmRlMSuzhmARx55hOHDh7N48WJbt8rtt99O69atC+y7du1aevbsCcDw4cMv+5yPP/44119/PY0aNSIuLo6XX36ZxMREJk6ciMViYdq0acyaNYuWLVvSsmVLZs2aha+vL3fccQcAgYGB3HfffTz22GPUrl2bWrVq8fjjj9OxY0e76hIREREREREREXGVxYsX8/bbbwPwySef0Lhx4wL7hIaGEhcXR3R0NJ07d3Z2iXKJ439+el4e4Uz9P+ezio6OJjc3V9PYOYBhwMmT1sCzkI+/Xc5cl91iOQ4EceyYqyuS4tgdzoB1vsqOHTuWuN8NN9zADTfcYPf5IiMjuf3224mPj6du3br06dOHLVu22P6F8+STT5KWlsaUKVNISEigd+/erFy5Ml8nz5tvvomHhwe33noraWlpDBs2jIULF+Lu7m53fSIiIiIiIiIiIs50/PhxJk2aBMBTTz3F6NGjC90vNDSU3bt3q3OmgijPcCYkJASLxUJWVhZnz561Lfkgly8mBtLTPYFsunYNdHU5BfTr148PP/yQhITtQH91zlRwdoUz5h/8a665hnHjxjmkoNL46quv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kJOTw/79+11dTplcvAh/NscUCGfy/l205G2pERtz2kQvL2uoWNzUZtauGfO3GQwZMrgcK7syOCScOX36NBMnTqRGjRoMHDiQW2+9lXvuuYfIyMh8+82fP59evXoxYsQIDMMoYjQRERERERERESkL80PIwYMHl+t58k5rps92yo+z15sBcHd3Jzg4GNDUZvaojJ0zFovF1j1T2aY2W78ecnOhRQto1Cj/tj/++APQlGbFMf/GpKRY24+KC2feeAPS0sDPbz/wK0OGaEoze9kdzmzdupWuXbvy2WefkZmZiWEYRf7LecyYMezdu5fff/+dlStX2ntqEREREREREZEr3oULFzh8+DBAua43A9C6dWssFgsJCQnqrihHruicAa07Y6+LFy/aXrvKFM7AX+vO7N6927WFlFHe9WbySk9PZ8uWLUD5dxRWZs2aNcPNzY3MzLUAbNliDbsuFRcH771nvZ2a+hRQ/l8GuBLYFc5cvHiRG264gfPnzxMcHMz777/Pvn37ity/bt26XHPNNQD8/PPP9pxaRERERERERESAI0eOANYP1mvVqlWu56pWrRrNmjUDNLVZeXJF5wwonLGX2XXSuHFjateu7eJqyqayds4UFc5s3bqVjIwMgoKCaNWqlfMLqyS8vLz+XDdmL97eOVy4AH/+KyUf61oz0KpVAoaxnObNm9OwYUNnl1vl2BXOvPPOO5w5c4Y6deqwefNmHnjgAdq3b1/sMeaUZltLWl1IRERERERERERKZIYzrVu3dsr5tO5M+VPnTOX03XffAdC7d28XV1J2ZufM3r17ycnJcXE1pRMfD3v2WG9f2sSRd0ozrTdTPGsInE2jRmeBglOb5e2a6dDB+h7XlGaOYVc489NPP2GxWHj00UdpdOmkfkUww5sTJ07Yc2oREREREREREcH54UzedWfE8S5cuEB8fDygcKYyuXDhAh9//DEAf//7311cTdm1atWKatWqkZKSYgsHK7o1a6z/7NABgoLyb/v+++8BGHppS40UYHbo1aplnR7z0nDG7Jrp1QvCw/8LKJxxFLvCGbPFsiyLKtWoUQOAxMREe04tIiIiIiIiIiK4rnPm0KFDTjnflcb8YDwoKAh/f3+nnlvhzOX78MMPSUlJoWPHjgwbNszV5ZSZu7s7nTp1Alyz7kxycjJ9+vyLq656p8j1zC9lTml26dO9Z88e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XbrXKVu2LFWqVGHfvn0sWbKExx9/3E4Risld5s2YzLkza9euJTY2Fn9/f4fut2vXLl5++WXr7JgCBQowatQotmzZwrRp0xgzZgxLly5lxowZVKxY8bZzV6xYAaQkvrJnz+7QOLOCKlWqULJkSU6ePMnKlSutlTTwb0uzNm3aEBAQ4KwQRURERNIkTcmZadOmYbFYbnufYRjMnTs3VeebQxvz5MnDyJEj07K1iIiIiIi4iaVLlwJQp04dm4egd+vWjX379jF//nwlZ+wsJiaGHTt2AO5TOVO5cmWKFSvGmTNnWLt2rTVZY28RERG8++67TJkyBcMw8PX15aWXXmLkyJHkzJmT559/ni5duvDMM8+wbds2ateuzZdffskzzzxj/ZtZ82bsy2Kx0KVLF77//nsWLlx41+SMWpqJiIiIO0lTW7MSJUrc9gYpvyAVLlz4jsdufStZsiQVK1akVatWvP322+zevZvSpUs75AMSERERERHnMltO2ePGeffu3QFYtGjRPdtHSfps3bqVxMREihQpYv37ztVZLBbr88oRc2fi4+P5+OOPKV++PD/++COGYdC7d28OHDjA2LFjyZkzp/XYRx55hN27d9OmTRtiYmJ47rnn6NGjB5GRkSQlJVmrbZScsR+ztdmCBQusL/68cOECGzduBJScEREREfeSpsqZEydO3PZ/c7Dn0qVLqVKlit2CEhERERER95ScnGytnLFl3oypQYMG5MuXj4sXL7J+/XpatWpl85qS4taWZv/tkODKOnbsyJQpU+w+d2bevHkMGzaMCxcuAFC/fn3GjRt336qiYsWKsXTpUsaPH8/IkSOZP38+QUFB1tk0OXPmpG7dunaNMytr1aoV/v7+nDlzhj179lC9enUWLlyIYRjUqlVLs21FRETEraSpcua/mjdvTvPmzdU/V0REREREAAgNDeXixYvkyJGDhg0b2ryep6en9dXy8+fPt3k9+deGDRsA92lpZmrTpg0eHh7s37+f06dP22XN48eP06dPHy5cuECxYsWYMWMGGzduTNXnxsPDg5dffpktW7ZQtWpVIiMjeeuttwBo2bIlXl5pek2k3Ie/vz+tW7cGYOHChcC/Lc3MKjsRERERd2FTcmb16tWsWrWKkiVL2iseERERERFxY2arqbZt2+Lt7W2XNc2brvPmzbO2MhLbJCcnW1tBNWnSxMnRpE3u3Llp0KABgN2qZ5YuXUpiYiLlypUjLCyMfv36WTtFpFaNGjXYtm0bI0aMsL6vXbt2dolP/mUmaxcuXEhcXJy1Uk/JGREREXE3NiVnREREREREbmXPeTOm9u3b4+Pjw9GjRzlw4IDd1s3KDh06xOXLl/H396dmzZrODifNzJZ59po7Y86HqVevHtmyZUv3On5+fowfP54VK1bw1ltv8dRTT9klPvmXmZzZuHEjf/31Fzdu3KBo0aLUqlXLyZGJiIiIpI3d66ujoqK4fv06SUlJDzzWXYZOioiIiIjIg127ds1ajWHP5ExAQACtWrUiODiY+fPnU7lyZbutnVWZLc3q169vtwqnjNShQwfef/99li9fTmJiok2tw5KTk1m1ahUAQUFBdomvdevW1vZbYl8lSpSgWrVqhIWF8cYbbwDQrVs3t5qbJCIiIgJ2qpxZtmwZDz30EPny5SN37tyUKFGC0qVL3/etTJky9thaRERERERcxIoVK0hKSqJixYqUKlXKrmvf2tpMbBcSEgK437wZU926dcmTJw/Xrl1jy5YtNq21d+9eLly4QLZs2ShfvrydIhRH6tq1KwBnz54F1NJMRERE3JPNyZkXXniBjh07Mm/ePC5fvoxhGKl+ExERERFJr9jYWN566y3eeust/W7pIswWU2bLKXsyb8Zu3LiRixcv2n39rMasnHHX5Iynpydt27YFbJ87s2LFCgCaNWvmllVEWZHZ2gwge/bstGrVyonRiIiIiKSPTW3NZs6cybfffguk9Nbt2bMnderUIU+ePGkenigiIiIiklqHDx/m0UcfZdeuXQD07t2bGjVqODmqrM0wDIfMmzGVKFGCGjVqsGvXLhYtWsSAAQPsvkdWcfHiRQ4ePAhAo0aNnBxN+nXs2JE//viDJUuWMHr06HSvY86badmypZ0iE0dr2LAhuXPn5sqVK7Rv3x4/Pz9nhyQiIiKSZjYlZyZOnAhA8eLFWblyJWXLlrVLUCIiIiIi9/LHH38wePBgrl+/bn3fwoULlZxxsoMHD3Lq1Cl8fX1p0aKFQ/bo3r07u3btYt68eUrO3EdSUhKXLl0iPDyciIiIO96OHDkCQKVKlcibN6+To02/9u3bA7B161YuXbqUro8lMTGRNWvWANCqVSsiIiLsGqM4hpeXF7179+aHH37giSeecHY4IiIiIuliU3Jm9+7dWCwW3n//fSVmRERERMSh4uPjefnll/n++++BlBZErVq14oMPPmDhwoW89dZbTo4wazNbmjVv3pxs2bI5ZI9u3brx4YcfEhwcTHx8PL6+vg7Zx10YhsGJEycIDQ21vu3Zs4eIiAiSkpIeeH7nzp0zIErHKVq0qHUw/PLly+ndu3ea19i+fTtRUVHkypWLGjVqKDnjRsaNG8fQoUMJCgpydigiIiIi6WJTciYhIQGAWrVq2SUYEREREZG7OXr0KI899hihoaEAjBw5kg8++IBz587xwQcfsGnTpnS/cl7sw2xp5oh5M6Y6depQqFAhIiIiWLNmjbVyIitITk7m8OHDtyViQkNDuXr16l2Pt1gs5M+fn8KFC1OoUKE73ooWLerWLc1MHTp0ICwsjCVLlqQrOWO2NGvVqhWenp72Dk8cyM/PT4kZERERcWs2JWdKlSrF/v37iY6Otlc8IiIiIiK3+fvvv3nqqaeIiooib968TJ8+nU6dOgEpc0iqV6/O7t27WbJkCf369XNytFlTbGwsq1evBhwzb8bk4eFBt27dmDx5MvPmzcsyyZkrV65Qu3ZtTpw4ccdjPj4+VKtWjdq1a1O7dm1q1qxJqVKlyJ8/P15eNv255xY6duzIF198wdKlSzEMA4vFkqbzzeRM69atHRGeiIiIiMg9edhy8sMPPwzAihUr7BKMiIiIiIjp5s2bjBgxgl69ehEVFUXjxo3ZsWOHNTFj6tKlC5Ayd0acY926dcTFxVGsWDGqVKni0L26desGwPz58zEMw6F7uYp//vmHEydO4OvrS6NGjfjf//7HlClT2LFjB9evX2f79u1MnjyZ559/nkaNGlG4cOEskZgBaNq0Kf7+/pw7d46wsLA0nRsfH8/69esBJWdEREREJOPZlJx55ZVXKFGiBOPHj+fAgQP2iklEREREsrgTJ07QtGlTvv76awBee+01Vq9eTfHixe841kzOLFmyhMTExAyNU1KY82Y6dOiQ5sqFtGrTpg1+fn6cOnWKPXv2OHQvV/HPP/8AKe38QkJC+Pbbbxk0aBA1a9bEx8fHucE5mZ+fHy1btgT+ba2XWhs3biQuLo5ChQpRuXJlB0QnIiIiInJvNiVnAgMDWbJkCQULFqRJkyZ8//33XLlyxV6xiYiIiEgWZFbJbN26ldy5czNv3jw+/fRTvL2973p8w4YNyZMnD1euXGHTpk0ZHK0ALF68GHDsvBlTtmzZaNeuHZBSPZPZxcTEsGzZMgB69uzp3GBclNlKz0wSptatLc0cnVQUEREREfkvm5IzZcqUoVOnTly7do0rV64wfPhw8ufPT6FChShTpsx938qWLWuvj0FEREREMpGvv/6a8PBwypQpw44dO6xtrO7F09PTmhRYsGBBRoQotwgLC+PAgQP4+PhYkyaOZj4n5s2blyH7OdPSpUuJjY2lVKlSVK9e3dnhuCTz+l+3bh03btxI9XmaNyMiIiIizmRTI+L/DqQ0DAPDMIiMjHzguXplkoiIiIj817Vr1/jiiy8A+L//+z9KliyZqvO6dOnCzJkzWbhwIR9//LEjQ5T/+P333wHo1KkTgYGBGbJn165dAdiyZQsREREUKlQoQ/Z1BrOlWc+ePfU31D1UqFCBkiVLcvLkSdasWUPnzp0feE50dDSbN28GlJwREREREeewKTnz5JNP2isOERERERHGjx/P1atXqVy5Mo899liqz+vYsSMeHh6EhYVx6tQpSpQo4cAoxWQYBrNmzQKgT58+GbZv4cKFqVevHlu3bmXhwoU8/fTTGbZ3RkpMTLS2blNLs3uzWCx06NCBSZMmERwcnKrkzLp160hMTKRUqVKULl06A6IUEREREbmdTcmZqVOn2isOEREREcnirl69yrhx4wAYNWoUnp6eqT43T548NGrUiA0bNrBw4UKef/55R4UptwgNDeXIkSP4+/tbq1kySrdu3di6dSvz5s3LtMmZ9evXc/nyZfLmzUuTJk2cHY5L69ixI5MmTUr13BmzpVmbNm0cGZaIiIiIyD3ZNHNGRERERMRexo0bx7Vr16hWrRqPPPJIms/v0qULAAsXLrR3aHIPZkuzbt26ERAQkKF7m3Nnli1bRnR0dIbunVHMlmbdunXDy8um19Vleq1bt8bT05NDhw7d0X77bjRvRkREREScTckZEREREXG6y5cvW6tm3n//fTw80v5rqlm5sXLlSmJjY+0an9wpOTnZmpzp3bt3hu9fo0YNypUrR2xsLHPnzs3w/R3NMIzb5s3I/QUGBtKoUSMAgoOD73vs5cuX2bFjBwCtWrVyeGwiIiIiIndj9+TM+fPnWbFiBbNnz2b27NmsWLGC8+fP23sbEREREclEvvzyS65fv0716tV5+OGH07VGtWrVKF68OLGxsaxatcrOEcp/bdq0iVOnTpEjRw46deqU4ftbLBb69esHwK+//prh+zva7t27OXnyJP7+/rRr187Z4biFDh06AA9OzqxevRrDMKhcuTKFCxfOiNBERERERO5gl+SMYRhMnDiRoKAgihQpQvv27enTpw99+vShffv2FClShKCgICZNmoRhGPbYUkREREQyiYsXL/LVV18BKbNm0lM1Ayk369XaLOOYVTM9e/bE39/fKTH07dsXgKVLlxIZGemUGBzFrJpp37492bJlc24wbqJjx44ALF++nISEhHsep3kzIiIiIuIKbE7OXLlyhWbNmjF06FD27duHYRh3fdu3bx/PP/88zZs35+rVq3YIXUREREQygy+++ILo6Ghq1qxpc/smMzmzYMECvSjIgZKSkvjjjz8A57Q0M1WoUIG6deuSlJTE7NmznRaHI6ilWdrVrl2bfPnycf36dTZt2nTP4zRvRkRERERcgU3JGcMw6NGjByEhIRiGQZ48eXj++eeZNm0aS5YsYfHixUybNo2hQ4eSN29eDMMgJCSEHj162Ct+EREREXFjFy5c4JtvvgFSqmYsFotN67Vu3Ro/Pz9OnTrF3r177RGi3MXatWuJiIggd+7cTm+5ZVbPZKbWZidOnGDnzp14eHhYZynJg3l4eFifj/dqbRYeHs7+/fuxWCy0aNEiI8MTEREREbmNTcmZmTNnsn79emu/52PHjvHdd98xYMAA2rdvT4cOHRgwYADffvstx44do3///hiGwfr16/ntt9/s9TGIiIiIiJv67LPPuHHjBrVr16Z79+42r5ctWzbrgG+1NnMcs6VZr1698PHxcWosffr0wWKxsHHjRo4dO+bUWOxl7ty5ADRr1ox8+fI5ORr38qC5M2bVTK1atciTJ0+GxSUiIiIi8l82J2cAWrRowfTp08mRI8c9jw0ICODnn3+mRYsWGIbBjBkzbNlaRERERNzc+fPn+e677wAYPXq0zVUzJs2dcayEhAT+/PNPwLktzUyFCxe2tqfKLC8AU0uz9Gvfvj0A27dv58KFC3c8rnkzIiIiIuIqbErOhIaGYrFYGDZsWKrPGT58OAA7duywZWsRERERcXOffvopMTEx1KtXz5pQsQdzrZCQEK5cuWK3dSXFihUruHTpEgUKFKBly5bODgeAfv36ASmtzdx91tClS5dYu3YtgNpBp0PhwoWpUaMGhmGw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9OvXj/3791O0aFH+/vtvfH198fX1Zd68efTt25e///6bRx99lJ9++okBAwZYz1VLM8fp0KGDNTGreTMiIiIi4kpSnZxp2bKlXVsYWCwWEhMT7baeiIiICEBcXBw9evTgwIEDFCtWjEWLFhEYGAik/D6zfPly5s6da50HkVUdPXqUDz74AD8/PwoXLnzHW8GCBfH29rZpj5EjRxIaGkqePHmYMWMGnp6edoo+bbp27crkyZP5888/+eKLL2z+uLKaW1uauYuyZcvSoEEDNm/ezO+//86IESMcvue7777LggUL8PX1Zc6cORQuXNj6mK+vL7///jtDhgxh2rRpPPnkk0RFRTFs2DBOnTpFaGgoHh4edO3a1eFxZjVdu3bl7bffpmjRolStWtXZ4YiIiIiIWKW54a5hGI6IQ0RERMRmycnJ9O/fn/Xr1xMYGMjixYspVqyY9fEePXqwfPly/vnnnyyfnBkzZgy//PLLPR+3WCzky5ePwoULU7lyZd566600DYJfsGAB48aNA1KGcd/6dchoHTt2pECBAoSHhzNv3jx69erltFgc7fLly7zwwgt07NiRJ554wub1zp8/z8qVKwH3aGl2q379+rF582Zmzpzp8OTMrFmzGDt2LABTpkyhXr16dxzj5eXFlClTyJkzJ19//TXDhw/n2rVr5MiRA4AmTZqQP39+h8aZFQUFBbF8+XIKFSqEh4e6eouIiIiI60hzcsbf358ePXrQrl07/XIrIiIiLuWVV17hzz//xMfHh3/++Ydq1ard9niPHj0YPnw4GzZsIDIykgIFCjgpUucyDINly5YB8NRTT+Ht7U14eLj1LSIigqSkJC5cuMCFCxfYvXs3s2fPZtCgQXz44YcPbBF19uxZBg4cCMCIESPo1q2boz+k+/Lx8eHpp59m7Nix/PDDD5k6OTNjxgx+/fVXfv31V9asWcM333yDn59futYyDIOvv/6a5ORk6tWrR5kyZewcrWM99thjvPTSS2zZsoXDhw9Tvnx5h+wTGhrKoEGDAHjttdes827uxsPDg/Hjx5M7d25Gjx7NO++8Q86cOQG1NHMkzZoREREREVeU6uRMjhw5uH79OrGxsfz++++sXr2avn370r9/f2rUqOHIGEVEREQeaNy4cYwfPx5IqdRo2bLlHccUL16cOnXqsH37dhYsWGC9oZrVHDlyhNOnT+Pj48O3335LtmzZbns8OTmZixcvEh4ezrlz55g6dSqzZ8/mxx9/ZNasWbz11lu89NJLd73pb87duHTpErVq1eKTTz7JqA/rvp555hk+/vhjli9f7tAb9c4WEhJi/fePP/7Ijh07+OuvvyhZsmSa1jl58iRDhgy5LYnnbgoWLEjbtm0JDg7mt99+47333rP7HufPn6dHjx7ExsbSqVMna/XM/VgsFkaNGkVgYCAvv/wyUVFRQEryWEREREREso5Ul76cP3+e3377jc6dO+Pp6UlERATjxo2jdu3a1KhRg88//5xz5845MlYRERGRu/rjjz94+eWXAfj00095/PHH73mseQPUHMCdFS1fvhxIaaP038QMpLy6v0CBAtSoUYNOnTrxxx9/sG7dOurWrUt0dDRvvfUWlSpV4vfff7+j5e2YMWNYs2YNAQEB/P777/j6+mbIx/QgpUqVolOnTgBMnDjRydE4jpmceeedd8ibNy/bt2+ndu3aBAcHp+r85ORkJkyYQLVq1Vi2bBl+fn58/vnnPPvss44M22H69u0LwK+//mr39szx8fH06tWLM2fOULFiRWbOnJmmuUovvfQSU6ZMwcPDg8aNG1O2bFm7xiciIiIiIq4t1ckZPz8/evfuzYIFCzh79izjxo2jVq1aGIbBnj17eOONNyhZsiTt2rVj+vTp3Lhxw5Fxi4iIiACwdu1a+vfvD8Dw4cN59dVX73u82Tpo2bJlWfb3FTM506ZNm1Sf07RpUzZv3sz06dMpVqwYJ0+epE+fPjRp0oTNmzcDsG7dOkaNGgXA999/73LVKc8//zwAU6dOJS4uzsnR2N+ZM2c4ffo0np6evPnmm2zfvp26dety+fJlOnXqxIcffkhycvI9zz927Bht2rRh6NChREdH07RpU3bt2sUrr7zitu2MH3roIfz8/Dh06BChoaF2W9cwDIYNG8aGDRsIDAxk7ty55MqVK83rDBo0iBMnTrBkyRK7xSYiIiIiIu4hXX9l5c+fnxEjRrBt2zb27t3LG2+8QbFixUhKSmLFihUMHDiQggUL0r9/f4KDg+3+KjURERERgL1799KjRw9u3rzJQw89xLhx47BYLPc9p1q1apQpU4a4uDiWLl2aQZG6jqSkJOuA97Zt26bpXA8PD5544gkOHjzIBx98QLZs2di4cSMNGzakb9++9O3bl+TkZAYMGGBNmLmSTp06UaJECS5fvszs2bOdHY7dbdy4EYAaNWqQPXt2SpYsybp163jmmWcwDIP33nuP7t27c+XKldvOS05O5uuvvyYoKIjVq1eTLVs2vvrqK9asWUOFChWc8aHYTY4cOejevTuQUj1jL9999x0//vgjFouF3377jYoVK6Z7reLFi5MjRw67xSYiIiIiIu7B5pfAVa5cmbFjx3Ly5ElWrlzJwIEDyZEjBzExMfz666907tyZokWL8sYbb9gjXhEREREAzp07R6dOnbh69SqNGzfm119/TVVLIYvFkqVbm4WGhnL16lUCAwOpU6dOutbIli0b7777LocPH2bgwIHWG9RnzpyhfPnyfPfdd3aO2j48PT155plnAPjhhx+cHI39mS3NGjdubH2fn58fEydO5KeffsLPz4+FCxdSt25ddu7cCcChQ4do3rw5I0aMICYmhpYtW7J7925eeOEFt62W+a9+/foB8Ntvv5GYmGjzejt37uTFF18E4JNPPrG2yxMREREREUkLu/7F1bJlS3766SciIiKYOXMmnTp1ss6n+eabb+y5lYiIiGRhUVFRdO7cmdOnT1OhQgXmzZuHv79/qs83W5stWLDALjdr3YnZ0qxVq1Z4eXnZtFaRIkWYOnUq27Zto3Xr1hQtWpQ//viDgIAAe4TqEE8//TReXl6EhISwe/duZ4djV3dLzpieeuopQkJCKF26NMeOHaNRo0Y899xz1KhRgw0bNhAQEMD333/PihUrMt3sk44dO5IvXz4iIiJYvHixzet9/fXXJCUl0aNHjwe2URQREREREbkXh7wczmKx4OHhgcVieWBrEREREZG0uHnzJr169WLXrl0UKFCAJUuWkDdv3jSt0bhxY/Lly8fly5dZv369gyJ1TWZyJq0tze6ndu3arFixgjNnzlCzZk27resIhQoV4qGHHgIyV/VMbGysdabK3ZIzALVq1WLbtm107tyZuLg4Jk6cSFxcHO3atSMsLIznn38+01TL3MrHx4cBAwYAMHnyZJvWunLlCrNmzQLg9ddf1986IiIiIiKSbnb962vNmjUMHjyYggUL8vjjj7N48WISEhIoXLgwL7zwgj23EhERkSzIMAwGDx7M8uXLyZ49O4sWLaJ06dJpXsfLy4uuXbsCWau1WUxMjDUZZc/kjLt57rnnAJg+fTrXr193cjT2sW3bNhITEylc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MplMWrZsmX7//Xerj2ctvXr10saNG5UiRQotW7ZMadOmfaX706VLp1WrVsnLy0s7duxQoUKF5OXlpTx58qhRo0YaMWKEVq9erfPnz8tkMilv3rxq3Lix5syZo3z58llpVrbXs2dPZcyYUSdPntS0adOe227lypU6dOiQUqZMqW7dutkwISzlcfH38VF+bdu2VY4cOeyYCAAAAACQGFGcAQAkemPHjtWtW7dUpEgRNWjQwCZj5s+f3/wb9Il198yUKVMUHBwsSQoLC1ORIkVeq58CBQpoyZIlcnJy0okTJ3T79m25ubnpnXfeUfv27TV58mTt2LFDt27dUkREhL7//nu1bNnSklOxuxQpUmjQoEGSpKFDh+rWrVtPtfnnrpkuXbrI29vblhFhIaVKlTIXY5ydndW/f3/7BgIAAAAAJEoUZwAAidrVq1f17bffSpIGDRokBwfbvbU9Psrohx9+0LFjx2w27psyDEMjR440P8h+8ODBql+//hv1Wa1aNW3btk3z58/XkSNHFB0drd27d2v69Onq3Lmzypcvr5QpU1oifoLVtm1b5c2bV1euXNE333zz1PVffvlFu3btkpubmz7//HM7JIQlmEwm87GGHTt2VLZs2eycCAAAAACQGFGcAQBYxJ07d9SoUaNnfihtLdHR0erRo4du376tYsWKqV69ejYbW5KKFSsmX19fGYahr7/+2qZjv674+Hj16tVLffv2lST17t1bX375pUX6Llu2rJo2baqCBQvKycnJIn0mJk5OTgoKCpL0aDfX+fPnn7j+eNdM+/btlSFDBpvng+UEBgZq9erVGjt2rL2jAAAAAAASKYozAACL+O6777Rw4UL16dNHP//8s1XHio+PV1hYmPLly6d58+ZJevTBty13zTz2ePdMWFiYTp06ZfPxX8XDhw/l7+9vfj7P6NGj9c0338hkMtk5WdJRv359lStXTnfv3tWQIUPMr2/fvl2//vqrnJ2d9cUXX9gxISzBxcVFtWvXlrOzs72jAAAAAAASKYozAACLmD17tvnPbdq00fXr160yzt69e/Xuu++qZcuWOn/+vHLlyqUVK1aoTp06Vhnv35QrV07Vq1dXbGysRo0aZZcML+P27dvy8/PT/Pnz5eTkpLCwMPXq1cvesZIck8mkkSNHSpJmzJihiIgISf+/ayYgIEBZs2a1Wz4AAAAAAJAw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", + "text/plain": [ + "
" + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "#| eval: false\n", + "# Plot predictions\n", + "fig, ax = plt.subplots(1, 1, figsize = (20, 7))\n", + "Y_hat_df = forecasts.reset_index(drop=False).drop(columns=['unique_id','ds'])\n", + "plot_df = pd.concat([Y_test_df, Y_hat_df], axis=1)\n", + "plot_df = pd.concat([Y_train_df, plot_df])\n", + "\n", + "plot_df = plot_df[plot_df.unique_id=='Airline1'].drop('unique_id', axis=1)\n", + "plt.plot(plot_df['ds'], plot_df['y'], c='black', label='True')\n", + "plt.plot(plot_df['ds'], plot_df['iTransformer'], c='blue', label='Forecast')\n", + "ax.set_title('AirPassengers Forecast', fontsize=22)\n", + "ax.set_ylabel('Monthly Passengers', fontsize=20)\n", + "ax.set_xlabel('Year', fontsize=20)\n", + "ax.legend(prop={'size': 15})\n", + "ax.grid()" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import pytorch_lightning as pl\n", + "import matplotlib.pyplot as plt\n", + "\n", + "from neuralforecast import NeuralForecast\n", + "from neuralforecast.utils import AirPassengersPanel, AirPassengersStatic\n", + "from neuralforecast.losses.pytorch import MSE" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/marcopeix/miniconda3/envs/neuralforecast/lib/python3.10/site-packages/pytorch_lightning/utilities/parsing.py:198: Attribute 'loss' is an instance of `nn.Module` and is already saved during checkpointing. It is recommended to ignore them using `self.save_hyperparameters(ignore=['loss'])`.\n", + "/Users/marcopeix/miniconda3/envs/neuralforecast/lib/python3.10/site-packages/pytorch_lightning/utilities/parsing.py:198: Attribute 'valid_loss' is an instance of `nn.Module` and is already saved during checkpointing. It is recommended to ignore them using `self.save_hyperparameters(ignore=['valid_loss'])`.\n", + "Seed set to 1\n", + "GPU available: True (mps), used: True\n", + "TPU available: False, using: 0 TPU cores\n", + "IPU available: False, using: 0 IPUs\n", + "HPU available: False, using: 0 HPUs\n", + "\n", + " | Name | Type | Params\n", + "---------------------------------------------------------\n", + "0 | padder | ConstantPad1d | 0 \n", + "1 | loss | MSE | 0 \n", + "2 | valid_loss | MAE | 0 \n", + "3 | scaler | TemporalNorm | 0 \n", + "4 | enc_embedding | DataEmbedding_inverted | 3.2 K \n", + "5 | encoder | TransEncoder | 135 K \n", + "6 | projector | Linear | 1.5 K \n", + "---------------------------------------------------------\n", + "140 K Trainable params\n", + "0 Non-trainable params\n", + "140 K Total params\n", + "0.562 Total estimated model params size (MB)\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "f118cbdd019d4bb0990b028bc6e8ddeb", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Sanity Checking: | | 0/? [00:00]. Skipping setting a default `ModelSummary` callback.\n", + "GPU available: True (mps), used: True\n", + "TPU available: False, using: 0 TPU cores\n", + "IPU available: False, using: 0 IPUs\n", + "HPU available: False, using: 0 HPUs\n", + "/Users/marcopeix/miniconda3/envs/neuralforecast/lib/python3.10/site-packages/pytorch_lightning/trainer/connectors/data_connector.py:441: The 'predict_dataloader' does not have many workers which may be a bottleneck. Consider increasing the value of the `num_workers` argument` to `num_workers=10` in the `DataLoader` to improve performance.\n" + ] + }, + { + "data": { + "application/vnd.jupyter.widget-view+json": { + "model_id": "7d07116f871b4263a25d7874684e167a", + "version_major": 2, + "version_minor": 0 + }, + "text/plain": [ + "Predicting: | | 0/? [00:00=AirPassengersPanel['ds'].values[-12]].reset_index(drop=True) # 12 test\n", + "\n", + "model = iTransformer(h=12,\n", + " input_size=24,\n", + " n_series=1,\n", + " hidden_size=128,\n", + " n_heads=2,\n", + " e_layers=2,\n", + " d_layers=1,\n", + " d_ff=4,\n", + " factor=1,\n", + " dropout=0.1,\n", + " use_norm=True,\n", + " loss=MSE(),\n", + " valid_loss=MAE(),\n", + " early_stop_patience_steps=3,\n", + " batch_size=32)\n", + "\n", + "fcst = NeuralForecast(models=[model], freq='M')\n", + "fcst.fit(df=Y_train_df, val_size=12)\n", + "forecasts = fcst.predict(futr_df=Y_test_df)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "python3", + "language": "python", + "name": "python3" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/neuralforecast/_modidx.py b/neuralforecast/_modidx.py index 933d3af02..0f795ee19 100644 --- a/neuralforecast/_modidx.py +++ b/neuralforecast/_modidx.py @@ -120,7 +120,12 @@ 'neuralforecast.auto.AutoVanillaTransformer.__init__': ( 'models.html#autovanillatransformer.__init__', 'neuralforecast/auto.py'), 'neuralforecast.auto.AutoVanillaTransformer.get_default_config': ( 'models.html#autovanillatransformer.get_default_config', - 'neuralforecast/auto.py')}, + 'neuralforecast/auto.py'), + 'neuralforecast.auto.AutoiTransformer': ('models.html#autoitransformer', 'neuralforecast/auto.py'), + 'neuralforecast.auto.AutoiTransformer.__init__': ( 'models.html#autoitransformer.__init__', + 'neuralforecast/auto.py'), + 'neuralforecast.auto.AutoiTransformer.get_default_config': ( 'models.html#autoitransformer.get_default_config', + 'neuralforecast/auto.py')}, 'neuralforecast.core': { 'neuralforecast.core.NeuralForecast': ('core.html#neuralforecast', 'neuralforecast/core.py'), 'neuralforecast.core.NeuralForecast.__init__': ( 'core.html#neuralforecast.__init__', 'neuralforecast/core.py'), @@ -674,6 +679,32 @@ 'neuralforecast/models/informer.py'), 'neuralforecast.models.informer.ProbMask.mask': ( 'models.informer.html#probmask.mask', 'neuralforecast/models/informer.py')}, + 'neuralforecast.models.itransformer': { 'neuralforecast.models.itransformer.DataEmbedding_inverted': ( 'models.itransformer.html#dataembedding_inverted', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.DataEmbedding_inverted.__init__': ( 'models.itransformer.html#dataembedding_inverted.__init__', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.DataEmbedding_inverted.forward': ( 'models.itransformer.html#dataembedding_inverted.forward', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.FullAttention': ( 'models.itransformer.html#fullattention', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.FullAttention.__init__': ( 'models.itransformer.html#fullattention.__init__', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.FullAttention.forward': ( 'models.itransformer.html#fullattention.forward', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.TriangularCausalMask': ( 'models.itransformer.html#triangularcausalmask', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.TriangularCausalMask.__init__': ( 'models.itransformer.html#triangularcausalmask.__init__', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.TriangularCausalMask.mask': ( 'models.itransformer.html#triangularcausalmask.mask', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.iTransformer': ( 'models.itransformer.html#itransformer', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.iTransformer.__init__': ( 'models.itransformer.html#itransformer.__init__', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.iTransformer.forecast': ( 'models.itransformer.html#itransformer.forecast', + 'neuralforecast/models/itransformer.py'), + 'neuralforecast.models.itransformer.iTransformer.forward': ( 'models.itransformer.html#itransformer.forward', + 'neuralforecast/models/itransformer.py')}, 'neuralforecast.models.lstm': { 'neuralforecast.models.lstm.LSTM': ('models.lstm.html#lstm', 'neuralforecast/models/lstm.py'), 'neuralforecast.models.lstm.LSTM.__init__': ( 'models.lstm.html#lstm.__init__', 'neuralforecast/models/lstm.py'), diff --git a/neuralforecast/auto.py b/neuralforecast/auto.py index cbfef705b..20932619a 100644 --- a/neuralforecast/auto.py +++ b/neuralforecast/auto.py @@ -3,8 +3,8 @@ # %% auto 0 __all__ = ['AutoRNN', 'AutoLSTM', 'AutoGRU', 'AutoTCN', 'AutoDeepAR', 'AutoDilatedRNN', 'AutoMLP', 'AutoNBEATS', 'AutoNBEATSx', 'AutoNHITS', 'AutoDLinear', 'AutoNLinear', 'AutoTFT', 'AutoVanillaTransformer', 'AutoInformer', - 'AutoAutoformer', 'AutoFEDformer', 'AutoPatchTST', 'AutoTimesNet', 'AutoStemGNN', 'AutoHINT', 'AutoTSMixer', - 'AutoTSMixerx', 'AutoMLPMultivariate'] + 'AutoAutoformer', 'AutoFEDformer', 'AutoPatchTST', 'AutoiTransformer', 'AutoTimesNet', 'AutoStemGNN', + 'AutoHINT', 'AutoTSMixer', 'AutoTSMixerx', 'AutoMLPMultivariate'] # %% ../nbs/models.ipynb 2 from os import cpu_count @@ -37,6 +37,7 @@ from .models.fedformer import FEDformer from .models.patchtst import PatchTST from .models.timesnet import TimesNet +from .models.itransformer import iTransformer from .models.stemgnn import StemGNN from .models.hint import HINT @@ -1297,7 +1298,92 @@ def get_default_config(cls, h, backend, n_series=None): return config -# %% ../nbs/models.ipynb 88 +# %% ../nbs/models.ipynb 87 +class AutoiTransformer(BaseAuto): + + default_config = { + "input_size_multiplier": [1, 2, 3, 4, 5], + "h": None, + "n_series": None, + "hidden_size": tune.choice([64, 128, 256]), + "n_heads": tune.choice([4, 8]), + "learning_rate": tune.loguniform(1e-4, 1e-1), + "scaler_type": tune.choice([None, "robust", "standard"]), + "max_steps": tune.choice([500, 1000, 2000]), + "batch_size": tune.choice([32, 64, 128, 256]), + "loss": None, + "random_seed": tune.randint(1, 20), + } + + def __init__( + self, + h, + n_series, + loss=MAE(), + valid_loss=None, + config=None, + search_alg=BasicVariantGenerator(random_state=1), + num_samples=10, + refit_with_val=False, + cpus=cpu_count(), + gpus=torch.cuda.device_count(), + verbose=False, + alias=None, + backend="ray", + callbacks=None, + ): + + # Define search space, input/output sizes + if config is None: + config = self.get_default_config(h=h, backend=backend, n_series=n_series) + + # Always use n_series from parameters, raise exception with Optuna because we can't enforce it + if backend == "ray": + config["n_series"] = n_series + elif backend == "optuna": + mock_trial = MockTrial() + if ( + "n_series" in config(mock_trial) + and config(mock_trial)["n_series"] != n_series + ) or ("n_series" not in config(mock_trial)): + raise Exception(f"config needs 'n_series': {n_series}") + + super(AutoiTransformer, self).__init__( + cls_model=iTransformer, + h=h, + loss=loss, + valid_loss=valid_loss, + config=config, + search_alg=search_alg, + num_samples=num_samples, + refit_with_val=refit_with_val, + cpus=cpus, + gpus=gpus, + verbose=verbose, + alias=alias, + backend=backend, + callbacks=callbacks, + ) + + @classmethod + def get_default_config(cls, h, backend, n_series): + config = cls.default_config.copy() + config["input_size"] = tune.choice( + [h * x for x in config["input_size_multiplier"]] + ) + + # Rolling windows with step_size=1 or step_size=h + # See `BaseWindows` and `BaseRNN`'s create_windows + config["step_size"] = tune.choice([1, h]) + del config["input_size_multiplier"] + if backend == "optuna": + # Always use n_series from parameters + config["n_series"] = n_series + config = cls._ray_config_to_optuna(config) + + return config + +# %% ../nbs/models.ipynb 92 class AutoTimesNet(BaseAuto): default_config = { @@ -1365,7 +1451,7 @@ def get_default_config(cls, h, backend, n_series=None): return config -# %% ../nbs/models.ipynb 93 +# %% ../nbs/models.ipynb 97 class AutoStemGNN(BaseAuto): default_config = { @@ -1450,7 +1536,7 @@ def get_default_config(cls, h, backend, n_series): return config -# %% ../nbs/models.ipynb 97 +# %% ../nbs/models.ipynb 101 class AutoHINT(BaseAuto): def __init__( @@ -1515,7 +1601,7 @@ def _fit_model(self, cls_model, config, dataset, val_size, test_size): def get_default_config(cls, h, backend, n_series=None): raise Exception("AutoHINT has no default configuration.") -# %% ../nbs/models.ipynb 102 +# %% ../nbs/models.ipynb 106 class AutoTSMixer(BaseAuto): default_config = { @@ -1601,7 +1687,7 @@ def get_default_config(cls, h, backend, n_series): return config -# %% ../nbs/models.ipynb 106 +# %% ../nbs/models.ipynb 110 class AutoTSMixerx(BaseAuto): default_config = { @@ -1687,7 +1773,7 @@ def get_default_config(cls, h, backend, n_series): return config -# %% ../nbs/models.ipynb 110 +# %% ../nbs/models.ipynb 114 class AutoMLPMultivariate(BaseAuto): default_config = { diff --git a/neuralforecast/core.py b/neuralforecast/core.py index 5e6061c04..cefc05463 100644 --- a/neuralforecast/core.py +++ b/neuralforecast/core.py @@ -52,6 +52,7 @@ TSMixer, TSMixerx, MLPMultivariate, + iTransformer, ) # %% ../nbs/core.ipynb 5 @@ -156,6 +157,8 @@ def _insample_times( "autotsmixerx": TSMixerx, "mlpmultivariate": MLPMultivariate, "automlpmultivariate": MLPMultivariate, + "itransformer": iTransformer, + "autoitransformer": iTransformer, } # %% ../nbs/core.ipynb 8 diff --git a/neuralforecast/models/__init__.py b/neuralforecast/models/__init__.py index bd3fae666..4ce374098 100644 --- a/neuralforecast/models/__init__.py +++ b/neuralforecast/models/__init__.py @@ -2,6 +2,7 @@ 'MLP', 'NHITS', 'NBEATS', 'NBEATSx', 'DLinear', 'NLinear', 'TFT', 'VanillaTransformer', 'Informer', 'Autoformer', 'PatchTST', 'FEDformer', 'StemGNN', 'HINT', 'TimesNet', 'TimeLLM', 'TSMixer', 'TSMixerx', 'MLPMultivariate', + 'iTransformer' ] from .rnn import RNN @@ -28,4 +29,5 @@ from .timellm import TimeLLM from .tsmixer import TSMixer from .tsmixerx import TSMixerx -from .mlpmultivariate import MLPMultivariate \ No newline at end of file +from .mlpmultivariate import MLPMultivariate +from .itransformer import iTransformer diff --git a/neuralforecast/models/itransformer.py b/neuralforecast/models/itransformer.py new file mode 100644 index 000000000..25b7c69f9 --- /dev/null +++ b/neuralforecast/models/itransformer.py @@ -0,0 +1,293 @@ +# AUTOGENERATED! DO NOT EDIT! File to edit: ../../nbs/models.itransformer.ipynb. + +# %% auto 0 +__all__ = ['iTransformer'] + +# %% ../../nbs/models.itransformer.ipynb 6 +import torch +import torch.nn as nn +import torch.nn.functional as F + +import numpy as np + +from typing import Optional +from math import sqrt + +from ..losses.pytorch import MAE +from ..common._base_multivariate import BaseMultivariate + +from neuralforecast.common._modules import ( + TransEncoder, + TransEncoderLayer, + AttentionLayer, +) + +# %% ../../nbs/models.itransformer.ipynb 9 +class TriangularCausalMask: + def __init__(self, B, L, device="cpu"): + mask_shape = [B, 1, L, L] + with torch.no_grad(): + self._mask = torch.triu( + torch.ones(mask_shape, dtype=torch.bool), diagonal=1 + ).to(device) + + @property + def mask(self): + return self._mask + + +class FullAttention(nn.Module): + def __init__( + self, + mask_flag=True, + factor=5, + scale=None, + attention_dropout=0.1, + output_attention=False, + ): + super(FullAttention, self).__init__() + self.scale = scale + self.mask_flag = mask_flag + self.output_attention = output_attention + self.dropout = nn.Dropout(attention_dropout) + + def forward(self, queries, keys, values, attn_mask, tau=None, delta=None): + B, L, H, E = queries.shape + _, S, _, D = values.shape + scale = self.scale or 1.0 / sqrt(E) + + scores = torch.einsum("blhe,bshe->bhls", queries, keys) + + if self.mask_flag: + if attn_mask is None: + attn_mask = TriangularCausalMask(B, L, device=queries.device) + + scores.masked_fill_(attn_mask.mask, -np.inf) + + A = self.dropout(torch.softmax(scale * scores, dim=-1)) + V = torch.einsum("bhls,bshd->blhd", A, values) + + if self.output_attention: + return (V.contiguous(), A) + else: + return (V.contiguous(), None) + +# %% ../../nbs/models.itransformer.ipynb 11 +class DataEmbedding_inverted(nn.Module): + def __init__(self, c_in, hidden_size, dropout=0.1): + super(DataEmbedding_inverted, self).__init__() + self.value_embedding = nn.Linear(c_in, hidden_size) + self.dropout = nn.Dropout(p=dropout) + + def forward(self, x, x_mark): + x = x.permute(0, 2, 1) + # x: [Batch Variate Time] + if x_mark is None: + x = self.value_embedding(x) + else: + # the potential to take covariates (e.g. timestamps) as tokens + x = self.value_embedding(torch.cat([x, x_mark.permute(0, 2, 1)], 1)) + # x: [Batch Variate hidden_size] + return self.dropout(x) + +# %% ../../nbs/models.itransformer.ipynb 13 +class iTransformer(BaseMultivariate): + """iTransformer + + **Parameters:**
+ `h`: int, Forecast horizon.
+ `input_size`: int, autorregresive inputs size, y=[1,2,3,4] input_size=2 -> y_[t-2:t]=[1,2].
+ `n_series`: int, number of time-series.
+ `futr_exog_list`: str list, future exogenous columns.
+ `hist_exog_list`: str list, historic exogenous columns.
+ `stat_exog_list`: str list, static exogenous columns.
+ `hidden_size`: int, dimension of the model.
+ `n_heads`: int, number of heads.
+ `e_layers`: int, number of encoder layers.
+ `d_layers`: int, number of decoder layers.
+ `d_ff`: int, dimension of fully-connected layer.
+ `factor`: int, attention factor.
+ `dropout`: float, dropout rate.
+ `use_norm`: bool, whether to normalize or not.
+ `loss`: PyTorch module, instantiated train loss class from [losses collection](https://nixtla.github.io/neuralforecast/losses.pytorch.html).
+ `valid_loss`: PyTorch module=`loss`, instantiated valid loss class from [losses collection](https://nixtla.github.io/neuralforecast/losses.pytorch.html).
+ `max_steps`: int=1000, maximum number of training steps.
+ `learning_rate`: float=1e-3, Learning rate between (0, 1).
+ `num_lr_decays`: int=-1, Number of learning rate decays, evenly distributed across max_steps.
+ `early_stop_patience_steps`: int=-1, Number of validation iterations before early stopping.
+ `val_check_steps`: int=100, Number of training steps between every validation loss check.
+ `batch_size`: int=32, number of different series in each batch.
+ `step_size`: int=1, step size between each window of temporal data.
+ `scaler_type`: str='identity', type of scaler for temporal inputs normalization see [temporal scalers](https://nixtla.github.io/neuralforecast/common.scalers.html).
+ `random_seed`: int=1, random_seed for pytorch initializer and numpy generators.
+ `num_workers_loader`: int=os.cpu_count(), workers to be used by `TimeSeriesDataLoader`.
+ `drop_last_loader`: bool=False, if True `TimeSeriesDataLoader` drops last non-full batch.
+ `alias`: str, optional, Custom name of the model.
+ `optimizer`: Subclass of 'torch.optim.Optimizer', optional, user specified optimizer instead of the default choice (Adam).
+ `optimizer_kwargs`: dict, optional, list of parameters used by the user specified `optimizer`.
+ `**trainer_kwargs`: int, keyword trainer arguments inherited from [PyTorch Lighning's trainer](https://pytorch-lightning.readthedocs.io/en/stable/api/pytorch_lightning.trainer.trainer.Trainer.html?highlight=trainer).
+ + **References**
+ - [Yong Liu, Tengge Hu, Haoran Zhang, Haixu Wu, Shiyu Wang, Lintao Ma, Mingsheng Long. "iTransformer: Inverted Transformers Are Effective for Time Series Forecasting"](https://arxiv.org/abs/2310.06625) + """ + + # Class attributes + SAMPLING_TYPE = "multivariate" + + def __init__( + self, + h, + input_size, + n_series, + futr_exog_list=None, + hist_exog_list=None, + stat_exog_list=None, + hidden_size: int = 512, + n_heads: int = 8, + e_layers: int = 2, + d_layers: int = 1, + d_ff: int = 2048, + factor: int = 1, + dropout: float = 0.1, + use_norm: bool = True, + loss=MAE(), + valid_loss=None, + max_steps: int = 1000, + learning_rate: float = 1e-3, + num_lr_decays: int = -1, + early_stop_patience_steps: int = -1, + val_check_steps: int = 100, + batch_size: int = 32, + step_size: int = 1, + scaler_type: str = "identity", + random_seed: int = 1, + num_workers_loader: int = 0, + drop_last_loader: bool = False, + optimizer=None, + optimizer_kwargs=None, + **trainer_kwargs + ): + + super(iTransformer, self).__init__( + h=h, + input_size=input_size, + n_series=n_series, + stat_exog_list=None, + futr_exog_list=None, + hist_exog_list=None, + loss=loss, + valid_loss=valid_loss, + max_steps=max_steps, + learning_rate=learning_rate, + num_lr_decays=num_lr_decays, + early_stop_patience_steps=early_stop_patience_steps, + val_check_steps=val_check_steps, + batch_size=batch_size, + step_size=step_size, + scaler_type=scaler_type, + random_seed=random_seed, + num_workers_loader=num_workers_loader, + drop_last_loader=drop_last_loader, + optimizer=optimizer, + optimizer_kwargs=optimizer_kwargs, + **trainer_kwargs + ) + + # Asserts + if stat_exog_list is not None: + raise Exception("iTransformer does not support static exogenous variables") + if futr_exog_list is not None: + raise Exception("iTransformer does not support future exogenous variables") + if hist_exog_list is not None: + raise Exception( + "iTransformer does not support historical exogenous variables" + ) + + self.enc_in = n_series + self.dec_in = n_series + self.c_out = n_series + self.hidden_size = hidden_size + self.n_heads = n_heads + self.e_layers = e_layers + self.d_layers = d_layers + self.d_ff = d_ff + self.factor = factor + self.dropout = dropout + self.use_norm = use_norm + + # Architecture + self.enc_embedding = DataEmbedding_inverted( + input_size, self.hidden_size, self.dropout + ) + + self.encoder = TransEncoder( + [ + TransEncoderLayer( + AttentionLayer( + FullAttention( + False, self.factor, attention_dropout=self.dropout + ), + self.hidden_size, + self.n_heads, + ), + self.hidden_size, + self.d_ff, + dropout=self.dropout, + activation=F.gelu, + ) + for l in range(self.e_layers) + ], + norm_layer=torch.nn.LayerNorm(self.hidden_size), + ) + + self.projector = nn.Linear(self.hidden_size, h, bias=True) + + def forecast(self, x_enc): + if self.use_norm: + # Normalization from Non-stationary Transformer + means = x_enc.mean(1, keepdim=True).detach() + x_enc = x_enc - means + stdev = torch.sqrt( + torch.var(x_enc, dim=1, keepdim=True, unbiased=False) + 1e-5 + ) + x_enc /= stdev + + _, _, N = x_enc.shape # B L N + # B: batch_size; E: hidden_size; + # L: input_size; S: horizon(h); + # N: number of variate (tokens), can also includes covariates + + # Embedding + # B L N -> B N E (B L N -> B L E in the vanilla Transformer) + enc_out = self.enc_embedding( + x_enc, None + ) # covariates (e.g timestamp) can be also embedded as tokens + + # B N E -> B N E (B L E -> B L E in the vanilla Transformer) + # the dimensions of embedded time series has been inverted, and then processed by native attn, layernorm and ffn modules + enc_out, attns = self.encoder(enc_out, attn_mask=None) + + # B N E -> B N S -> B S N + dec_out = self.projector(enc_out).permute(0, 2, 1)[ + :, :, :N + ] # filter the covariates + + if self.use_norm: + # De-Normalization from Non-stationary Transformer + dec_out = dec_out * (stdev[:, 0, :].unsqueeze(1).repeat(1, self.h, 1)) + dec_out = dec_out + (means[:, 0, :].unsqueeze(1).repeat(1, self.h, 1)) + + return dec_out + + def forward(self, windows_batch): + insample_y = windows_batch["insample_y"] + + y_pred = self.forecast(insample_y) + y_pred = y_pred[:, -self.h :, :] + y_pred = self.loss.domain_map(y_pred) + + # domain_map might have squeezed the last dimension in case n_series == 1 + if y_pred.ndim == 2: + return y_pred.unsqueeze(-1) + else: + return y_pred