Prophet › Implementation in Prophet

Michael BrenndoerferAugust 5, 202510 min read
Machine Learning from ScratchAll chapters
Part 8 of 9Time Series
Chapter 59Prophet › Implementation in Prophet
Reading section 5 of 8 · Implementation in Prophet · 10 minSection 5 of 8 · 10 min

Book contents

Section 5 of 8 · 10 min read

Prophet › Implementation in ProphetOne section · Sections in this chapter5 / 8 ↓
Reading tools Definitions & inline links

Choose your expertise level to adjust how many terms are explained. Beginners see more tooltips, experts see fewer to maintain reading flow. Hover over underlined terms for instant definitions.

Article links

Make inline references clickable

Prophet provides a straightforward Python API that makes time series forecasting accessible. Let's implement a complete forecasting workflow using the Prophet library.

Framework Selection:

We use the Prophet library because it's specifically designed for time series forecasting with an intuitive API, automatic parameter tuning, and built-in visualization capabilities. Prophet abstracts away the statistical complexity while providing the flexibility to customize the model when needed.

In[12]:
Code
import warnings
from datetime import datetime

import numpy as np
import pandas as pd

warnings.filterwarnings("ignore")

# Load or create time series data
# For this example, we'll create realistic e-commerce sales data
np.random.seed(42)

# Create daily sales data for 2 years
start_date = datetime(2022, 1, 1)
end_date = datetime(2023, 12, 31)
dates = pd.date_range(start=start_date, end=end_date, freq="D")

# Generate realistic sales data with multiple components
sales_data = []
for i, date in enumerate(dates):
    # Base trend: gradual growth
    trend = 1000 + 2 * i

    # Weekly seasonality: higher on weekends
    day_of_week = date.weekday()
    weekly_seasonal = 200 * np.sin(2 * np.pi * day_of_week / 7)

    # Yearly seasonality: peak in December, dip in January
    day_of_year = date.timetuple().tm_yday
    yearly_seasonal = 300 * np.sin(2 * np.pi * day_of_year / 365.25)

    # Holiday effects
    holiday_effect = 0
    if date.month == 12 and date.day == 25:  # Christmas
        holiday_effect = 500
    elif date.month == 11 and date.day == 24:  # Black Friday
        holiday_effect = 400

    # Random noise
    noise = np.random.normal(0, 50)

    # Total sales
    total_sales = (
        trend + weekly_seasonal + yearly_seasonal + holiday_effect + noise
    )
    sales_data.append(max(0, total_sales))  # Ensure non-negative sales

# Create DataFrame in Prophet format
df = pd.DataFrame({"ds": dates, "y": sales_data})

print("Sample of our e-commerce sales data:")
print(df.head(10))
print("\nData summary:")
print(f"Date range: {df['ds'].min()} to {df['ds'].max()}")
print(f"Mean daily sales: ${df['y'].mean():.2f}")
print(f"Sales standard deviation: ${df['y'].std():.2f}")
Out[13]:
Console
Sample of our e-commerce sales data:
          ds            y
0 2022-01-01   835.010598
1 2022-01-02   849.039907
2 2022-01-03  1051.859737
3 2022-01-04  1259.144412
4 2022-01-05  1217.049745
5 2022-01-06  1115.979314
6 2022-01-07  1040.221743
7 2022-01-08   898.541775
8 2022-01-09   882.421198
9 2022-01-10  1096.481120

Data summary:
Date range: 2022-01-01 00:00:00 to 2023-12-31 00:00:00
Mean daily sales: $1730.28
Sales standard deviation: $419.37

Our dataset contains 730 days of daily sales data spanning two years. The mean daily sales of approximately $1,730 with a standard deviation of about $350 indicates moderate variability around the trend. This level of variation is typical for e-commerce data where daily fluctuations are expected, but the overall trend and seasonal patterns should be learnable by Prophet.

Now let's implement the Prophet model with proper configuration:

In[14]:
Code
# Initialize Prophet model with custom parameters
model = Prophet(
    # Seasonality settings
    yearly_seasonality=True,  # Enable yearly patterns
    weekly_seasonality=True,  # Enable weekly patterns
    daily_seasonality=False,  # Disable daily (we have daily data but want weekly patterns)
    # Trend flexibility
    changepoint_prior_scale=0.05,  # Lower = less flexible trend changes
    changepoint_range=0.8,  # Proportion of data to consider for changepoints
    # Seasonality strength
    seasonality_prior_scale=10.0,  # Higher = more flexible seasonality
    seasonality_mode="additive",  # Additive seasonality (default)
    # Uncertainty intervals
    interval_width=0.95,  # 95% confidence intervals
    mcmc_samples=0,  # Use MAP estimation (faster than MCMC)
)

# Add custom holidays
holidays = pd.DataFrame(
    {
        "holiday": [
            "christmas",
            "new_year",
            "black_friday",
            "christmas",
            "new_year",
        ],
        "ds": pd.to_datetime(
            [
                "2022-12-25",
                "2023-01-01",
                "2023-11-24",
                "2023-12-25",
                "2024-01-01",
            ]
        ),
        "lower_window": [-1, -1, -1, -1, -1],  # Effect starts 1 day before
        "upper_window": [1, 1, 1, 1, 1],  # Effect ends 1 day after
    }
)

model.add_country_holidays(country_name="US")  # Add US holidays
model.add_seasonality(
    name="monthly", period=30.5, fourier_order=5
)  # Custom monthly seasonality

# Fit the model
print("Fitting Prophet model...")
model.fit(df)
print("Model fitting completed!")
Out[15]:
Console
Fitting Prophet model...
Model fitting completed!

The model has successfully fitted to our data. Prophet has learned the trend, weekly seasonality, yearly seasonality, monthly patterns, and holiday effects from the historical sales data. The fitting process uses Bayesian inference to estimate all parameters, which typically completes in a few seconds for datasets of this size.

Now let's make forecasts and analyze the results:

In[16]:
Code
# Create future dataframe for forecasting
future = model.make_future_dataframe(
    periods=90, freq="D"
)  # Forecast 90 days ahead

# Make predictions
forecast = model.predict(future)

# Display forecast summary
print("Forecast Summary:")
print(f"Forecast period: {future['ds'].min()} to {future['ds'].max()}")
print(f"Number of future periods: {len(future) - len(df)}")
print(f"Mean predicted sales: ${forecast['yhat'].mean():.2f}")
print(f"Forecast uncertainty (std): ${forecast['yhat'].std():.2f}")

# Show last few predictions
print("\nLast 10 forecasted values:")
print(forecast[["ds", "yhat", "yhat_lower", "yhat_upper"]].tail(10))
Out[17]:
Console
Forecast Summary:
Forecast period: 2022-01-01 00:00:00 to 2024-03-30 00:00:00
Number of future periods: 90
Mean predicted sales: $1840.44
Forecast uncertainty (std): $507.00

Last 10 forecasted values:
            ds         yhat   yhat_lower   yhat_upper
810 2024-03-21  2972.696881  2871.126845  3067.132860
811 2024-03-22  2796.113255  2701.196403  2898.423580
812 2024-03-23  2697.933289  2598.498186  2795.003799
813 2024-03-24  2753.401189  2644.693233  2855.981746
814 2024-03-25  2913.525864  2813.181167  3003.714214
815 2024-03-26  3078.671859  2979.326781  3183.335892
816 2024-03-27  3107.937859  3009.645537  3207.124403
817 2024-03-28  3005.476061  2903.946376  3104.973919
818 2024-03-29  2826.216029  2723.305132  2930.047737
819 2024-03-30  2720.958837  2625.261519  2810.988038

The forecast extends 90 days into the future. The mean predicted sales value combines the projected trend with recurring seasonal patterns and holiday effects. The forecast uncertainty, measured by the standard deviation of predictions, indicates how confident the model is in its forecasts. Higher uncertainty typically occurs during periods with less historical data or greater variability.

The last 10 forecasted values show both point predictions (yhat) and uncertainty intervals (yhat_lower and yhat_upper). These intervals represent the 95% confidence range, meaning we expect the actual values to fall within this range 95% of the time. Wider intervals indicate higher uncertainty, which is normal when forecasting further into the future.

Let's visualize our Prophet model:

Out[18]:
Visualization
Time series forecast plot showing Prophet predictions with confidence intervals for e-commerce sales data.
Complete Prophet forecast visualization showing the original observations, fitted values, and future predictions with confidence intervals. The plot demonstrates Prophet's ability to capture trend, seasonality, and holiday effects in e-commerce sales data.
Out[19]:
Visualization
Five-panel plot showing Prophet decomposition into trend, holiday effects, weekly seasonality, yearly seasonality, and monthly seasonality.
Prophet component decomposition showing trend, holiday effects, weekly seasonality, yearly seasonality, and monthly seasonality. This visualization helps explain what drives the forecasts and identify potential modeling issues.

Alternative Implementation: Manual Parameter Tuning

For advanced users who want more control over the model, here's how to manually tune Prophet parameters:

In[20]:
Code
# Advanced Prophet configuration with manual tuning
advanced_model = Prophet(
    # Trend parameters
    growth="linear",  # Use linear growth (vs 'logistic')
    changepoint_prior_scale=0.01,  # Very conservative changepoints
    changepoint_range=0.9,  # Use 90% of data for changepoint detection
    # Seasonality parameters
    yearly_seasonality=True,
    weekly_seasonality=True,
    daily_seasonality=False,
    seasonality_prior_scale=20.0,  # More flexible seasonality
    seasonality_mode="additive",  # Additive (vs 'multiplicative')
    # Holiday parameters
    holidays_prior_scale=10.0,  # Holiday effect strength
    # Uncertainty
    interval_width=0.8,  # 80% confidence intervals
    mcmc_samples=100,  # Use MCMC for uncertainty (slower but more accurate)
)

# Add custom seasonalities
advanced_model.add_seasonality(
    name="quarterly",
    period=91.25,  # ~3 months
    fourier_order=8,  # More complex quarterly patterns
    prior_scale=15.0,
)

# Add custom regressors (external variables)
# Note: This would require additional data columns
# advanced_model.add_regressor('marketing_spend', prior_scale=0.5)

# Fit the advanced model
print("Fitting advanced Prophet model with manual tuning...")
advanced_model.fit(df)
print("Advanced model fitting completed!")

# Make forecast with advanced model
advanced_future = advanced_model.make_future_dataframe(periods=90, freq="D")
advanced_forecast = advanced_model.predict(advanced_future)

print(f"Advanced model forecast mean: ${advanced_forecast['yhat'].mean():.2f}")
print(f"Standard model forecast mean: ${forecast['yhat'].mean():.2f}")
Out[21]:
Console
Fitting advanced Prophet model with manual tuning...
Advanced model fitting completed!
Advanced model forecast mean: $1840.86
Standard model forecast mean: $1840.44

The advanced model uses more conservative changepoint settings and MCMC sampling for uncertainty estimation, which provides more accurate uncertainty intervals at the cost of longer computation time. Comparing the forecast means between the standard and advanced models helps assess sensitivity to parameter choices. Similar means indicate that these parameter variations have little effect on the forecasts.

Key Parameters

Below are some of the main parameters that affect how Prophet works and performs.

  • yearly_seasonality: Enable or disable yearly seasonal patterns (default: 'auto'). Set to True for yearly data, False to disable, or 'auto' to let Prophet decide based on data frequency.

  • weekly_seasonality: Enable or disable weekly seasonal patterns (default: 'auto'). Useful for daily data with day-of-week effects. Set to False for monthly or yearly data.

  • daily_seasonality: Enable or disable daily seasonal patterns (default: 'auto'). Typically only needed for sub-daily data (hourly, etc.).

  • changepoint_prior_scale: Controls flexibility of trend changes (default: 0.05). Lower values (0.01-0.05) create stable trends, higher values (0.1-0.5) allow more adaptation. Start with 0.05 and adjust based on how much your trend changes.

  • changepoint_range: Proportion of data to consider for changepoints (default: 0.8). Values of 0.8-0.9 work well for most cases, excluding the most recent data from changepoint detection.

  • seasonality_prior_scale: Controls strength of seasonal patterns (default: 10.0). Increase (15-20) for strong, consistent seasonality. Decrease (5-8) for weak or noisy seasonal patterns.

  • seasonality_mode: Type of seasonality (default: 'additive'). Use 'additive' when seasonal effects are constant regardless of trend level. Use 'multiplicative' when seasonal effects scale with the trend.

  • holidays_prior_scale: Controls strength of holiday effects (default: 10.0). Increase for holidays with large impacts, decrease if holiday effects are subtle.

  • interval_width: Width of uncertainty intervals (default: 0.80 for 80% intervals). Set to 0.95 for 95% intervals, which are wider but more conservative.

  • mcmc_samples: Number of MCMC samples for uncertainty (default: 0, uses MAP). Set to 100-1000 for more accurate uncertainty intervals, but expect 10-100x slower fitting.

Key Methods

The following are the most commonly used methods for interacting with Prophet models.

  • fit(df): Trains the Prophet model on historical data. The DataFrame df should have columns 'ds' (dates) and 'y' (values). Returns the fitted model object.

  • predict(df): Generates forecasts for the dates in df. The DataFrame should have a 'ds' column with future dates. Returns a DataFrame with predictions (yhat) and uncertainty intervals (yhat_lower, yhat_upper).

  • make_future_dataframe(periods, freq): Creates a DataFrame with historical dates plus future periods for forecasting. periods is the number of future periods, freq is the frequency ('D' for daily, 'M' for monthly, etc.).

  • plot(forecast): Creates a visualization of the forecast showing historical data, fitted values, and future predictions with uncertainty intervals.

  • plot_components(forecast): Creates a decomposition plot that separates the trend from seasonal and holiday effects.

  • add_country_holidays(country_name): Adds built-in holidays for a specific country (e.g., 'US', 'UK', 'CN'). Prophet includes holiday calendars for many countries.

  • add_seasonality(name, period, fourier_order, prior_scale): Adds a custom seasonal pattern. Useful for quarterly patterns, bi-weekly patterns, or other non-standard seasonalities.

  • add_regressor(name, prior_scale): Adds an external regressor (additional predictor variable). Requires the regressor values to be included in both training and future DataFrames.