6.3.3. Bank Telemarketing Upsell Campaign#
6.3.3.1. Summary#
This dataset is related to a direct marketing campaigns (phone calls) of a Portuguese banking institution. The marketing campaigns were based on phone calls. Often, more than one contact to the same client was required, in order to access if the product (bank term deposit) would be or not subscribed.
Features recorded before the contact event are removed from the original dataset [1] to avoid data leakage. Only clients with a positive balance are considered, since clients in debt are not eligible for term deposits.
Classes |
2 |
Subscribers |
4787 |
Non-subscribers |
33144 |
Samples |
37931 |
Features |
10 |
6.3.3.2. Using the Dataset#
The dataset can be loaded through the load_upsell_bank_telemarketing function.
This returns a Dataset object with the following attributes:
data: the feature matrixtarget: the target vectorcost_matrix: aCostMatrixwith default values pre-filledinstance_costs: a dict of per-instance cost drivers ('balance')feature_names: the feature namestarget_names: the target namesDESCR: the full description of the dataset
import pandas as pd
from empulse.datasets import load_upsell_bank_telemarketing
dataset = load_upsell_bank_telemarketing(backend=pd)
The backend argument selects the dataframe library used for data and target.
Pass the module itself — backend=pd for pandas or backend=pl for polars.
The cost matrix is symbolic: only the customer balance varies per instance, while the
interest rate, term deposit fraction and contact cost are parameters with defaults.
Pass the cost matrix to the model as a Metric loss, and hand it the
instance costs at fit time:
import pandas as pd
from empulse.datasets import load_upsell_bank_telemarketing
from empulse.metrics import Metric, Cost
from empulse.models import CSLogitClassifier
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, TargetEncoder
dataset = load_upsell_bank_telemarketing(backend=pd)
X, y = dataset.data, dataset.target
numeric = X.select_dtypes(include=['number']).columns
categorical = X.select_dtypes(exclude=['number']).columns
pipeline = Pipeline([
('preprocessor', ColumnTransformer([
('num', StandardScaler(), numeric),
('cat', TargetEncoder(), categorical),
])),
('model', CSLogitClassifier(loss=Metric(dataset.cost_matrix, Cost())))
])
pipeline.fit(X, y, model__balance=dataset.instance_costs['balance'])
6.3.3.3. Cost Matrix#
Actual positive \(y_i = 1\) |
Actual negative \(y_i = 0\) |
|
Predicted positive \(\hat{y}_i = 1\) |
|
|
Predicted negative \(\hat{y}_i = 0\) |
|
|
- with
\(c\) : cost of contacting the client
\(r\) : interest rate of the term deposit
\(d_i\) : fraction of the client’s balance that is deposited in the term deposit
\(b_i\) : client’s balance
Using default parameters, it is assumed that \(c = 1\), \(r = 0.02463333\), \(d_i = 0.25\) for all clients. The default parameters are based on [4].
These assumptions are symbolic parameters of the cost matrix, exposed under the aliases
interest_rate, term_deposit_fraction and contact_cost.
Override any of them by passing the alias when evaluating the metric:
import numpy as np
import pandas as pd
from empulse.datasets import load_upsell_bank_telemarketing
from empulse.metrics import Metric, Cost
dataset = load_upsell_bank_telemarketing(backend=pd)
# replace with your own model's predicted probabilities
y_score = np.random.default_rng(0).uniform(size=len(dataset.target))
cost = Metric(dataset.cost_matrix, Cost())
score = cost(
dataset.target,
y_score,
interest_rate=0.05,
term_deposit_fraction=0.30,
contact_cost=10,
**dataset.instance_costs,
)
6.3.3.4. Data Description#
Variable Name |
Description |
Type |
|---|---|---|
age |
Age of the client |
numeric |
balance |
Average yearly balance |
numeric |
previous |
Number of contacts performed before this campaign and for this client |
numeric |
job |
Type of job (e.g., ‘admin.’, ‘blue-collar’, ‘entrepreneur’, etc.) |
categorical |
marital |
Marital status (‘divorced’, ‘married’, ‘single’) |
categorical |
education |
Education level (‘primary’, ‘secondary’, ‘tertiary’, ‘unknown’) |
categorical |
has_credit_in_default |
Has credit in default? (‘yes’ = 1, ‘no’ = 0) |
binary |
has_housing_loan |
Has housing loan? (‘yes’ = 1, ‘no’ = 0) |
binary |
has_personal_loan |
Has personal loan? (‘yes’ = 1, ‘no’ = 0) |
binary |
previous_outcome |
Outcome of the previous marketing campaign (‘success’, ‘failure’, ‘other’, ‘unknown’) |
categorical |
subscribed |
Has the client subscribed a term deposit? (‘yes’ = 1, ‘no’ = 0) |
binary |