Exemple #1
0
    def test_seasonal_harmonics(self, seasonal_periods, seasonal_harmonics,
                                expected_harmonics):
        c = Components(seasonal_periods=seasonal_periods,
                       seasonal_harmonics=seasonal_harmonics)
        assert np.array_equal(expected_harmonics, c.seasonal_harmonics)

        copied = c.with_arma(p=1, q=2)
        assert np.array_equal(expected_harmonics, copied.seasonal_harmonics)
Exemple #2
0
    def test_without_seasonal_periods(self):
        old_periods = [3.3, 4.4]
        old_harmonics = [2, 1]
        c = Components(seasonal_periods=old_periods,
                       seasonal_harmonics=old_harmonics)
        copied = c.without_seasonal_periods()

        # old components should not change
        assert np.array_equal(old_periods, c.seasonal_periods)
        assert np.array_equal(old_harmonics, c.seasonal_harmonics)

        # new components should have no periods and no harmonics
        assert np.array_equal([], copied.seasonal_periods)
        assert np.array_equal([], copied.seasonal_harmonics)
Exemple #3
0
    def test_with_seasonal_periods(self):
        old_periods = [3.3, 4.4]
        old_harmonics = [2, 1]
        c = Components(seasonal_periods=old_periods,
                       seasonal_harmonics=old_harmonics)
        new_periods = [2, 3, 4.4]
        copied = c.with_seasonal_periods(seasonal_periods=new_periods)

        # old components should not change
        assert np.array_equal(old_periods, c.seasonal_periods)
        assert np.array_equal(old_harmonics, c.seasonal_harmonics)

        # new components should have new periods and ones for harmonics
        assert np.array_equal(new_periods, copied.seasonal_periods)
        assert np.array_equal([1, 1, 1], copied.seasonal_harmonics)
Exemple #4
0
    def test_fit_alpha_only(self):
        alpha = 0.7
        np.random.seed(345)
        T = 200

        l = l0 = 0.2
        y = [0] * T
        for t in range(0, T):
            d = np.random.normal()
            y[t] = l + d
            l = l + alpha * d

        c = Components(use_arma_errors=False)
        p = ModelParams(c, alpha=alpha, x0=np.array([l0]))
        model = self.create_model(p)
        fitted_model = model.fit(y)
        resid = fitted_model.resid

        # Residuals should form a normal distribution
        _, pvalue = stats.normaltest(resid)
        assert 0.05 < pvalue  # large p-value, we can not reject null hypothesis of normal distribution

        # Mean of residuals should be close to 0
        _, pvalue = stats.ttest_1samp(resid, popmean=0.0)
        assert 0.05 < pvalue  # large p-value we can not reject null hypothesis that mean is 0

        # We expect 95% of residuals to lie within [-2,2] interval
        assert len(resid[np.where(np.abs(resid) < 2)]) / len(resid) > 0.90
Exemple #5
0
    def test_gamma(self, components, params, expected_gamma, expected_gamma_1, expected_gamma_2):
        c = Components(**components)
        p = ModelParams(c, **params)

        assert np.array_equal(expected_gamma, p.gamma_params)
        assert np.array_equal(expected_gamma_1, p.gamma_1())
        assert np.array_equal(expected_gamma_2, p.gamma_2())
Exemple #6
0
 def test_calculate_seed_x0(self, components, params, expected):
     y = [2.0, 4.0, 2.0]
     c = Components(**components)
     p = ModelParams(c, **params)
     m = ParamsOptimizer(self.context)
     x0 = m._calculate_seed_x0(y, p)
     assert np.allclose(expected, x0)
 def test_break_into_seasons(self, components, matrix, expected_break):
     components = Components(**components)
     matrix_obj = ComponentMatrix(matrix, components)
     seasons = matrix_obj.break_into_seasons()
     assert len(expected_break) == len(seasons)
     for i in range(0, len(expected_break)):
         assert np.array_equal(expected_break[i], seasons[i])
Exemple #8
0
    def test_optimization_with_seasonal_period(self):
        alpha = 0.7
        gamma1 = 0.1
        gamma2 = 0.05
        period_length = 4
        np.random.seed(2342)
        T = 200

        l = 0.2
        s = 1
        s_star = 0
        y = [0] * T
        lam = 2 * np.pi / period_length
        for t in range(0, T):
            d = np.random.normal()
            y[t] = l + s + d
            l = l + alpha * d
            s_prev = s
            s = s_prev * np.cos(lam) + s_star * np.sin(lam) + gamma1 * d
            s_star = - s_prev * np.sin(lam) + s_star * np.cos(lam) + gamma2 * d

        c = Components(use_arma_errors=False, seasonal_periods=[period_length], seasonal_harmonics=[1])
        initial_params = ModelParams(components=c, alpha=0.09, gamma_params=[0., 0.])

        optimizer = ParamsOptimizer(self.context)
        optimizer.optimize(y, initial_params)

        assert optimizer.converged()

        model = optimizer.optimal_model()

        assert np.isclose(alpha, model.params.alpha, atol=0.1)
        assert np.allclose([gamma1, gamma2], model.params.gamma_params, atol=0.1)
Exemple #9
0
    def test_forecast_confidence_intervals(self):

        T = 30
        steps = 5

        period_length = 6
        y = [0] * T
        b = b0 = 2.1
        l = l0 = 1.2
        alpha = 0.5
        beta = 0.2
        np.random.seed(3433)
        for t in range(0, T):
            d = np.random.normal()
            y[t] = l + b + d
            l = l + b + alpha * d
            b = b + beta * d

        c = Components(use_arma_errors=False,
                       use_trend=True,
                       use_damped_trend=False,
                       use_box_cox=False)
        p = ModelParams(c, alpha=0.5, beta=0.2, x0=[1.2, 2.1])
        model = self.create_model(p)
        model = model.fit(y)
        forecasts, confidence_info = model.forecast(steps=4,
                                                    confidence_level=0.95)
        assert 0.95 == confidence_info['calculated_for_level']
        assert np.array_equal(forecasts, confidence_info['mean'])
        assert np.allclose([59.46379894, 60.44336595, 61.290095, 62.02915299],
                           confidence_info['lower_bound'])
        assert np.allclose([62.99372071, 64.75218458, 66.64348641, 68.6424593],
                           confidence_info['upper_bound'])
 def test_part_split(self, components, matrix, expected_alpha_beta,
                     expected_seasonal, expected_arma):
     components = Components(**components)
     matrix_obj = ComponentMatrix(matrix, components)
     assert np.array_equal(expected_alpha_beta,
                           matrix_obj.alpha_beta_part())
     assert np.array_equal(expected_seasonal, matrix_obj.seasonal_part())
     assert np.array_equal(expected_arma, matrix_obj.arma_part())
Exemple #11
0
    def test_fit_predict_trigonometric_seasonal(self, seasonal_periods,
                                                seasonal_harmonics,
                                                starting_values):
        """
        The aim of the test is to check if model is correctly calculating trigonometric series with no noise.
        """
        T = 60
        steps = 10
        l = 3.1
        x0 = [[l]]

        # construct trigonometric series
        y = [l] * T
        for period in range(0, len(seasonal_periods)):
            period_length = seasonal_periods[period]
            period_harmonics = seasonal_harmonics[period]
            s_harmonic = np.array(starting_values[period])
            s = s_harmonic[:int(len(s_harmonic) / 2)]
            s_star = s_harmonic[int(len(s_harmonic) / 2):]
            x0.append(s_harmonic)
            lambdas = 2 * np.pi * (np.arange(
                1, period_harmonics + 1)) / period_length
            # add periodic impact to y
            for t in range(0, T):
                y[t] += np.sum(s)
                s_prev = s
                s = s_prev * np.cos(lambdas) + s_star * np.sin(lambdas)
                s_star = -s_prev * np.sin(lambdas) + s_star * np.cos(lambdas)

        x0 = np.concatenate(x0)

        y_to_fit = y[:(T - steps)]
        y_to_predict = y[(T - steps):]

        c = Components(use_arma_errors=False,
                       seasonal_periods=seasonal_periods,
                       seasonal_harmonics=seasonal_harmonics)
        p = ModelParams(
            c, alpha=0.0,
            x0=np.array(x0))  # gamma_params initialize to zeros here
        model = self.create_model(p)
        fitted_model = model.fit(y_to_fit)
        resid = fitted_model.resid

        # sequence should be modelled perfectly
        assert np.allclose([0] * (T - steps), resid)
        assert np.allclose(y_to_fit, fitted_model.y_hat)

        # forecast should be perfect
        y_predicted = fitted_model.forecast(steps=steps)
        assert np.allclose(y_to_predict, y_predicted)
Exemple #12
0
    def test_trend_and_seasonal(self):
        T = 30
        steps = 5

        phi = 0.99
        period_length = 6
        y = [0] * T
        b = b0 = 2.1
        l = l0 = 1.2
        s = s0 = 0
        s_star = s0_star = 0.2
        for t in range(0, T):
            y[t] = l + phi * b + s
            l = l + phi * b
            b = phi * b
            lam = 2 * np.pi / period_length
            s_prev = s
            s = s_prev * np.cos(lam) + s_star * np.sin(lam)
            s_star = -s_prev * np.sin(lam) + s_star * np.cos(lam)

        y_to_fit = y[:(T - steps)]
        y_to_predict = y[(T - steps):]

        c = Components(use_arma_errors=False,
                       use_trend=True,
                       use_damped_trend=True,
                       seasonal_periods=[period_length],
                       seasonal_harmonics=[1])
        p = ModelParams(
            c,
            phi=phi,
            # alpha, beta, gamma_params do not matter in this case as there is no noise
            alpha=0,
            beta=0,
            gamma_params=[0, 0],
            x0=np.array([l0, b0, s0, s0_star]))
        model = self.create_model(p)
        fitted_model = model.fit(y_to_fit)
        resid = fitted_model.resid

        # sequence should be modelled perfectly
        assert np.allclose([0] * (T - steps), resid)
        assert np.allclose(y_to_fit, fitted_model.y_hat)

        # forecast should be perfect
        y_predicted = fitted_model.forecast(steps=steps)
        assert np.allclose(y_to_predict, y_predicted)
Exemple #13
0
    def test_fit_alpha_and_trigonometric_series(self):
        alpha = 0.7
        gamma1 = 0.1
        gamma2 = 0.05
        period_length = 4
        np.random.seed(2342)
        T = 300

        l = l0 = 0.2
        s = s0 = 1
        s_star = s0_star = 0
        y = [0] * T
        lam = 2 * np.pi / period_length
        for t in range(0, T):
            d = np.random.normal()
            y[t] = l + s + d
            l = l + alpha * d
            s_prev = s
            s = s_prev * np.cos(lam) + s_star * np.sin(lam) + gamma1 * d
            s_star = -s_prev * np.sin(lam) + s_star * np.cos(lam) + gamma2 * d

        c = Components(use_arma_errors=False,
                       seasonal_periods=[period_length],
                       seasonal_harmonics=[1])
        p = ModelParams(
            c,
            alpha=alpha,  # gamma_params=[gamma1, gamma2],
            x0=np.array([l0, s0, s0_star]))
        model = self.create_model(p)
        fitted_model = model.fit(y)
        resid = fitted_model.resid

        # Residuals should form a normal distribution
        _, pvalue = stats.normaltest(resid)
        assert 0.05 < pvalue  # large p-value, we can not reject null hypothesis of normal distribution

        # Mean of residuals should be close to 0
        _, pvalue = stats.ttest_1samp(resid, popmean=0.0)
        assert 0.05 < pvalue  # large p-value we can not reject null hypothesis that mean is 0

        # We expect 95% of residuals to lie within [-2,2] interval
        # 0.8 - lets choose something that expected 0.95 will meet
        assert len(resid[np.where(np.abs(resid) < 2)]) / len(resid) > 0.80
Exemple #14
0
    def test_optimization_with_2_seasonal_periods(self):
        alpha = 0.4
        gamma = 0.05
        period1_length = 4
        period2_length = 12
        np.random.seed(2342)
        T = 200

        l = 0.2
        s1 = 1
        s1_star = 0
        s2 = 0
        s2_star = 1
        y = [0] * T
        lam1 = 2 * np.pi / period1_length
        lam2 = 2 * np.pi / period2_length
        for t in range(0, T):
            d = np.random.normal()
            y[t] = l + s1 + s2 + d
            l = l + alpha * d

            s1_prev = s1
            s1 = s1_prev * np.cos(lam1) + s1_star * np.sin(lam1) + gamma * d
            s1_star = - s1_prev * np.sin(lam1) + s1_star * np.cos(lam1)

            s2_prev = s2
            s2 = s2_prev * np.cos(lam2) + s2_star * np.sin(lam2)
            s2_star = - s2_prev * np.sin(lam2) + s2_star * np.cos(lam2)

        c = Components(use_arma_errors=False,
                       seasonal_periods=[period1_length, period2_length], seasonal_harmonics=[1, 1])
        initial_params = ModelParams(components=c, alpha=0.09, gamma_params=[0., 0., 0., 0.])

        optimizer = ParamsOptimizer(self.context)
        optimizer.optimize(y, initial_params)

        assert optimizer.converged()

        model = optimizer.optimal_model()

        assert np.isclose(alpha, model.params.alpha, atol=0.1)
        assert np.allclose([gamma, 0., 0., 0.], model.params.gamma_params, atol=0.25)
Exemple #15
0
 def test_make_vector(self, components, params, expected_w, expected_g):
     m = MatrixBuilder(ModelParams(Components(**components), **params))
     assert np.array_equal(expected_w, m.make_w_vector())
     assert np.array_equal(expected_g, m.make_g_vector())
Exemple #16
0
 def test_make_F_matrix(self, components, params, expected_matrix):
     m = MatrixBuilder(ModelParams(Components(**components), **params))
     F = m.make_F_matrix()
     assert np.allclose(expected_matrix, F)
Exemple #17
0
 def test_make_gamma_vector(self, components, params, expected_gamma):
     m = MatrixBuilder(
         ModelParams(components=Components(**components), **params))
     assert np.array_equal(expected_gamma, m.make_gamma_vector())
 def create_case(self, **components):
     return Case(Components(**components), Context())
 def test_choose(self, components, aic_score_map, expected_harmonics):
     context = self.ContextMock(aic_score_map)
     strategy = HarmonicsChoosingStrategy(context, checking_range=1)
     harmonics = strategy.choose([1, 2, 3], Components(**components))
     assert np.array_equal(expected_harmonics, harmonics)