facebook / prophet

Tool for producing high quality forecasts for time series data that has multiple seasonality with linear or non-linear growth.
https://facebook.github.io/prophet
MIT License
18.48k stars 4.53k forks source link

ANNOUNCEMENT: v0.3 released #563

Closed bletham closed 5 years ago

bletham commented 6 years ago

v0.3 Release Notes

We have just pushed v0.3 to CRAN and PyPI. A big thanks to all of the contributers, both to the code and to resolving issues. There are several notable new features in this version:

Under the hood, there have been some changes that will improve performance:

And, of course, bug fixes and many documentation updates.

For typical usage, v0.3 will continue to work in exactly the same way as v0.2. These new features do, however, come with some changes to function outputs that will be relevant to some users. Changes that alter the way v0.3 behaves relative to v0.2 are now described in detail.

Multiplicative seasonality

Changes to the model

Previously the Prophet model was y(t) = trend(t) + X(t) beta, where X(t) beta is the linear part of the model that includes seasonality, holiday effects, and extra regressors. The model has been extended to be y(t) = trend(t) * (1 + X_m(t) beta_m) + X_a(t) beta_a. Seasonalities and regressors can be included in either the multiplicative component (X_m(t) beta_m) or the additive component (X_a(t) beta_a).

Changes to outputs

The outputs to some exported methods/functions have changed due to this new feature.

Internally, the inputs and ouputs to a number of not-exported functions/methods have changed, so any code that directly accessed internal functions may be broken.

Changes to model attributes

The model attributes have changed in several places. Models that were created with an older version of Prophet and exported via pickle or SaveRDS will not work with the new version of Prophet.

Trend uncertainty improvements

Uncertainty intervals for the future trend are created by simulating future changepoints in the trend. In Prophet v0.1, the model was limited to daily data and so this was done by computing the probability that a day in the history had a changepoint (p), and then for each future day, inserting a changepoint with probability p. Support for sub-daily data was added in v0.2, and this process for selecting future changepoints was adapted by first computing the smallest discretization for the data, and then doing the same thing but at that discretization instead of at the level of a day. This does not work for irregular data that have a mixture of very small inter-point intervals and very large inter-point intervals. As the time discretization goes to 0, this process is asymptotically equivalent to a Poisson process, so in v0.3 the process was switched entirely to generate future changepoints from a Poisson process whose rate matches the rate of changepoints in the history.

This will dramatically improve performance for sub-daily data with irregular spacing. The Poisson process becomes indistinguishable from the previous Bernoulli process with a relatively small amount of data, so this change is not expected to change the outputs of the forecast in most situations. For very short time series, there may be changes to the trend uncertainty interval (and thus yhat confidence interval as well).

Changes in cross validation

Prophet previously had two exported functions for cross validation: cross_validation, which specified a horizon, period, and initial window; and simulated_historical_forecasts, which specified a horizon, period, and number of simulated forecasts. The cross_validation function was the only one described in the documentation.

For irregularly spaced data, it can be difficult to know how many simulated forecasts a particular time series can actually support, since there may be gaps larger than the horizon. The cross_validation interface thus seems more generally convenient, and so to simplify things the simulated_historical_forecasts function was removed.

Previously, cross_validation could sometimes return cutoffs inside the initial window if there were gaps in the data larger than the horizon. Cutoff dates will now always respect the initial window, which may result in changes to the set of cutoffs in the results returned by cross_validation relative to the previous version.

Refactoring plotting code

Previously all of the plotting functionality in Python was accessed via methods of the Prophet class. The primary two plotting functions (Prophet.plot and Prophet.plot_components) will remain as class methods, but the remaining functions (plot_trend, plot_weekly, etc.) have been moved to a separate module, fbprophet.plot. For now the methods have also been kept but will raise a deprecation warning. Anyone accessing these plotting methods (besides the primary two previously mentioned) should switch to importing from the new module before the next version, when the methods will be removed entirely.

Pandas version requirement

To avoid a bug in how certain versions of pandas and numpy handle datetime objects, the minimum pandas requirement was increased from 0.18.1 to 0.20.1. See #256 for more details about the issue.

brylie commented 6 years ago

FWIW, I had a really difficult time upgrading a conda/pip environment from fbprophet 0.2.1 to 0.3, as it seemed to have installed conflicting or broken versions of pandas and numpy.

In the end, I have taken a rather brute-force approach, removing all pip packages and numpy from conda dependencies, then using conda install fbprophet to install 0.3. I assume this comes from conda-forge.

Did anyone else have similar difficulties with the upgrade? Was there a simpler way to upgrade/resolve the dependencies issue?

brylie commented 6 years ago

UPDATE: it turns out that 0.3 is not available to install via conda-forge, so I am back at fbprophet=0.2.1=py36_0. Darn! I was really hoping to try out the multiplicative seasonality :-)

https://github.com/conda-forge/fbprophet-feedstock/issues/12

brylie commented 6 years ago

On the conda-forge fbprophet 0.3 pull request, there are tests breaking. Spicifically m.make_holiday_features seems to have changed the order of the priors output. Was this documented/intentional?

lib/python3.6/site-packages/fbprophet/tests/test_prophet.py FAILED [ 70%]

__________________________ TestProphet.test_holidays ___________________________

self = <fbprophet.tests.test_prophet.TestProphet testMethod=test_holidays>

    def test_holidays(self):
        holidays = pd.DataFrame({
            'ds': pd.to_datetime(['2016-12-25']),
            'holiday': ['xmas'],
            'lower_window': [-1],
            'upper_window': [0],
        })
        model = Prophet(holidays=holidays)
        df = pd.DataFrame({
            'ds': pd.date_range('2016-12-20', '2016-12-31')
        })
        feats, priors, names = model.make_holiday_features(df['ds'])
        # 11 columns generated even though only 8 overlap
        self.assertEqual(feats.shape, (df.shape[0], 2))
        self.assertEqual((feats.sum(0) - np.array([1.0, 1.0])).sum(), 0)
        self.assertEqual(priors, [10., 10.])  # Default prior
        self.assertEqual(names, ['xmas'])

        holidays = pd.DataFrame({
            'ds': pd.to_datetime(['2016-12-25']),
            'holiday': ['xmas'],
            'lower_window': [-1],
            'upper_window': [10],
        })
        m = Prophet(holidays=holidays)
        feats, priors, names = m.make_holiday_features(df['ds'])
        # 12 columns generated even though only 8 overlap
        self.assertEqual(feats.shape, (df.shape[0], 12))
        self.assertEqual(priors, list(10. * np.ones(12)))
        self.assertEqual(names, ['xmas'])
        # Check prior specifications
        holidays = pd.DataFrame({
            'ds': pd.to_datetime(['2016-12-25', '2017-12-25']),
            'holiday': ['xmas', 'xmas'],
            'lower_window': [-1, -1],
            'upper_window': [0, 0],
            'prior_scale': [5., 5.],
        })
        m = Prophet(holidays=holidays)
        feats, priors, names = m.make_holiday_features(df['ds'])
        self.assertEqual(priors, [5., 5.])
        self.assertEqual(names, ['xmas'])
        # 2 different priors
        holidays2 = pd.DataFrame({
            'ds': pd.to_datetime(['2012-06-06', '2013-06-06']),
            'holiday': ['seans-bday'] * 2,
            'lower_window': [0] * 2,
            'upper_window': [1] * 2,
            'prior_scale': [8] * 2,
        })
        holidays2 = pd.concat((holidays, holidays2))
        m = Prophet(holidays=holidays2)
        feats, priors, names = m.make_holiday_features(df['ds'])
>       self.assertEqual(priors, [8., 8., 5., 5.])
E       AssertionError: Lists differ: [5.0, 5.0, 8.0, 8.0] != [8.0, 8.0, 5.0, 5.0]
bletham commented 6 years ago

Yes, the issue there was just with the unit test and due to the new sorted dictionaries in Python 3.6. The unit test was fixed in a5869505c0b840a546d89c169763d36ef8414a4e and we're pushing it out to PyPI now, so it should reach conda forge soon.

Kandekwe commented 6 years ago

hey Bletham,

thanks for the great work, i am using fbprophet but i encountered this error : from fbprophet.diagnostics import performance_metrics from fbprophet.diagnostics import performance_metrics

ImportError Traceback (most recent call last)

in () ----> 1 from fbprophet.diagnostics import performance_metrics ImportError: cannot import name 'performance_metrics' i wonder what is the reason behind yet i had everything working properly, would you give me a suggestion on that? Thanks.
bletham commented 6 years ago

@Kandekwe it looks like you don't have v0.3 installed, can you check

import fbprophet
fbprophet.__version__

Try re-installing from pip, with pip install --upgrade fbprophet

Kandekwe commented 6 years ago

I got what was the issue.

Thanks

Kandekwe commented 6 years ago

Exactly, I had v0.2.

Thanks