def fit(self, series: TimeSeries): super().fit(series) ts = self.training_series self.length = len(ts) # Check for statistical significance of user-defined season period # or infers season_period from the TimeSeries itself. if self.season_mode is SeasonalityMode.NONE: self.season_period = 1 else: self.season_period = self.seasonality_period if self.season_period is None: max_lag = len(ts) // 2 self.is_seasonal, self.season_period = check_seasonality( ts, self.season_period, max_lag=max_lag ) else: # force the user-defined seasonality to be considered as a true seasonal period. self.is_seasonal = self.season_period > 1 new_ts = ts # Store and remove seasonality effect if there is any. if self.is_seasonal: _, self.seasonality = extract_trend_and_seasonality( ts, self.season_period, model=self.season_mode ) new_ts = remove_from_series(ts, self.seasonality, model=self.season_mode) # SES part of the decomposition. self.model = hw.SimpleExpSmoothing(new_ts.values(copy=False)).fit() # Linear Regression part of the decomposition. We select the degree one coefficient. b_theta = np.polyfit( np.array([i for i in range(0, self.length)]), (1.0 - self.theta) * new_ts.values(copy=False), 1, )[0] # Normalization of the coefficient b_theta. self.coef = b_theta / (-self.theta) self.alpha = self.model.params["smoothing_level"] if self.alpha == 0.0: self.model = hw.SimpleExpSmoothing(new_ts.values(copy=False)).fit( initial_level=ALPHA_START ) self.alpha = self.model.params["smoothing_level"] return self
def exp_smoothing(ts, back_steps=10, degree=1, steps=1): """ Predicts next value using simple exponential smoothing. Parameters: ----------- ts: Array of floats An array of times series data to be used for the polyfit regression Returns: -------- x : The predicted value from the exponential smoothing method. """ timeseries = np.array(list(ts.values())) timeseries = timeseries[-back_steps:] if len(timeseries) == 1: timeseries = [np.inf, 0] # exponential smoothing errors when there are five datapoints # average is appended to the beginning of the timeseries for minimal impact # https://github.com/statsmodels/statsmodels/issues/4878 elif len(timeseries) == 5: timeseries = np.append(np.mean(timeseries), timeseries) model = hw.SimpleExpSmoothing(timeseries) model_fit = model.fit() x = model_fit.predict(len(timeseries), len(timeseries) + steps - 1) return x[-1]
def fit(self, ts, season_period: int = None): """ Fits the Theta method to the TimeSeries `ts`. The model decomposition is defined by the parameters `theta`, and the TimeSeries `ts` is de-seasonalized according to `season_period`. :param ts: The TimeSeries to fit. :param season_period: User-defined seasonality period. Default to None. """ super().fit(ts) self.length = len(ts) # Check for statistical significance of user-defined season period # or infers season_period from the TimeSeries itself. if season_period is None: max_lag = 24 self.is_seasonal, self.season_period = check_seasonality(ts, season_period, max_lag=max_lag) else: self.season_period = season_period self.is_seasonal = True # force the user-defined seasonality to be considered as a true seasonal period. new_ts = ts # Store and remove seasonality effect if there is any. if self.is_seasonal: _, self.seasonality = extract_trend_and_seasonality(ts, self.season_period, model=self.mode) new_ts = remove_seasonality(ts, self.season_period, model=self.mode) # SES part of the decomposition. self.model = hw.SimpleExpSmoothing(new_ts.values()).fit() # Linear Regression part of the decomposition. We select the degree one coefficient. b_theta = np.polyfit(np.array([i for i in range(0, self.length)]), (1.0 - self.theta) * new_ts.values(), 1)[0] # Normalization of the coefficient b_theta. self.coef = b_theta / (2.0 - self.theta) self.alpha = self.model.params["smoothing_level"]
def decompose(self): ''' Croston's decomposition ''' z = ts.SimpleExpSmoothing(self.demandValues.to_numpy()) p = ts.ExponentialSmoothing(self.intervals.to_numpy()) # Demand level z = z.fit(smoothing_level=self.alpha, initial_level = self.demandValues[0], optimized=False) # Intervals p = p.fit(smoothing_level=self.alpha, initial_level = self.intervals[0], optimized=False ) self.fittedvalues = z.fittedfcast self.fittedIntervals = p.fittedfcast self.fittedForecasts = self.fittedvalues/self.fittedIntervals self.fcast = z.forecast(1)/p.forecast(1)
def fit(self, series: TimeSeries, component_index: Optional[int] = None): super().fit(series, component_index) ts = self.training_series self.length = len(ts) self.season_period = self.seasonality_period # Check for statistical significance of user-defined season period # or infers season_period from the TimeSeries itself. if self.season_period is None: max_lag = len(ts) // 2 self.is_seasonal, self.season_period = check_seasonality( ts, self.season_period, max_lag=max_lag) logger.info( 'Theta model inferred seasonality of training series: {}'. format(self.season_period)) else: self.is_seasonal = True # force the user-defined seasonality to be considered as a true seasonal period. new_ts = ts # Store and remove seasonality effect if there is any. if self.is_seasonal: _, self.seasonality = extract_trend_and_seasonality( ts, self.season_period, model=self.mode) new_ts = remove_seasonality(ts, self.season_period, model=self.mode) # SES part of the decomposition. self.model = hw.SimpleExpSmoothing(new_ts.values()).fit() # Linear Regression part of the decomposition. We select the degree one coefficient. b_theta = np.polyfit(np.array([i for i in range(0, self.length)]), (1.0 - self.theta) * new_ts.values(), 1)[0] # Normalization of the coefficient b_theta. self.coef = b_theta / (2.0 - self.theta) self.alpha = self.model.params["smoothing_level"]
def fit(self, series): super().fit(series) self.length = len(series) # normalization of data if self.normalization: self.mean = series.pd_dataframe(copy=False).mean().mean() raise_if_not( not np.isclose(self.mean, 0), "The mean value of the provided series is too close to zero to perform normalization", logger, ) new_ts = series / self.mean else: new_ts = series # Check for statistical significance of user-defined season period # or infers season_period from the TimeSeries itself. if self.season_mode is SeasonalityMode.NONE: self.season_period = 1 else: self.season_period = self.seasonality_period if self.season_period is None: max_lag = len(series) // 2 self.is_seasonal, self.season_period = check_seasonality( series, self.season_period, max_lag=max_lag ) else: # force the user-defined seasonality to be considered as a true seasonal period. self.is_seasonal = self.season_period > 1 # Store and remove seasonality effect if there is any. if self.is_seasonal: _, self.seasonality = extract_trend_and_seasonality( new_ts, self.season_period, model=self.season_mode ) new_ts = remove_from_series( new_ts, self.seasonality, model=self.season_mode ) ts_values = new_ts.univariate_values() if (ts_values <= 0).any(): self.model_mode = ModelMode.ADDITIVE self.trend_mode = TrendMode.LINEAR logger.warning( "Time series has negative values. Fallback to additive and linear model" ) # Drift part of the decomposition if self.trend_mode is TrendMode.LINEAR: linreg = ts_values else: linreg = np.log(ts_values) self.drift = np.poly1d(np.polyfit(np.arange(self.length), linreg, 1)) theta0_in = self.drift(np.arange(self.length)) if self.trend_mode is TrendMode.EXPONENTIAL: theta0_in = np.exp(theta0_in) if (theta0_in > 0).all() and self.model_mode is ModelMode.MULTIPLICATIVE: theta_t = (ts_values**self.theta) * (theta0_in ** (1 - self.theta)) else: if self.model_mode is ModelMode.MULTIPLICATIVE: logger.warning("Negative Theta line. Fallback to additive model") self.model_mode = ModelMode.ADDITIVE theta_t = self.theta * ts_values + (1 - self.theta) * theta0_in # SES part of the decomposition. self.model = hw.SimpleExpSmoothing(theta_t).fit() theta2_in = self.model.fittedvalues if (theta2_in > 0).all() and self.model_mode is ModelMode.MULTIPLICATIVE: self.fitted_values = theta2_in**self.wses * theta0_in**self.wdrift else: if self.model_mode is ModelMode.MULTIPLICATIVE: self.model_mode = ModelMode.ADDITIVE logger.warning("Negative Theta line. Fallback to additive model") theta_t = self.theta * ts_values + (1 - self.theta) * theta0_in self.model = hw.SimpleExpSmoothing(theta_t).fit() theta2_in = self.model.fittedvalues self.fitted_values = self.wses * theta2_in + self.wdrift * theta0_in if self.is_seasonal: if self.season_mode is SeasonalityMode.ADDITIVE: self.fitted_values += self.seasonality.univariate_values(copy=False) elif self.season_mode is SeasonalityMode.MULTIPLICATIVE: self.fitted_values *= self.seasonality.univariate_values(copy=False) # Fitted values are the results of the fit of the model on the train series. A good fit of the model # will lead to fitted_values similar to ts. But one cannot see if it overfits. if self.normalization: self.fitted_values *= self.mean return self
def exponentialFit(self, name): ''' Parameters ---------- name: name of model ''' modelName = name errorObjs = [] # Step 1: fit selected model if name == 'NAIVE': # for evaluation self.fittedModel = ts.ExponentialSmoothing(self.trainData) self.fittedModel = self.fittedModel.fit(smoothing_level=1) # for real forecasts self.fittedModelFinal = ts.ExponentialSmoothing(self.data) self.fittedModelFinal = self.fittedModelFinal.fit( smoothing_level=1) elif name == 'SES': # for evaluation self.fittedModel = ts.SimpleExpSmoothing(self.trainData) self.fittedModel = self.fittedModel.fit( optimized=True, use_brute=True) #grid search # for real forecasts self.fittedModelFinal = ts.SimpleExpSmoothing(self.data) self.fittedModelFinal = self.fittedModelFinal.fit( optimized=True, use_brute=True) #grid search elif name == 'HOLT': # Holt-Winters # for evaluation self.fittedModel = ts.Holt(self.trainData) self.fittedModel = self.fittedModel.fit( optimized=True, use_brute=True) #grid search # for real forecasts self.fittedModelFinal = ts.Holt(self.data) self.fittedModelFinal = self.fittedModelFinal.fit( optimized=True, use_brute=True) #grid search # Step 2: get fitted values for training, test and forecasts trainingFit = pd.Series(self.fittedModel.fittedvalues) forecasts = pd.Series(self.fittedModelFinal.forecast(self.horizon)) if self.stepType == 'multi': testPredictions = pd.Series( self.fittedModel.forecast(len(self.testData))) else: # Compute one-step-ahead forecast over the test data SESParams = self.fittedModel.params self.fittedModel = ts.SimpleExpSmoothing(self.data) if modelName == 'HOLT': self.fittedModel = ts.Holt(self.data) self.fittedModel = self.fittedModel.fit( smoothing_level=SESParams['smoothing_level'], optimized=False, smoothing_slope=SESParams['smoothing_slope'], initial_slope=SESParams['initial_slope'], initial_level=SESParams['initial_level'], use_brute=False) else: self.fittedModel = self.fittedModel.fit( smoothing_level=SESParams['smoothing_level'], optimized=False, initial_level=SESParams['initial_level'], use_brute=False) testPredictions = self.fittedModel.fittedvalues[self.start:] # Step 3: set error errorObjs = self.setErrorData(trainingFit, testPredictions) # Add to ModelsResult list self.setModelResults(modelName, errorObjs, trainingFit, testPredictions, forecasts)
def fit(self): self.fittedModel = holtwinters.SimpleExpSmoothing( self.ts_train).fit(optimized=True)
# root_path=r"C:\Users\Kang\Desktop\model_management\saved_models" file_name=id+'_'+model_name+'.m' # e.g., 44117_WMA.m model_path=os.path.join(root_path, file_name) # 模型的加载 # model = joblib.load(model_path) try: model = joblib.load(model_path) except Exception as e: print('[ERROR]:sku_id({})的{}模型加载失败({})'.format(id,model_name,e)) return None return model if __name__=='__main__': import numpy as np import pandas as pd from statsmodels.tsa import holtwinters # 测试指数平滑 index=pd.date_range('5/1/2018',periods=20,freq='d') ts_train=pd.Series([1.0,2,3,4,3,6,3,7,3,5,1,2,3,4,3,6,3,7,3,5],index=index) train_model = holtwinters.SimpleExpSmoothing(ts_train).fit(optimized=True) save_forecast_model(id='11111',model_name='SES',model=train_model) loaded_model=load_forecast_model(id='11111',model_name='SES') fittedvalues=loaded_model.predict(start=0,end=len(ts_train)-1) y_predict=loaded_model.forecast(4) print(fittedvalues) print(y_predict)
def exponentialFit(self, name): ''' Parameters ---------- name: name of model ''' modelName = name errorObjs = [] runTimeObj = obj.ModelsRunTime(name) startTime = None totalTime = None # Step 1: fit selected model if name == 'NAIVE': # for evaluation startTime = dt.datetime.now() self.fittedModel = ts.ExponentialSmoothing(self.trainData) self.fittedModel = self.fittedModel.fit(smoothing_level=1) runTimeObj.setTrainingTime(dt.datetime.now() - startTime) # for real forecasts self.fittedModelFinal = ts.ExponentialSmoothing(self.data) self.fittedModelFinal = self.fittedModelFinal.fit( smoothing_level=1) elif name == 'SES': # for evaluation startTime = dt.datetime.now() self.fittedModel = ts.SimpleExpSmoothing(self.trainData) self.fittedModel = self.fittedModel.fit( optimized=True, use_brute=True) #grid search runTimeObj.setTrainingTime(dt.datetime.now() - startTime) # for real forecasts self.fittedModelFinal = ts.SimpleExpSmoothing(self.data) self.fittedModelFinal = self.fittedModelFinal.fit( optimized=True, use_brute=True) #grid search elif name == 'HOLT': # Holt's linear trend method # for evaluation startTime = dt.datetime.now() self.fittedModel = ts.Holt(self.trainData) self.fittedModel = self.fittedModel.fit( optimized=True, use_brute=True) #grid search runTimeObj.setTrainingTime(dt.datetime.now() - startTime) # for real forecasts self.fittedModelFinal = ts.Holt(self.data) self.fittedModelFinal = self.fittedModelFinal.fit( optimized=True, use_brute=True) #grid search # Step 2: get fitted values for training, test and forecasts trainingFit = pd.Series(np.ceil(self.fittedModel.fittedvalues)) startTime = dt.datetime.now() testPredictions = pd.Series( np.ceil(self.fittedModel.forecast(len(self.testData)))) totalTime = dt.datetime.now() - startTime forecasts = pd.Series( np.ceil(self.fittedModelFinal.forecast(self.horizon))) # Step 3: set error errorObjs = self.setErrorData(trainingFit, testPredictions, runTimeObj) runTimeObj.setTestTime(runTimeObj.getTestTime() + totalTime) self.runTimeList.append(runTimeObj) # Add to ModelsResult list self.setModelResults(modelName, errorObjs, trainingFit, testPredictions, forecasts)