Skip to main content

Bayesian time‑series model with Beta/Gaussian heads, smooth changepoints and seasonality

Project description

📈 Murphet — Prophet's (0-1) Cousin for Probabilities & Rates

PyPI version Python License: MIT

A Stan-powered time-series model that never breaks the 0 - 1 bounds and still feels like Prophet.


1 · Why Murphet?

Problem with vanilla Prophet How Murphet fixes it
Forecasts of rates can shoot < 0 or > 1 Beta head maps μ → (0, 1) automatically
Constant-variance Gaussian noise mis-prices tails Mean-dependent Beta / Student-t likelihoods
Hard CPs create kinks; few data → over-fit Smooth logistic changepoints + Laplace shrinkage
Season coefficients often blow up Weak-Normal (σ≈10) priors, optional horseshoe
Residual AR left untreated Latent AR(1) disturbance (ρ, μ₀)
One-size-fits-all variance Heteroscedastic φᵢ/σᵢ via log-linear link

2 · Installation

pip install murphet              # wheels include pre-compiled Stan models

Requirements

  • Python >= 3.8 & CmdStanPy >= 1.0 (auto-installed)
  • A recent CmdStan toolchain (gcc/clang) — cmdstanpy.install_cmdstan() will fetch it.

3 · Quick start

import pandas as pd, numpy as np
from murphet import fit_churn_model

df = pd.read_csv("churn_data.csv")        # cols: ds, y  (0<y<1)
df["ds"] = pd.to_datetime(df["ds"])
df["t"]  = np.arange(len(df))             # integer index

mod = fit_churn_model(
        t              = df["t"],
        y              = df["y"],
        periods        = 12, num_harmonics = 3,    # yearly seasonality
        n_changepoints = 4,
        likelihood     = "beta",                   # default & safest
        inference      = "nuts",                   # full posterior
      )

future_t = np.arange(len(df), len(df)+6)
fcst     = mod.predict(future_t)

4 · Model internals (nutshell)

Component Equation Note
Trend μdet(t) = k·t + m + ∑ δj σ(γ (t − sj)) smooth CP ramps
Seasonality Fourier blocks on raw t (fmod) multiple periods OK
Link / saturation μlogit⁻¹p optional
Likelihoods Beta(p·φᵢ,(1-p)·φᵢ) or Student-tν(μ,σᵢ) φᵢ / σᵢ heteroscedastic
Latent error y* = μdet + ρ·lag AR(1) disturbance

Add-ons implemented

✔ add-on Stan code snippet Effect
AR(1) latent error real<lower=-1,upper=1> rho; real mu0; + update in partial_sum_* absorbs slow drifts / residual autocorr
Heteroscedastic precision / scale phi_i = exp(log_phi0 - beta_phi*abs(mu_det)); (Beta) / sigma_i = exp(log_sigma0 + beta_sigma*abs(mu_det)); (Gauss) wider tails when level high
Heavy-tail option `student_t_lpdf(y ν, μ, σᵢ)withν ~ Exp(1/30)`

5 · Case-studies

5 a · Hong-Kong hotel occupancy (monthly, 2020-2025)

Source link

Hotel hold-out

Hold-out horizon RMSE
Murphet β 0.0916
Prophet (optimised) 0.1159

5 b · U.S. Retail Inventories-to-Sales Ratio (FRED RETAILIRNSA)

Retail hold-out

Hold-out (24 mo) RMSE SMAPE
Murphet β 0.0496 5.15 %
Prophet 0.1140 13.21 %

Residual check:

Residual diagnostics

Murphet's AR(1)+heteroscedastic head slashes autocorrelation; Prophet still shows structure.


6 · Which head to choose?

Head Use-case Link Likelihood
β (default) Proportions, CTR, churn %, conversion % logit⁻¹ Beta(p·φᵢ,(1-p)·φᵢ)
Gaussian / Student-t Ratios "around" 0.4–1.0 or unbounded KPI identity Normal/Student-t(μ,σᵢ)

Switch with likelihood="gaussian"; all other API calls identical.


7 · API cheat-sheet

Function Purpose
fit_churn_model(t, y, **kwargs) fit (MAP, ADVI, or NUTS)
model.predict(t_new) fast vectorised prediction
model.fit_result access raw CmdStanPy object
model.summary() pretty DataFrame of posteriors

Key kwargs:

periods, num_harmonics         # seasonality
n_changepoints, delta_scale    # trend flexibility
gamma_scale                    # CP steepness
season_scale                   # weaken/strengthen Fourier priors
likelihood  = "beta"|"gaussian"
inference   = "map"|"advi"|"nuts"

8 · Road-map

  • Holiday regressors (Prophet style)
  • Prophet-like plotting helpers
  • Automatic Stan/C++ speed-ups for long MCMC chains

9 · Citing Murphet

If you use Murphet in academic work, please cite:

Murphy, S. (2025). Murphet: A Bayesian Time-Series Model for Bounded Rates.
https://github.com/halsted312/murphet

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

murphet-1.1.0.tar.gz (15.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

murphet-1.1.0-py3-none-any.whl (13.0 kB view details)

Uploaded Python 3

File details

Details for the file murphet-1.1.0.tar.gz.

File metadata

  • Download URL: murphet-1.1.0.tar.gz
  • Upload date:
  • Size: 15.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.17

File hashes

Hashes for murphet-1.1.0.tar.gz
Algorithm Hash digest
SHA256 c06e1da6d5990f7ef92ddb2737a11f951e06a2e4beb575aa3e585b5c7a6dc84a
MD5 cd414a5de28dcee5cccca29b02c76e2a
BLAKE2b-256 6f801f487e08b420612df30b2354ec1f3ac4c71efe74122d469c6cf47abc0920

See more details on using hashes here.

File details

Details for the file murphet-1.1.0-py3-none-any.whl.

File metadata

  • Download URL: murphet-1.1.0-py3-none-any.whl
  • Upload date:
  • Size: 13.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.10.17

File hashes

Hashes for murphet-1.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d75deaca2dbd2fa087b75279de8f004b8efae9330bcedf8a1b4442a28e1f1484
MD5 0030640f1e4b4050a70de9c716721dd9
BLAKE2b-256 e1a4815404d8cf4c4086f130e39201ae540be95d84a9beb6d3cbbb6f7c69bbc2

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page