示例#1
0
def test_prediction_no_seasonality(sample_data):
    '''
        Test that predictions without seasonality
        can be done, and that the trend is close to
        predictions since without seasonality
        only the distribution parameters should
        modify the predictions
    '''
    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
        if (distribution not in [
                chronos_utils.Poisson_dist_code,
                chronos_utils.HalfNormal_dist_code
        ]):
            # Poisson and half-normal produes very strange results here
            my_chronos = Chronos(n_changepoints=6,
                                 max_iter=100,
                                 distribution=distribution,
                                 year_seasonality_order=0,
                                 month_seasonality_order=0,
                                 weekly_seasonality_order=0)
            my_chronos.fit(sample_data)

            predictions = my_chronos.predict(sample_number=2000,
                                             period=30,
                                             frequency='D')

            assert (np.mean(np.abs(predictions['yhat'] - predictions['trend']))
                    <= 0.1)
示例#2
0
def test_basic_creation():
    '''
        Test that the class can be created using both MLE and MAP methods
    '''
    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
        my_chronos = Chronos(distribution=distribution)
        my_chronos = Chronos(method="MAP", distribution=distribution)
        my_chronos = Chronos(method="MLE", distribution=distribution)
示例#3
0
def test_bad_changepoint_number():
    my_chronos = Chronos(n_changepoints=5)

    with pytest.raises(ValueError):
        my_chronos = Chronos(n_changepoints=-5)

    for value in [5.3, "hello", True, None]:
        with pytest.raises(TypeError):
            my_chronos = Chronos(n_changepoints=value)
示例#4
0
def test_bad_weekly_seasonality_order():
    my_chronos = Chronos(weekly_seasonality_order=5)

    with pytest.raises(ValueError):
        my_chronos = Chronos(weekly_seasonality_order=-5)

    for value in [5.3, "hello", True, None]:
        with pytest.raises(TypeError):
            my_chronos = Chronos(weekly_seasonality_order=value)
示例#5
0
def test_bad_changepoint_scale():
    my_chronos = Chronos(changepoint_prior_scale=0.6)

    with pytest.raises(ValueError):
        my_chronos = Chronos(changepoint_prior_scale=-0.3)

    with pytest.raises(ValueError):
        my_chronos = Chronos(changepoint_prior_scale=0.0)

    for value in ["hello", True, False, None]:
        with pytest.raises(TypeError):
            my_chronos = Chronos(changepoint_prior_scale=value)
示例#6
0
def test_bad_learning_rate():
    my_chronos = Chronos(learning_rate=0.3)

    with pytest.raises(ValueError):
        my_chronos = Chronos(learning_rate=-0.3)

    with pytest.raises(ValueError):
        my_chronos = Chronos(learning_rate=0.0)

    with pytest.raises(ValueError):
        my_chronos = Chronos(learning_rate=-0.0)

    for value in ["hello", True, False, None]:
        with pytest.raises(TypeError):
            my_chronos = Chronos(learning_rate=value)
示例#7
0
def test_bad_distribution():
    my_chronos = Chronos(distribution="Normal")

    with pytest.raises(ValueError):
        my_chronos = Chronos(distribution="Bla")

    with pytest.raises(ValueError):
        my_chronos = Chronos(distribution="normal")

    with pytest.raises(ValueError):
        my_chronos = Chronos(distribution="student")

    for value in [3, 5.7, True, False, None]:
        with pytest.raises(TypeError):
            my_chronos = Chronos(distribution=value)
示例#8
0
def test_bad_seasonality_mode():
    for mode in ["add", "mul"]:
        my_chronos = Chronos(seasonality_mode=mode)

    with pytest.raises(ValueError):
        my_chronos = Chronos(seasonality_mode="moo")

    with pytest.raises(ValueError):
        my_chronos = Chronos(seasonality_mode="additive")

    with pytest.raises(ValueError):
        my_chronos = Chronos(seasonality_mode="multiplicative")

    for value in [3, 5.7, True, False, None]:
        with pytest.raises(TypeError):
            my_chronos = Chronos(seasonality_mode=value)
示例#9
0
def test_bad_method():
    with pytest.raises(ValueError):
        my_chronos = Chronos(method="BOO")

    with pytest.raises(ValueError):
        my_chronos = Chronos(method="map")

    with pytest.raises(ValueError):
        my_chronos = Chronos(method="mlo")

    with pytest.raises(ValueError):
        my_chronos = Chronos(method="mle")

    for value in [1, 5.4, True, False, None]:
        with pytest.raises(TypeError):
            my_chronos = Chronos(method=value)
示例#10
0
def test_prediction_no_changepoints(sample_data):
    '''
        Test that predictions work without
        changepoints and that fitting can 
        still be done
    '''
    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
        my_chronos = Chronos(n_changepoints=0,
                             distribution=distribution,
                             max_iter=100)
        my_chronos.fit(sample_data)

        predictions = my_chronos.predict(sample_number=2000,
                                         period=30,
                                         frequency='D')

        assert (my_chronos._Chronos__number_of_changepoints == 0)
示例#11
0
 def getFramework(self, request_uri):
     marathon_pattern = re.compile("^{}$".format("/marathon/.*"))
     marathon_check = marathon_pattern.match(request_uri)
     chronos_pattern = re.compile("^{}$".format("/chronos/.*"))
     chronos_check = chronos_pattern.match(request_uri)
     if marathon_check:
         return Marathon()
     elif chronos_check:
         return Chronos()
     else:
         return None
示例#12
0
def test_plotting_no_history(capsys, monkeypatch, sample_data):
    '''
        Test the plotting of data when no history is provided.
        This was an issue raised in issue #2.
    '''
    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
        my_chronos = Chronos(n_changepoints=0, max_iter=100, distribution=distribution)
        my_chronos.fit(sample_data)

        future_df = my_chronos.make_future_dataframe(include_history=False)
        predictions = my_chronos.predict(future_df)

        
        fig = plt.figure(figsize=(15,5))
        gs = gridspec.GridSpec(1,1, figure=fig)
        gs_section = gs[0,0]
        ax = fig.add_subplot(gs_section)

        #chronos_plotting.plot_predictions(predictions, my_chronos, fig=fig, gs_section=gs_section)
        chronos_plotting.plot_predictions(predictions, my_chronos, axs=ax)
        plt.savefig("test_prediction_no_history.png")

        std_error = capsys.readouterr().err
        assert(std_error == "")

    os.remove("test_prediction_no_history.png")
示例#13
0
def test_bad_max_iter():
    my_chronos = Chronos(max_iter=100)

    with pytest.raises(ValueError):
        my_chronos = Chronos(max_iter=-100)

    with pytest.raises(ValueError):
        my_chronos = Chronos(max_iter=0)

    for value in ["hello", 5.7, True, False, None]:
        with pytest.raises(TypeError):
            my_chronos = Chronos(max_iter=value)


######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
######################################################################
示例#14
0
def test_prediction_with_easy_extra_regressors(sample_data):
    '''
        Test that when the size of the data is too small, the
        number of changepoints gets adjusted
    '''

    z = sample_data.index.values
    y = 0.01 * z + np.sin(z / 30)
    sample_data['y'] = y

    # should be easy since the target is just dummy1 + dummy2
    dummy1 = 0.01 * z
    dummy2 = np.sin(z / 30)
    sample_data['dummy1'] = dummy1
    sample_data['dummy2'] = dummy2

    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:

        # Student t distribution has issues with the long tails
        if (distribution != chronos_utils.StudentT_dist_code):
            my_chronos = Chronos(max_iter=200, distribution=distribution)

            # add dummies
            my_chronos.add_regressors("dummy1")
            my_chronos.add_regressors("dummy2")

            my_chronos.fit(sample_data)

            future_df = my_chronos.make_future_dataframe()

            # Add dummies to future df
            z = future_df.index.values

            y = 0.01 * z + np.sin(z / 30)
            future_df['y'] = y

            dummy1 = 0.01 * z
            dummy2 = np.sin(z / 30)
            future_df['dummy1'] = dummy1
            future_df['dummy2'] = dummy2

            # Make predictions
            predictions = my_chronos.predict(future_df)

            # The predictions should be almost the same as the target
            assert (np.mean(np.abs(predictions['y'] - predictions['yhat'])) <
                    0.1)
示例#15
0
def test_predictions_not_nan(sample_data):
    '''
        Make sure no nans are returned during the prediction process
    '''
    for method in ["MAP", "MLE"]:
        for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
            my_chronos = Chronos(n_changepoints=0,
                                 max_iter=100,
                                 distribution=distribution,
                                 method=method)
            my_chronos.fit(sample_data)

            future_df = my_chronos.make_future_dataframe(include_history=False)
            predictions = my_chronos.predict(future_df)

            predictions.drop('y', axis=1, inplace=True)
            #print(predictions)

            assert (predictions.isna().sum().sum() == 0)
示例#16
0
def test_prediction_too_small_for_default_changepoints(sample_data):
    '''
        Test that when the size of the data is too small, the
        number of changepoints gets adjusted
    '''
    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
        my_chronos = Chronos(max_iter=100,
                             n_changepoints=20,
                             distribution=distribution)

        # This should raise a warning about the size of the data and changepoint number
        with pytest.warns(RuntimeWarning):
            my_chronos.fit(sample_data.iloc[:10])

        future_df = my_chronos.make_future_dataframe()
        predictions = my_chronos.predict(future_df)

        assert (my_chronos._Chronos__number_of_changepoints <
                sample_data.shape[0])
示例#17
0
def test_plotting(capsys, monkeypatch, sample_data):
    '''
        Test the plotting of data when no history is provided.
        This was an issue raised in issue #2.
    '''
    for distribution in chronos_utils.SUPPORTED_DISTRIBUTIONS:
        my_chronos = Chronos(n_changepoints=0, max_iter=100, distribution=distribution)
        my_chronos.fit(sample_data)

        future_df = my_chronos.make_future_dataframe(include_history=True)
        predictions = my_chronos.predict(future_df)


        with pytest.warns(UserWarning):
            chronos_plotting.plot_components(predictions, my_chronos, figure_name="test_prediction.png")

        std_error = capsys.readouterr().err
        assert(std_error == "")

    os.remove("test_prediction.png")
示例#18
0
def test_error_for_nan_values(sample_data):
    '''
        Tests that Chronos complains when given
        nan values to fit on, but not to predict on
    '''
    def add_dummy_regressors(data):

        z = data.index.values
        y = 0.01 * z + np.sin(z / 30)
        data['y'] = y

        # should be easy since the target is just dummy1 + dummy2
        dummy1 = 0.01 * z
        dummy2 = np.sin(z / 30)
        data['dummy1'] = dummy1
        data['dummy2'] = dummy2

        return data

    sample_data = add_dummy_regressors(sample_data)

    my_chronos = Chronos(max_iter=200)

    # add dummies
    my_chronos.add_regressors("dummy1")
    my_chronos.add_regressors("dummy2")

    # check nan values fail for all columns
    for col in ['ds', 'y', 'dummy1', 'dummy2']:
        sample_data_with_nans = sample_data.copy()
        sample_data_with_nans.loc[0, col] = np.nan

        with pytest.raises(ValueError):
            my_chronos.fit(sample_data_with_nans)

    # check original data works
    my_chronos.fit(sample_data)

    future_df = my_chronos.make_future_dataframe()
    future_df = add_dummy_regressors(future_df)

    # check nan values fail for all columns EXCEPT
    # the target column when making predictions
    for col in ['ds', 'y', 'dummy1', 'dummy2']:
        future_df_with_nans = future_df.copy()
        future_df_with_nans.loc[0, col] = np.nan
        if (col == 'y'):
            predictions = my_chronos.predict(future_df_with_nans)
        else:
            with pytest.raises(ValueError):
                predictions = my_chronos.predict(future_df_with_nans)
示例#19
0
def test_predictions_with_additional_regressors(sample_data):
    '''
        TODO: update
    '''

    my_chronos = Chronos(n_changepoints=0, max_iter=100)
    my_chronos.add_regressors("reg1", "mul")
    my_chronos.add_regressors("reg2", "mul")

    # Check not including the regressor throws an error
    with pytest.raises(KeyError):
        my_chronos.fit(sample_data)

    # Now check with the regressor
    sample_data['reg1'] = [1] * sample_data.shape[0]
    sample_data['reg2'] = [1] * sample_data.shape[0]
    my_chronos.fit(sample_data)

    future_df = my_chronos.make_future_dataframe(include_history=False)

    # Check not including the regressor throws an error
    with pytest.raises(KeyError):
        predictions = my_chronos.predict(future_df)

    # Now check with the regressor
    future_df['reg1'] = [1] * future_df.shape[0]
    future_df['reg2'] = [1] * future_df.shape[0]
    predictions = my_chronos.predict(future_df)

    predictions.drop('y', axis=1, inplace=True)

    assert (predictions.isna().sum().sum() == 0)