docstr: `train_sample` contains the following tensors:
      (past_target, past_covariates, historic_future_covariates, future_covariates, static_covariates,
      future_target)
  
      each tensor has shape (n_timesteps, n_variables)
      - past/historic tensors have shape (input_chunk_length, n_variables)
      - future tensors have shape (output_chunk_length, n_variables)
      - static covariates have shape (component, static variable)
  
  Darts Interpretation of pytorch-forecasting's TimeSeriesDataSet:
      time_varying_knowns : future_covariates (including historic_future_covariates)
      time_varying_unknowns : past_targets, past_covariates
  
      time_varying_encoders : [past_targets, past_covariates, historic_future_covariates, future_covariates]
      time_varying_decoders : [historic_future_covariates, future_covariates]
  
  `variable_meta` is used in TFT to access specific variables
docstr_tok: ["`","train_sample","`","contains","the","following","tensors",":","(","past_target",",","past_covariates",",","historic_future_covariates",",","future_covariates",",","static_covariates",",","future_target",")","each","tensor","has","shape","(","n_timesteps",",","n_variables",")","-","past\/historic","tensors","have","shape","(","input_chunk_length",",","n_variables",")","-","future","tensors","have","shape","(","output_chunk_length",",","n_variables",")","-","static","covariates","have","shape","(","component",",","static","variable",")","Darts","Interpretation","of","pytorch-forecasting","'s","TimeSeriesDataSet",":","time_varying_knowns",":","future_covariates","(","including","historic_future_covariates",")","time_varying_unknowns",":","past_targets",",","past_covariates","time_varying_encoders",":","[","past_targets",",","past_covariates",",","historic_future_covariates",",","future_covariates","]","time_varying_decoders",":","[","historic_future_covariates",",","future_covariates","]","`","variable_meta","`","is","used","in","TFT","to","access","specific","variables"]
code: def _create_model(
      self, train_sample: MixedCovariatesTrainTensorType
  ) -> nn.Module:
      """
      `train_sample` contains the following tensors:
          (past_target, past_covariates, historic_future_covariates, future_covariates, static_covariates,
          future_target)
  
          each tensor has shape (n_timesteps, n_variables)
          - past/historic tensors have shape (input_chunk_length, n_variables)
          - future tensors have shape (output_chunk_length, n_variables)
          - static covariates have shape (component, static variable)
  
      Darts Interpretation of pytorch-forecasting's TimeSeriesDataSet:
          time_varying_knowns : future_covariates (including historic_future_covariates)
          time_varying_unknowns : past_targets, past_covariates
  
          time_varying_encoders : [past_targets, past_covariates, historic_future_covariates, future_covariates]
          time_varying_decoders : [historic_future_covariates, future_covariates]
  
      `variable_meta` is used in TFT to access specific variables
      """
      (
          past_target,
          past_covariate,
          historic_future_covariate,
          future_covariate,
          static_covariates,
          future_target,
      ) = train_sample
  
      # add a covariate placeholder so that relative index will be included
      if self.add_relative_index:
          time_steps = (
              self.input_chunk_length + self.output_chunk_length
          )
  
          expand_future_covariate = np.arange(time_steps).reshape(
              (time_steps, 1)
          )
  
          historic_future_covariate = np.concatenate(
              [
                  ts[: self.input_chunk_length]
                  for ts in [
                      historic_future_covariate,
                      expand_future_covariate,
                  ]
                  if ts is not None
              ],
              axis=1,
          )
          future_covariate = np.concatenate(
              [
                  ts[-self.output_chunk_length :]
                  for ts in [future_covariate, expand_future_covariate]
                  if ts is not None
              ],
              axis=1,
          )
  
      self.output_dim = (
          (future_target.shape[1], 1)
          if self.likelihood is None
          else (future_target.shape[1], self.likelihood.num_parameters)
      )
  
      tensors = [
          past_target,
          past_covariate,
          historic_future_covariate,  # for time varying encoders
          future_covariate,
          future_target,  # for time varying decoders
          static_covariates,  # for static encoder
      ]
      type_names = [
          "past_target",
          "past_covariate",
          "historic_future_covariate",
          "future_covariate",
          "future_target",
          "static_covariate",
      ]
      variable_names = [
          "target",
          "past_covariate",
          "future_covariate",
          "future_covariate",
          "target",
          "static_covariate",
      ]
  
      variables_meta = {
          "input": {
              type_name: [
                  f"{var_name}_{i}" for i in range(tensor.shape[1])
              ]
              for type_name, var_name, tensor in zip(
                  type_names, variable_names, tensors
              )
              if tensor is not None
          },
          "model_config": {},
      }
  
      reals_input = []
      categorical_input = []
      time_varying_encoder_input = []
      time_varying_decoder_input = []
      static_input = []
      static_input_numeric = []
      static_input_categorical = []
      categorical_embedding_sizes = {}
      for input_var in type_names:
          if input_var in variables_meta["input"]:
              vars_meta = variables_meta["input"][input_var]
              if input_var in [
                  "past_target",
                  "past_covariate",
                  "historic_future_covariate",
              ]:
                  time_varying_encoder_input += vars_meta
                  reals_input += vars_meta
              elif input_var in ["future_covariate"]:
                  time_varying_decoder_input += vars_meta
                  reals_input += vars_meta
              elif input_var in ["static_covariate"]:
                  if (
                      self.static_covariates is None
                  ):  # when training with fit_from_dataset
                      static_cols = pd.Index(
                          [i for i in range(static_covariates.shape[1])]
                      )
                  else:
                      static_cols = self.static_covariates.columns
                  numeric_mask = ~static_cols.isin(
                      self.categorical_embedding_sizes
                  )
                  for idx, (
                      static_var,
                      col_name,
                      is_numeric,
                  ) in enumerate(
                      zip(vars_meta, static_cols, numeric_mask)
                  ):
                      static_input.append(static_var)
                      if is_numeric:
                          static_input_numeric.append(static_var)
                          reals_input.append(static_var)
                      else:
                          # get embedding sizes for each categorical variable
                          embedding = self.categorical_embedding_sizes[
                              col_name
                          ]
                          raise_if_not(
                              isinstance(embedding, (int, tuple)),
                              "Dict values of `categorical_embedding_sizes` must either be integers or tuples. Read "
                              "the TFTModel documentation for more information.",
                              logger,
                          )
                          if isinstance(embedding, int):
                              embedding = (
                                  embedding,
                                  get_embedding_size(n=embedding),
                              )
                          categorical_embedding_sizes[
                              vars_meta[idx]
                          ] = embedding
  
                          static_input_categorical.append(static_var)
                          categorical_input.append(static_var)
  
      variables_meta["model_config"]["reals_input"] = list(
          dict.fromkeys(reals_input)
      )
      variables_meta["model_config"]["categorical_input"] = list(
          dict.fromkeys(categorical_input)
      )
      variables_meta["model_config"][
          "time_varying_encoder_input"
      ] = list(dict.fromkeys(time_varying_encoder_input))
      variables_meta["model_config"][
          "time_varying_decoder_input"
      ] = list(dict.fromkeys(time_varying_decoder_input))
      variables_meta["model_config"]["static_input"] = list(
          dict.fromkeys(static_input)
      )
      variables_meta["model_config"]["static_input_numeric"] = list(
          dict.fromkeys(static_input_numeric)
      )
      variables_meta["model_config"]["static_input_categorical"] = list(
          dict.fromkeys(static_input_categorical)
      )
  
      n_static_components = (
          len(static_covariates) if static_covariates is not None else 0
      )
  
      self.categorical_embedding_sizes = categorical_embedding_sizes
  
      return _TFTModule(
          output_dim=self.output_dim,
          variables_meta=variables_meta,
          num_static_components=n_static_components,
          hidden_size=self.hidden_size,
          lstm_layers=self.lstm_layers,
          dropout=self.dropout,
          num_attention_heads=self.num_attention_heads,
          full_attention=self.full_attention,
          feed_forward=self.feed_forward,
          hidden_continuous_size=self.hidden_continuous_size,
          categorical_embedding_sizes=self.categorical_embedding_sizes,
          add_relative_index=self.add_relative_index,
          norm_type=self.norm_type,
          **self.pl_module_params,
      )
  
imports: from typing import Dict, List, Optional, Sequence, Tuple, Union
  import numpy
  import pandas
  import torch
  from torch import nn
  from torch.nn import LSTM
  from darts import TimeSeries
  from darts.logging import get_logger, raise_if, raise_if_not, raise_log
  from darts.models.components import glu_variants, layer_norm_variants
  from darts.models.components.glu_variants import GLU_FFN
  from darts.models.forecasting.pl_forecasting_module import PLMixedCovariatesModule, io_processor
  from darts.models.forecasting.tft_submodels import _GateAddNorm, _GatedResidualNetwork, _InterpretableMultiHeadAttention, _MultiEmbedding, _VariableSelectionNetwork, get_embedding_size
  from darts.models.forecasting.torch_forecasting_model import MixedCovariatesTorchModel
  from darts.utils.data import MixedCovariatesSequentialDataset, MixedCovariatesTrainingDataset, TrainingDataset
  from darts.utils.likelihood_models import Likelihood, QuantileRegression
label_desc: Use image node_id 2 for calling the TFTModel obj's underlying member method code with example usage: obj._create_model(train_sample) and returns: _TFTModule