Hide keyboard shortcuts

Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1""" 

2Initialization methods for states of exponential smoothing models 

3""" 

4 

5import numpy as np 

6import pandas as pd 

7 

8 

9def _initialization_simple(endog, trend=False, seasonal=False, 

10 seasonal_periods=None): 

11 # See Section 7.6 of Hyndman and Athanasopoulos 

12 initial_trend = None 

13 initial_seasonal = None 

14 

15 # Non-seasonal 

16 if seasonal is None: 

17 initial_level = endog[0] 

18 if trend == 'add': 

19 initial_trend = endog[1] - endog[0] 

20 elif trend == 'mul': 

21 initial_trend = endog[1] / endog[0] 

22 # Seasonal 

23 else: 

24 initial_level = np.mean(endog[:seasonal_periods]) 

25 m = seasonal_periods 

26 if trend is not None: 

27 initial_trend = (pd.Series(endog).diff(m)[m:2 * m] / m).mean() 

28 

29 if seasonal == 'add': 

30 initial_seasonal = endog[:m] - initial_level 

31 elif seasonal == 'mul': 

32 initial_seasonal = endog[:m] / initial_level 

33 

34 return initial_level, initial_trend, initial_seasonal 

35 

36 

37def _initialization_heuristic(endog, trend=False, seasonal=False, 

38 seasonal_periods=None): 

39 # See Section 2.6 of Hyndman et al. 

40 endog = endog.copy() 

41 nobs = len(endog) 

42 

43 if nobs < 10: 

44 raise ValueError('Cannot use heuristic method with less than 10' 

45 ' observations.') 

46 

47 # Seasonal component 

48 initial_seasonal = None 

49 if seasonal is not None: 

50 # Calculate the number of full cycles to use 

51 if nobs < 2 * seasonal_periods: 

52 raise ValueError('Cannot compute initial seasonals using' 

53 ' heuristic method with less than two full' 

54 ' seasonal cycles in the data.') 

55 # We need at least 10 periods for the level initialization 

56 # and we will lose self.seasonal_periods // 2 values at the 

57 # beginning and end of the sample, so we need at least 

58 # 10 + 2 * (self.seasonal_periods // 2) values 

59 min_obs = 10 + 2 * (seasonal_periods // 2) 

60 if nobs < min_obs: 

61 raise ValueError('Cannot use heuristic method to compute' 

62 ' initial seasonal and levels with less' 

63 ' than 10 + 2 * (seasonal_periods // 2)' 

64 ' datapoints.') 

65 # In some datasets we may only have 2 full cycles (but this may 

66 # still satisfy the above restriction that we will end up with 

67 # 10 seasonally adjusted observations) 

68 k_cycles = min(5, nobs // seasonal_periods) 

69 # In other datasets, 3 full cycles may not be enough to end up 

70 # with 10 seasonally adjusted observations 

71 k_cycles = max(k_cycles, int(np.ceil(min_obs / seasonal_periods))) 

72 

73 # Compute the moving average 

74 series = pd.Series(endog[:seasonal_periods * k_cycles]) 

75 initial_trend = series.rolling(seasonal_periods, center=True).mean() 

76 if seasonal_periods % 2 == 0: 

77 initial_trend = initial_trend.shift(-1).rolling(2).mean() 

78 

79 # Detrend 

80 if seasonal == 'add': 

81 detrended = series - initial_trend 

82 elif seasonal == 'mul': 

83 detrended = series / initial_trend 

84 

85 # Average seasonal effect 

86 tmp = np.zeros(k_cycles * seasonal_periods) * np.nan 

87 tmp[:len(detrended)] = detrended.values 

88 initial_seasonal = np.nanmean( 

89 tmp.reshape(k_cycles, seasonal_periods).T, axis=1) 

90 

91 # Normalize the seasonals 

92 if seasonal == 'add': 

93 initial_seasonal -= np.mean(initial_seasonal) 

94 elif seasonal == 'mul': 

95 initial_seasonal /= np.mean(initial_seasonal) 

96 

97 # Replace the data with the trend 

98 endog = initial_trend.dropna().values 

99 

100 # Trend / Level 

101 exog = np.c_[np.ones(10), np.arange(10) + 1] 

102 beta = np.linalg.pinv(exog).dot(endog[:10]) 

103 initial_level = beta[0] 

104 

105 initial_trend = None 

106 if trend == 'add': 

107 initial_trend = beta[1] 

108 elif trend == 'mul': 

109 initial_trend = 1 + beta[1] / beta[0] 

110 

111 return initial_level, initial_trend, initial_seasonal