예제 #1
0
    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
예제 #2
0
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]
예제 #3
0
    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)
예제 #5
0
    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"]
예제 #6
0
    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
예제 #7
0
    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)



예제 #10
0
    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)