Skip to content

Commit 55e84d3

Browse files
committed
💥 Add perfect_uplift_curve func; add normalisation in uplift_auc_score
1 parent edd69ab commit 55e84d3

File tree

1 file changed

+75
-20
lines changed

1 file changed

+75
-20
lines changed

sklift/metrics/metrics.py

Lines changed: 75 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,7 @@
99
def uplift_curve(y_true, uplift, treatment):
1010
"""Compute Uplift curve.
1111
12-
This is a general function, given points on a curve. For computing the
13-
area under the Uplift Curve, see :func:`uplift_auc_score`.
12+
For computing the area under the Uplift Curve, see :func:`uplift_auc_score`.
1413
1514
Args:
1615
y_true (1d array-like): Correct (true) target values.
@@ -23,6 +22,8 @@ def uplift_curve(y_true, uplift, treatment):
2322
See also:
2423
:func:`uplift_auc_score`: Compute the area under the Uplift curve.
2524
25+
:func:`perfect_uplift_curve`: Compute the perfect (optimal) Uplift curve.
26+
2627
:func:`plot_uplift_qini_curves`: Plot Uplift and Qini curves.
2728
"""
2829

@@ -59,6 +60,75 @@ def uplift_curve(y_true, uplift, treatment):
5960
return num_all, curve_values
6061

6162

63+
def perfect_uplift_curve(y_true, treatment):
64+
"""Compute the perfect (optimum) Uplift curve.
65+
66+
This is a function, given points on a curve. For computing the
67+
area under the Uplift Curve, see :func:`uplift_auc_score`.
68+
69+
Args:
70+
y_true (1d array-like): Correct (true) target values.
71+
treatment (1d array-like): Treatment labels.
72+
73+
Returns:
74+
array (shape = [>2]), array (shape = [>2]): Points on a curve.
75+
76+
See also:
77+
:func:`uplift_auc_score`: Compute the area under the Uplift curve.
78+
79+
:func:`perfect_uplift_curve`: Compute Uplift curve.
80+
81+
:func:`plot_uplift_qini_curves`: Plot Uplift and Qini curves.
82+
"""
83+
check_consistent_length(y_true, treatment)
84+
y_true, treatment = np.array(y_true), np.array(treatment)
85+
86+
CR_num = np.sum((y_true == 1) & (treatment == 0)) # Control Responders
87+
TN_num = np.sum((y_true == 0) & (treatment == 1)) # Treated Non-Responders
88+
89+
summand = y_true if CR_num > TN_num else treatment
90+
perfect_uplift = 2 * (y_true == treatment) + summand
91+
92+
return uplift_curve(y_true, perfect_uplift, treatment)
93+
94+
95+
def uplift_auc_score(y_true, uplift, treatment):
96+
"""Compute normalized Area Under the Uplift Curve from prediction scores.
97+
98+
By computing the area under the Qini curve, the curve information is summarized in one number.
99+
For binary outcomes the ratio of the actual uplift gains curve above the diagonal to that of the optimum Qini Curve.
100+
101+
Args:
102+
y_true (1d array-like): Correct (true) target values.
103+
uplift (1d array-like): Predicted uplift, as returned by a model.
104+
treatment (1d array-like): Treatment labels.
105+
106+
Returns:
107+
float: Area Under the Uplift Curve.
108+
109+
See also:
110+
:func:`uplift_curve`:
111+
112+
:func:`perfect_uplift_curve`:
113+
114+
:func:`plot_uplift_qini_curves`:
115+
"""
116+
check_consistent_length(y_true, uplift, treatment)
117+
n_samples = len(y_true)
118+
119+
y_true, uplift, treatment = np.array(y_true), np.array(uplift), np.array(treatment)
120+
121+
x_actual, y_actual = uplift_curve(y_true, uplift, treatment)
122+
x_perfect, y_perfect = perfect_uplift_curve(y_true, treatment)
123+
x_baseline, y_baseline = np.array([0, x_perfect[-1]]), np.array([0, y_perfect[-1]])
124+
125+
auc_score_baseline = auc(x_baseline, y_baseline)
126+
auc_score_perfect = auc(x_perfect, y_perfect) - auc_score_baseline
127+
auc_score_actual = auc(x_actual, y_actual) - auc_score_baseline
128+
129+
return auc_score_actual / auc_score_perfect
130+
131+
62132
def qini_curve(y_true, uplift, treatment):
63133
"""Compute Qini curve.
64134
@@ -74,7 +144,7 @@ def qini_curve(y_true, uplift, treatment):
74144
array (shape = [>2]), array (shape = [>2]): Points on a curve.
75145
76146
See also:
77-
:func:`qini_auc_score`: Compute the area under the Qini curve.
147+
:func:`uplift_curve`: Compute the area under the Qini curve.
78148
79149
:func:`plot_uplift_qini_curves`: Plot Uplift and Qini curves.
80150
"""
@@ -113,22 +183,6 @@ def qini_curve(y_true, uplift, treatment):
113183
return num_all, curve_values
114184

115185

116-
def uplift_auc_score(y_true, uplift, treatment):
117-
"""Compute Area Under the Uplift Curve from prediction scores.
118-
119-
Args:
120-
y_true (1d array-like): Correct (true) target values.
121-
uplift (1d array-like): Predicted uplift, as returned by a model.
122-
treatment (1d array-like): Treatment labels.
123-
124-
Returns:
125-
float: Area Under the Uplift Curve.
126-
"""
127-
# ToDO: Add normalization
128-
# ToDO: Add baseline
129-
return auc(*uplift_curve(y_true, uplift, treatment))
130-
131-
132186
# FIXME: remove in 0.2.0
133187
def auuc(y_true, uplift, treatment):
134188
"""Compute Area Under the Uplift Curve from prediction scores.
@@ -154,8 +208,9 @@ def auuc(y_true, uplift, treatment):
154208

155209

156210
def qini_auc_score(y_true, uplift, treatment, negative_effect=True):
157-
"""Compute Area Under the Qini Curve (aka Qini coefficient) from prediction scores.
211+
"""Compute normalized Area Under the Qini Curve (aka Qini coefficient) from prediction scores.
158212
213+
By computing the area under the Qini curve, the curve information is summarized in one number.
159214
For binary outcomes the ratio of the actual uplift gains curve above the diagonal to that of the optimum Qini Curve.
160215
161216
Args:

0 commit comments

Comments
 (0)