Bayesian time‑series model with Beta/Gaussian heads, smooth changepoints and seasonality
Project description
📈 Murphet — Prophet's (0-1) Cousin for Probabilities & Rates
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)
| Hold-out horizon | RMSE |
|---|---|
| Murphet β | 0.0916 |
| Prophet (optimised) | 0.1159 |
5 b · U.S. Retail Inventories-to-Sales Ratio (FRED RETAILIRNSA)
| Hold-out (24 mo) | RMSE | SMAPE |
|---|---|---|
| Murphet β | 0.0496 | 5.15 % |
| Prophet | 0.1140 | 13.21 % |
Residual check:
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
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file murphet-1.3.0.tar.gz.
File metadata
- Download URL: murphet-1.3.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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
298f7c0d8bad410b00ac70fcb33bc1daed53559acb9369785d33413dbc920e46
|
|
| MD5 |
7dc61cb50bf39be0841f91cc3d45d112
|
|
| BLAKE2b-256 |
40636c2a7e2af596d8205273b1f7b3f035430e3b6fcafcc022ed52a467577472
|
File details
Details for the file murphet-1.3.0-py3-none-any.whl.
File metadata
- Download URL: murphet-1.3.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
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f27d8a0391d5e54050f11a20df466564911e2be36a1570a44776b40b27b84507
|
|
| MD5 |
d0ae4e4003a9d737c14b74f7eea579c9
|
|
| BLAKE2b-256 |
adc751b45937a2b5bd2321422ab9cd8886948fab157e34c8927b6605b9cd05fa
|