From lifetimes#
If you have working lifetimes code, the same fit is shorter here, and the two
knobs that quietly change the answer are named instead of hidden. lifetimes is
archived and takes no new releases; clvkit fits the same four models on Python
3.11+.
Archived means nobody fixes it when the ground moves, and it already has.
setuptools 83 removed pkg_resources, lifetimes.datasets stopped importing
with it, and the load_cdnow_summary() line that opens every old tutorial now
dies on a fresh install. The models themselves still fit; the on-ramp is what
broke.
The whole migration, side by side#
lifetimes makes you build the RFM summary, then thread frequency,
recency and T through every call by hand:
from lifetimes import BetaGeoFitter, GammaGammaFitter
from lifetimes.utils import summary_data_from_transaction_data
summary = summary_data_from_transaction_data(
log, "customer_id", "date", monetary_value_col="amount", freq="W",
)
bgf = BetaGeoFitter(penalizer_coef=0.0)
bgf.fit(summary["frequency"], summary["recency"], summary["T"])
returning = summary[summary["frequency"] > 0]
ggf = GammaGammaFitter(penalizer_coef=0.0)
ggf.fit(returning["frequency"], returning["monetary_value"])
clv = ggf.customer_lifetime_value(
bgf,
summary["frequency"], summary["recency"], summary["T"],
summary["monetary_value"],
time=52, freq="W", discount_rate=0.001,
)
clvkit builds the summary once, as a CustomerBase, and every model reads it:
from clvkit import CustomerBase, CLV
cb = CustomerBase.from_transactions(log, time_unit="W", collapse="D")
clv = CLV().fit(cb).predict(horizon=52, discount_rate=0.001).to_pandas()
Call by call#
|
|
|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
What changes#
One object, not three arrays. lifetimes hands you frequency,
recency and T and trusts you to pass the right one to every call. Line
them up wrong and the model still fits, on the wrong data, without a word.
CustomerBase holds them together, so there’s nothing to line up.
The reporting unit and the event grain are separate. lifetimes folds both
into one freq. clvkit splits them: time_unit is the clock the parameters
are reported in, collapse is the grain at which same-period purchases count as
one event. freq="W" in lifetimes silently deletes every second purchase inside
a week; time_unit="W", collapse="D" keeps them and reports in weeks, the pair
that reproduces the published CDNOW fit. Get it wrong and α moves 55%, from
4.41 to 6.85.
Swapping the transaction model is one line. BGNBD to MBGNBD is a
one-word change on the same cb, with nothing re-summarised. In lifetimes
you re-thread the arrays into a different fitter.
See CustomerBase, the shared contract for the contract these all read, or CDNOW: from a raw transaction log to lifetime value for the CDNOW fit end to end.