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)
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)
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")
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)
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)
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)
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)
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])
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")