Pareto-NBD Model

Summary

The Pareto/NBD model of Schmittlein, Morrison & Colombo (1987, “SMC”) describes repeat buying in a noncontractual, continuous-time setting where customer “death” is never observed. While alive a customer buys as a Poisson process with rate ; the customer’s unobserved lifetime is exponential with rate ; and vary independently across customers as gammas. Mixing gives an NBD for purchases while alive and a Pareto (type II) for lifetimes. Fader & Hardie’s 2005 note re-derives SMC’s results more transparently and adds the explicit likelihood: the customer’s history enters only through frequency , recency and observation length , and and the expected number of future purchases follow by Bayes’ theorem. The cost is repeated evaluation of the Gaussian hypergeometric function — the motivation for the BG-NBD Model.

Overview

The firm sees a transaction log and, for each customer, a silence since the last purchase. Is the customer gone, or just between purchases? The Pareto/NBD answers probabilistically by combining a counting process with a latent survival process (Survival Analysis with an unobserved event time). SMC derived and the conditional expectation but never wrote down the likelihood, which — together with reported numerical difficulty — left the model rarely implemented for almost two decades. The note summarized here (Fader & Hardie 2005, brucehardie.com/notes/009) supplies the missing likelihood and a “key intermediate result” that makes every derivation a one-liner.

Main Content

Pareto/NBD assumptions ^def-pnbd-assumptions

(Fader & Hardie 2005, Sec. 2)

  1. Customers are “alive” for some time, then become permanently inactive.
  2. While alive, purchases follow a Poisson process with rate : ; equivalently, interpurchase times are exponential.
  3. The unobserved lifetime is exponential with dropout rate : .
  4. across customers: ( is a rate, despite being called “scale” in the paper).
  5. across customers.
  6. and vary independently across customers.

Assumptions 2 and 4 give the NBD for purchases while alive, and 3 and 5 give the Pareto distribution of the second kind (Lomax) for lifetimes (Eqs. 4–6):

The NBD is the gamma-Poisson marginal of Single-Parameter Models; the Pareto is a gamma mixture of exponentials, whose decreasing aggregate hazard is a pure sorting effect (compare Shifted-Beta-Geometric Model for Contractual Retention).

Individual-level likelihood and sufficiency of

Given purchase times in , either the customer is still alive at , contributing , or died at some , contributing . “In both cases, information on when each of the transactions occurred is not required” — (recency) and (frequency) are sufficient. Integrating out (Eqs. 12–14):

The authors note “this is a new result, as SMC do not present an explicit expression for the model likelihood function.”

Likelihood for a randomly chosen customer ^thm-pnbd-likelihood

Taking the expectation over the two gammas (Eq. 18):

where, for (Eq. 19),

and for (Eq. 20) the same with second argument , ratio and base . Two forms are needed because the series for converges only for ; choosing the branch by the sign of keeps (Sec. 2.1). Parameters are estimated by maximizing .

The derivation trick (Sec. 2.1) is a change of variables , (Jacobian ), which turns every double integral of the form into Euler’s integral for . A second route (Eq. 21) integrates over first and last, displaying the likelihood as “NBD likelihood × Pareto survivor” plus an integral over death times.

Mean of the Pareto/NBD ^thm-pnbd-mean

Conditional on the traits, (Eq. 26); for a randomly chosen customer (Eq. 27, SMC Eq. 17), for ,

This drives the aggregate tracking plot of cumulative repeat sales for a cohort.

Probability alive ^thm-pnbd-palive

By Bayes’ theorem , which simplifies to SMC’s (A10) (Eq. 31):

Averaging over the posterior of gives (Eqs. 34–35)

The individual-level form shows the mechanics: decays with the silence at rate , so a high-frequency customer is declared dead much sooner after going quiet — the root of the “increasing frequency paradox” in RFM Sufficient Statistics and Iso-Value Curves. (The note also flags an error in SMC’s Eq. A25.)

Conditional expectation of future purchases ^thm-pnbd-conditional-expectation

Let be purchases in . If alive at , memorylessness gives (Eq. 38). Multiplying by and averaging over the posterior (Eq. 41 rearranged; SMC Eq. 22):

The second factor is the Pareto/NBD mean (above) with updated parameters , , — the conjugate gamma posterior of a customer who survived to .

Estimation difficulty. Fader, Hardie & Lee (2005, Marketing Science, Sec. 2) describe the likelihood as “quite complex, involving numerous evaluations of the Gaussian hypergeometric function”, whose numerical precision “can vary substantially over the parameter space”, causing trouble for optimizers; they knew of only one published MLE implementation (Reinartz & Kumar 2003), and SMC’s own three-step method-of-moments procedure lacks MLE’s properties. Their own Pareto/NBD fit had to be done in MATLAB.

Examples

CDNOW cohort. For a 1/10 sample (2,357 customers) of the Q1-1997 CDNOW cohort, calibrated on 39 weeks, the MLEs are , , , with (Marketing Science 2005, Table 2). The cumulative tracking plot under-forecasts week-78 repeat sales by less than 2%.

Plugging these into the formulas above (own calculation, branch, weeks, horizon ):

History
0.300.11
0.170.17
0.871.46
0.753.71

Note the zero class: under Pareto/NBD a customer who never repurchased may already be dead (), whereas the BG/NBD forces for . A new customer is expected to make repeat purchases in the first 39 weeks.

import numpy as np
from scipy.special import hyp2f1, gammaln
 
def pnbd_loglik(r, a, s, b, x, tx, T):
    """Eq. 18 with A0 from Eq. 19 (a >= b) or Eq. 20 (a <= b)."""
    if a >= b:
        F = lambda u: hyp2f1(r+s+x, s+1, r+s+x+1, (a-b)/(a+u)) / (a+u)**(r+s+x)
    else:
        F = lambda u: hyp2f1(r+s+x, r+x, r+s+x+1, (b-a)/(b+u)) / (b+u)**(r+s+x)
    A0 = F(tx) - F(T)
    alive = 1.0 / ((a+T)**(r+x) * (b+T)**s)
    pre = gammaln(r+x) - gammaln(r) + r*np.log(a) + s*np.log(b)
    return pre + np.log(alive + s/(r+s+x) * A0)      # P(alive) = alive / (alive + s/(r+s+x)*A0)

Connections

See Also