class_docstr: Multi-scale Exponential Smoother (MSES) is a forecasting algorithm modeled heavily 
  after classical mechanical concepts, namely, velocity and acceleration.
  
  Having seen data points of a time series up to time t, MSES forecasts x(t+h) by
  anchoring at a value b steps back from the last known value, x(t-b), and estimating the
  delta between x(t-b) and x(t+h). The delta over these b+h timesteps, delta(b+h), also known 
  as the delta at scale b+h, is predicted by estimating the velocity over these timesteps 
  as well as the change in the velocity, acceleration. Specifically, 
  
      xhat(t+h) = x(t-b) + velocity_hat(b+h) + acceleration_hat(b+h)
  
  This estimation is done for each b, known as a backstep, from 0, which anchors at x(t), 
  1,... up to a maximum backstep configurable by the user. The algorithm then takes the 
  seperate forecasts of x(t+h), indexed by which backstep was used, xhat_b(t+h), and determines
  a final forecast: p(b|h) dot xhat_b, where p(b|h) is a distribution over the xhat_b's that is 
  determined according to the lowest standard errors of the recency-weighted velocity estimates.
  
  Letting ``w`` be the recency weight, ``B`` the maximum backstep, ``x_t`` the last seen data point,
  and ``l_s,t`` the series of losses for scale ``s``. 
  
      .. math:: 
          \begin{align*}
          \hat{x}_{t+h} & = \sum_{b=0}^B p_{b} \cdot (x_{t-b} + v_{b+h,t} + a_{b+h,t}) \\
          \space \\
          \text{where} \space\space & v_{b+h,t} = \text{EMA}_w(\Delta_{b+h} x_t)   \\
          & a_{b+h,t} = \text{EMA}_w(\Delta_{b+h}^2 x_t) \\
          \text{and} \space\space & p_b = \sigma(z)_b \space\space \\
          \text{if} & \space\space  z_b = (b+h)^\phi \cdot \text{EMA}_w(l_{b+h,t}) \cdot \text{RWSE}_w(l_{b+h,t})\\
          \end{align*}
class_docstr_tok: ["Multi-scale","Exponential","Smoother","(","MSES",")","is","a","forecasting","algorithm","modeled","heavily","after","classical","mechanical","concepts",",","namely",",","velocity","and","acceleration",".","Having","seen","data","points","of","a","time","series","up","to","time","t",",","MSES","forecasts","x","(","t+h",")","by","anchoring","at","a","value","b","steps","back","from","the","last","known","value",",","x","(","t-b",")",",","and","estimating","the","delta","between","x","(","t-b",")","and","x","(","t+h",")",".","The","delta","over","these","b+h","timesteps",",","delta","(","b+h",")",",","also","known","as","the","delta","at","scale","b+h",",","is","predicted","by","estimating","the","velocity","over","these","timesteps","as","well","as","the","change","in","the","velocity",",","acceleration",".","Specifically",",","xhat","(","t+h",")","=","x","(","t-b",")","+","velocity_hat","(","b+h",")","+","acceleration_hat","(","b+h",")","This","estimation","is","done","for","each","b",",","known","as","a","backstep",",","from","0",",","which","anchors","at","x","(","t",")",",","1",",","...","up","to","a","maximum","backstep","configurable","by","the","user",".","The","algorithm","then","takes","the","seperate","forecasts","of","x","(","t+h",")",",","indexed","by","which","backstep","was","used",",","xhat_b","(","t+h",")",",","and","determines","a","final","forecast",":","p","(","b|h",")","dot","xhat_b",",","where","p","(","b|h",")","is","a","distribution","over","the","xhat_b","'s","that","is","determined","according","to","the","lowest","standard","errors","of","the","recency-weighted","velocity","estimates",".","Letting","``","w","``","be","the","recency","weight",",","``","B","``","the","maximum","backstep",",","``","x_t","``","the","last","seen","data","point",",","and","``","l_s",",","t","``","the","series","of","losses","for","scale","``","s","``",".","..","math",":",":","\\begin","{","align","*","}","\\hat","{","x","}","_","{","t+h","}","&","=","\\sum_","{","b=0","}","^B","p_","{","b","}","\\cdot","(","x_","{","t-b","}","+","v_","{","b+h",",","t","}","+","a_","{","b+h",",","t","}",")","\\\\","\\space","\\\\","\\text","{","where","}","\\space\\space","&","v_","{","b+h",",","t","}","=","\\text","{","EMA","}","_w","(","\\Delta_","{","b+h","}","x_t",")","\\\\","&","a_","{","b+h",",","t","}","=","\\text","{","EMA","}","_w","(","\\Delta_","{","b+h","}","^2","x_t",")","\\\\","\\text","{","and","}","\\space\\space","&","p_b","=","\\sigma","(","z",")","_b","\\space\\space","\\\\","\\text","{","if","}","&","\\space\\space","z_b","=","(","b+h",")","^\\phi","\\cdot","\\text","{","EMA","}","_w","(","l_","{","b+h",",","t","}",")","\\cdot","\\text","{","RWSE","}","_w","(","l_","{","b+h",",","t","}",")","\\\\","\\end","{","align","*","}"]
docstr: Updates the MSES model with new data that has been acquired since the model's initial training.
  
  :param new_data: New data that has occured since the last training time.
  :param tune_recency_weights: If True, the model will first forecast the values at the
      new_data's timestamps, calculate the associated losses, and use these losses
      to make updates to the recency weight.
  :param train_cadence: The frequency at which the training forecasts will be generated
      during incremental training.
code: def update(
      self,
      new_data: pd.DataFrame,
      tune_recency_weights: bool = True,
      train_cadence=None,
  ) -> Tuple[TimeSeries, TimeSeries]:
      """
      Updates the MSES model with new data that has been acquired since the model's initial training.
  
      :param new_data: New data that has occured since the last training time.
      :param tune_recency_weights: If True, the model will first forecast the values at the
          new_data's timestamps, calculate the associated losses, and use these losses
          to make updates to the recency weight.
      :param train_cadence: The frequency at which the training forecasts will be generated
          during incremental training.
      """
      name = self.target_name
      if len(new_data) == 0:
          return (
              UnivariateTimeSeries.empty(name=name).to_ts(),
              UnivariateTimeSeries.empty(name=f"{name}_err").to_ts(),
          )
  
      new_data = TimeSeries.from_pd(new_data).univariates[name]
      assert_equal_timedeltas(
          new_data, self.timedelta, self.timedelta_offset
      )
      next_train_time = self.last_train_time + self.timedelta
      if to_pd_datetime(new_data.t0) > next_train_time:
          logger.warning(
              f"Updating the model with new data requires the "
              f"new data to start at or before time "
              f"{to_pd_datetime(next_train_time)}, which is the time "
              f"directly after the last train time. Got data starting "
              f"at {to_pd_datetime(new_data.t0)} instead."
          )
  
      _, new_data = new_data.bisect(next_train_time, t_in_left=False)
      if new_data.is_empty():
          return (
              UnivariateTimeSeries.empty(name=name).to_ts(),
              UnivariateTimeSeries.empty(name=f"{name}_err").to_ts(),
          )
  
      return self._incremental_train(
          train_data=new_data,
          train_cadence=train_cadence,
          process_losses=True,
          tune_recency_weights=tune_recency_weights,
      )
  
imports: import logging
  from math import floor
  from typing import Dict, List, Optional, Tuple, Union
  import numpy
  import pandas
  from merlion.utils.time_series import TimeSeries, UnivariateTimeSeries, assert_equal_timedeltas
  from merlion.utils.istat import ExponentialMovingAverage, RecencyWeightedVariance
  from merlion.utils.resample import to_pd_datetime, to_timestamp
  from merlion.transform.moving_average import LagTransform
  from merlion.transform.resample import TemporalResample
  from merlion.models.forecast.base import ForecasterBase, ForecasterConfig
label_desc: Use image node_id 10 for calling the MSES obj's underlying member method code with example usage: obj.update(new_data, tune_recency_weights, train_cadence) and returns: self, UnivariateTimeSeries,  UnivariateTimeSeries, UnivariateTimeSeries,  UnivariateTimeSeries