docstr: Fits the NeuralForecast model.
docstr_tok: ["Fits","the","NeuralForecast","model","."]
code: def fit(self, train_data: EncodedDs, dev_data: EncodedDs) -> None:
      """
      Fits the NeuralForecast model.
      """  # noqa
      log.info("Started fitting N-HITS forecasting model")
  
      # prepare data
      cat_ds = ConcatedEncodedDs([train_data, dev_data])
      oby_col = self.ts_analysis["tss"].order_by
      gby = (
          self.ts_analysis["tss"].group_by
          if self.ts_analysis["tss"].group_by
          else []
      )
      df = deepcopy(cat_ds.data_frame)
      Y_df, _ = self._make_initial_df(df, mode="train")
      self.group_boundaries = self._set_boundary(Y_df, gby)
      if gby:
          n_time = df[gby].value_counts().min()
      else:
          n_time = len(df[f"__mdb_original_{oby_col}"].unique())
      n_ts_val = max(
          int(0.1 * n_time), self.horizon
      )  # at least self.horizon to validate on
  
      # train the model
      n_time_out = self.horizon
      if self.pretrained:
          # TODO: let user specify finetuning
          self.model_name = self.model_names.get(
              self.freq_to_model[
                  self.ts_analysis["sample_freqs"]["__default"]
              ],
              None,
          )
          self.model_name = (
              self.model_names["hourly"]
              if self.model_name is None
              else self.model_name
          )
          ckpt_url = self.base_url + self.model_name
          self.model = self.model_class.load_from_checkpoint(ckpt_url)
  
          if not self.window < self.model.hparams.n_time_in:
              log.info(
                  f"NOTE: Provided window ({self.window}) is smaller than specified model input length ({self.model.hparams.n_time_in}). Will train a new model from scratch."
              )  # noqa
              self.pretrained = False
          if self.horizon > self.model.hparams.n_time_out:
              log.info(
                  f"NOTE: Horizon ({self.horizon}) is bigger than that of the pretrained model ({self.model.hparams.n_time_out}). Will train a new model from scratch."
              )  # noqa
              self.pretrained = False
          if self.pretrained:
              log.info(
                  f"Successfully loaded pretrained N-HITS forecasting model ({self.model_name})"
              )
  
      if not self.pretrained:
          if self.window + self.horizon > n_time:
              new_window = max(1, n_time - self.horizon - 1)
              self.window = new_window
              log.info(
                  f"Window {self.window} is too long for data provided (group: {df[gby].value_counts()[::-1].index[0]}), reducing window to {new_window}."
              )  # noqa
          model = self.model_class(
              h=n_time_out,
              input_size=self.window,
              **self.train_args,
              loss=MQLoss(level=self.conf_level),
          )  # noqa
          self.model = NeuralForecast(
              models=[model],
              freq=self.ts_analysis["sample_freqs"]["__default"],
          )
          self.model.fit(df=Y_df, val_size=n_ts_val)
          log.info("Successfully trained N-HITS forecasting model.")
  
file_path: lightwood/lightwood/mixer/nhits.py
imports: from typing import Dict, Union, Optional
  from copy import deepcopy
  import numpy
  import pandas
  from neuralforecast import NeuralForecast
  from neuralforecast.models.nhits import NHITS
  from neuralforecast.models.nbeats import NBEATS
  from neuralforecast.losses.pytorch import MQLoss
  from lightwood.helpers.log import log
  from lightwood.mixer.base import BaseMixer
  from lightwood.api.types import PredictionArguments
  from lightwood.data.encoded_ds import EncodedDs, ConcatedEncodedDs
label_desc: Use image node_id 2 for calling the NHitsMixer obj's underlying member method code with example usage: obj.fit(train_data, dev_data) without return types