TypeError: ParetoNBDRV.make_node() missing 1 required positional argument: 'T'

Hi team,

I am following the “How-to” instruction on pymc-marketing Pareto/NBD, but get the error. Can anyone please help with it? Thank you!

The code:

flat_config = {
    "r_prior": {"dist": "HalfFlat", "kwargs": {}},
    "alpha_prior": {"dist": "HalfFlat", "kwargs": {}},
    "s_prior": {"dist": "HalfFlat", "kwargs": {}},
    "beta_prior": {"dist": "HalfFlat", "kwargs": {}},
    }

pnbd_pymc = clv.ParetoNBDModel(data=rfm_data, model_config=flat_config)
pnbd_pymc.build_model()

The error:

---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
Cell In[13], line 11
      3 flat_config = {
      4     "r_prior": {"dist": "HalfFlat", "kwargs": {}},
      5     "alpha_prior": {"dist": "HalfFlat", "kwargs": {}},
      6     "s_prior": {"dist": "HalfFlat", "kwargs": {}},
      7     "beta_prior": {"dist": "HalfFlat", "kwargs": {}},
      8     }
     10 pnbd_pymc = clv.ParetoNBDModel(data=rfm_data, model_config=flat_config)
---> 11 pnbd_pymc.build_model()

File ~/miniconda3/envs/pymc_env/lib/python3.12/site-packages/pymc_marketing/clv/models/pareto_nbd.py:313, in ParetoNBDModel.build_model(self)
    310 else:
    311     beta = self.model.register_rv(beta_scale_prior, name="beta")
--> 313 ParetoNBD(
    314     name="recency_frequency",
    315     r=r,
    316     alpha=alpha,
    317     s=s,
    318     beta=beta,
    319     T=self.data["T"],
    320     observed=np.stack(
    321         (self.data["recency"], self.data["frequency"]), axis=1
    322     ),
    323     dims=["customer_id", "obs_var"],
    324 )

File ~/miniconda3/envs/pymc_env/lib/python3.12/site-packages/pymc/distributions/distribution.py:536, in Distribution.__new__(cls, name, rng, dims, initval, observed, total_size, transform, default_transform, *args, **kwargs)
    533     elif observed is not None:
    534         kwargs["shape"] = tuple(observed.shape)
--> 536 rv_out = cls.dist(*args, **kwargs)
    538 rv_out = model.register_rv(
    539     rv_out,
    540     name,
   (...)
    546     initval=initval,
    547 )
    549 # add in pretty-printing support

File ~/miniconda3/envs/pymc_env/lib/python3.12/site-packages/pymc_marketing/clv/distributions.py:413, in ParetoNBD.dist(cls, r, alpha, s, beta, T, **kwargs)
    411 @classmethod
    412 def dist(cls, r, alpha, s, beta, T, **kwargs):
--> 413     return super().dist([r, alpha, s, beta, T], **kwargs)

File ~/miniconda3/envs/pymc_env/lib/python3.12/site-packages/pymc/distributions/distribution.py:618, in Distribution.dist(cls, dist_params, shape, **kwargs)
    615     ndim_supp = cls.rv_op(*dist_params, **kwargs).owner.op.ndim_supp
    617 create_size = find_size(shape=shape, size=size, ndim_supp=ndim_supp)
--> 618 rv_out = cls.rv_op(*dist_params, size=create_size, **kwargs)
    620 rv_out.logp = _make_nice_attr_error("rv.logp(x)", "pm.logp(rv, x)")
    621 rv_out.logcdf = _make_nice_attr_error("rv.logcdf(x)", "pm.logcdf(rv, x)")

File ~/miniconda3/envs/pymc_env/lib/python3.12/site-packages/pymc_marketing/clv/distributions.py:301, in ParetoNBDRV.__call__(self, r, alpha, s, beta, T, size, **kwargs)
    300 def __call__(self, r, alpha, s, beta, T, size=None, **kwargs):
--> 301     return super().__call__(r, alpha, s, beta, T, size=size, **kwargs)

File ~/miniconda3/envs/pymc_env/lib/python3.12/site-packages/pytensor/tensor/random/op.py:311, in RandomVariable.__call__(self, size, name, rng, dtype, *args, **kwargs)
    309     props["dtype"] = dtype
    310     new_op = type(self)(**props)
--> 311     return new_op.__call__(
    312         *args, size=size, name=name, rng=rng, dtype=dtype, **kwargs
    313     )
    315 res = super().__call__(rng, size, *args, **kwargs)
    317 if name is not None:

File ~/miniconda3/envs/pymc_env/lib/python3.12/site-packages/pymc_marketing/clv/distributions.py:301, in ParetoNBDRV.__call__(self, r, alpha, s, beta, T, size, **kwargs)
    300 def __call__(self, r, alpha, s, beta, T, size=None, **kwargs):
--> 301     return super().__call__(r, alpha, s, beta, T, size=size, **kwargs)

File ~/miniconda3/envs/pymc_env/lib/python3.12/site-packages/pytensor/tensor/random/op.py:315, in RandomVariable.__call__(self, size, name, rng, dtype, *args, **kwargs)
    310     new_op = type(self)(**props)
    311     return new_op.__call__(
    312         *args, size=size, name=name, rng=rng, dtype=dtype, **kwargs
    313     )
--> 315 res = super().__call__(rng, size, *args, **kwargs)
    317 if name is not None:
    318     res.name = name

File ~/miniconda3/envs/pymc_env/lib/python3.12/site-packages/pytensor/graph/op.py:293, in Op.__call__(self, name, return_list, *inputs, **kwargs)
    249 def __call__(
    250     self, *inputs: Any, name=None, return_list=False, **kwargs
    251 ) -> Variable | list[Variable]:
    252     r"""Construct an `Apply` node using :meth:`Op.make_node` and return its outputs.
    253 
    254     This method is just a wrapper around :meth:`Op.make_node`.
   (...)
    291 
    292     """
--> 293     node = self.make_node(*inputs, **kwargs)
    294     if name is not None:
    295         if len(node.outputs) == 1:

TypeError: ParetoNBDRV.make_node() missing 1 required positional argument: 'T'

I installed pymc on the conda env and was following exactly the steps on the “How-to” webpage: Pareto/NBD Model — pymc-marketing 0.6.0 documentation

What version of PyMC is being installed? You can get it by running pymc.__version__ after importing it in whatever environment you’re using

The version of PyMC is 5.16.1

Try to go down to 5.15.1. The last PyMC release did some breaking API changes that pymc-experimental still is not handling

Thank you! I am trying pymc=5.15.1, it works now.