1.5. Customer Acquisition Metrics#

Customer acquisition inverts the churn problem: instead of keeping existing customers, you spend money contacting leads in the hope of converting them. Empulse ships ready-made metrics for this use case, following the profit-based framework of Verbraken et al. [1].

Note

These names are prebuilt Metric instances, not functions. Earlier versions of Empulse exposed hand-written empa and mpa functions returning a (score, threshold) tuple; those have been removed. Call the metric for the score, and use optimal_rate for the fraction of leads to target.

1.5.1. The Cost-Benefit Matrix#

Every contacted lead costs \(c\) (contact_cost), converted or not. Leads are handled in two ways, and direct_selling is the fraction handled directly:

  • Directly, by your own sales team: you gain the contribution \(R\) of a converted lead but pay the sales cost \(s\) (sales_cost).

  • Indirectly, through an intermediary: you avoid the sales cost but pay a commission \(\kappa\) (commission) on the contribution.

Leads you do not contact cost nothing, so both “predicted negative” outcomes are zero.

Actual converter \(y_i = 1\)

Actual non-converter \(y_i = 0\)

Predicted converter \(\hat{y}_i = 1\)

tp_benefit \(= \sigma (R - c - s) + (1 - \sigma)\,(R (1 - \kappa) - c)\)

fp_cost \(= c\)

Predicted non-converter \(\hat{y}_i = 0\)

fn_cost \(= 0\)

tn_benefit \(= 0\)

with \(\sigma\) the direct_selling fraction (1 = fully direct, 0 = fully indirect).

Metric

Strategy

Contribution of a conversion

mpa_score

MaxProfit

Fixed (contribution)

empa_score

MaxProfit

Gamma(alpha, beta)

expected_cost_loss_acquisition

Cost

Fixed (contribution)

1.5.2. Maximum Profit for Customer Acquisition (MPA)#

mpa_score treats the contribution of a conversion as a single known amount.

Defaults: contribution=8000, contact_cost=50, sales_cost=500, direct_selling=1, commission=0.1.

import numpy as np
from empulse.metrics import mpa_score

y_true = np.array([0, 1, 0, 1, 0, 1, 0, 1])
y_score = np.array([0.1, 0.9, 0.2, 0.8, 0.3, 0.7, 0.4, 0.6])

profit = mpa_score(y_true, y_score)
profit_indirect = mpa_score(y_true, y_score, direct_selling=0, commission=0.15)

1.5.3. Expected Maximum Profit for Customer Acquisition (EMPA)#

New customers are not equally valuable, and their value is not known in advance. empa_score models the contribution as a Gamma(alpha, beta) random variable and integrates over it.

Defaults: alpha=12, beta=1/0.0015 (a mean contribution of \(12 \times 666.7 = 8000\)), contact_cost=50, sales_cost=500, direct_selling=1, commission=0.1.

from empulse.metrics import empa_score

expected_profit = empa_score(y_true, y_score)

Warning

beta is the scale of the Gamma distribution (mean = alpha * beta), not the rate (mean = alpha / beta) used by the removed empa function. The default was adjusted so that calling with no arguments reproduces the previous result, but an explicit non-default beta= means something different than it used to.

1.5.3.1. How many leads should you target?#

from empulse.metrics import classification_threshold

target_fraction = empa_score.optimal_rate(y_true, y_score)
threshold = classification_threshold(y_true, y_score, customer_threshold=target_fraction)

1.5.4. Expected Cost Loss for Acquisition#

When you want to minimise cost from calibrated probabilities rather than maximise profit from ranking scores, expected_cost_loss_acquisition applies the same business model through the Cost strategy. Lower is better, and it always returns the mean cost per lead.

Defaults: contribution=7000, contact_cost=50, sales_cost=500, direct_selling=1, commission=0.1.

from empulse.metrics import expected_cost_loss_acquisition

y_proba = np.array([0.05, 0.95, 0.15, 0.85, 0.25, 0.75, 0.35, 0.65])

mean_cost = expected_cost_loss_acquisition(y_true, y_proba)

1.5.5. Using an acquisition metric to train a model#

from empulse.models import CSBoostClassifier
from sklearn.datasets import make_classification

X, y = make_classification(n_samples=200, n_features=5, random_state=42)

model = CSBoostClassifier(loss=expected_cost_loss_acquisition)
model.fit(X, y)

See Use your custom metric inside a model for which models support which strategies.

1.5.6. See also#

1.5.7. References#