Gain, Lift and Deciles

Updated Started

These curves answer a practical question: if we act on the rows the model ranks highest, how many of the positives do we reach? They use the same Titanic random forest as Classification Metrics. In the test set 38% of passengers survived, so survival is the positive class.

Gain

Sort the rows by predicted probability, highest first. The gain for the top fraction of rows is the share of all positives found there:

gain=positives in the subsetpositives in the whole sample\text{gain} = \frac{\text{positives in the subset}}{\text{positives in the whole sample}}

A perfect model would find every survivor in the top 38% of rows, for 100% gain. A real model has false positives near the top, so it takes more than 38% of the rows to get there, and 100% gain only arrives at the end, because some survivors get very low predicted probabilities. Random selection gives gain equal to the fraction of rows taken. This is the same cumulative curve as the CAP chart, just with both axes as proportions.

Lift

Lift compares the positive rate in the top fraction with the positive rate overall:

lift=positives in the subset  /  rows in the subsetpositives in the sample  /  rows in the sample\text{lift} = \frac{\text{positives in the subset} \;/\; \text{rows in the subset}}{\text{positives in the sample} \;/\; \text{rows in the sample}}

Equivalently, lift is gain divided by the fraction of rows taken. Random selection has a lift of 1. With 38% positives the highest possible lift is 1/0.38=2.631 / 0.38 = 2.63, which a perfect model would hold across its top 38% of rows.

def plot_lift(y_proba, y_real, ax=None):
    df = pd.DataFrame({"y_real": y_real, "y_proba": y_proba}).sort_values("y_proba", ascending=False)
    total_positive_ratio = (df["y_real"] == 1).mean()
    lift_values = []
    for threshold in df["y_proba"]:
        subset = df[df["y_proba"] >= threshold]
        lift_values.append((subset["y_real"] == 1).mean() / total_positive_ratio)
    ...
Gain and lift curves for the Titanic random forest

Decile analysis

Decile analysis is the tabular version, common in marketing and credit risk: sort by predicted probability, cut into ten equal groups, and count the positives in each. Decile 1 is the group the model rates most likely, for example to respond to an advert or default on a loan.

df = pd.DataFrame({"y_proba": preds_test, "y_real": y_test}).sort_values("y_proba", ascending=False)
df = df.reset_index(drop=True)
df["decile"] = pd.qcut(df.index, 10, labels=False) + 1
DecileRowsPositivesPositive rateGainLiftProbability range
133320.970.262.540.95 to 1.00
233290.880.492.430.83 to 0.95
333160.480.622.040.64 to 0.81
432150.470.741.840.45 to 0.63
533110.330.821.650.28 to 0.45
63350.150.861.440.19 to 0.28
73260.190.911.310.11 to 0.19
83340.120.941.180.05 to 0.11
93330.090.971.080.02 to 0.05
103340.121.001.000.00 to 0.02

Gain and lift here are cumulative: the top two deciles hold 49% of the survivors, at 2.43 times the base rate. A well-ranked model has positive rates that fall steadily down the table; the small rise in decile 10 shows a few survivors the model was confidently wrong about.

Sources

Original notebook

Linked from

Revision log

  1. Migrated from data-science-notes; fixed the lift formula

Tags: Machine Learning