{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "Tce3stUlHN0L"
},
"source": [
"##### Copyright 2023 The TensorFlow Authors."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {
"cellView": "form",
"execution": {
"iopub.execute_input": "2024-04-20T11:21:57.299827Z",
"iopub.status.busy": "2024-04-20T11:21:57.299373Z",
"iopub.status.idle": "2024-04-20T11:21:57.303487Z",
"shell.execute_reply": "2024-04-20T11:21:57.302899Z"
},
"id": "tuOe1ymfHZPu"
},
"outputs": [],
"source": [
"#@title Licensed under the Apache License, Version 2.0 (the \"License\");\n",
"# you may not use this file except in compliance with the License.\n",
"# You may obtain a copy of the License at\n",
"#\n",
"# https://www.apache.org/licenses/LICENSE-2.0\n",
"#\n",
"# Unless required by applicable law or agreed to in writing, software\n",
"# distributed under the License is distributed on an \"AS IS\" BASIS,\n",
"# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n",
"# See the License for the specific language governing permissions and\n",
"# limitations under the License."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "36EdAGhThQov"
},
"source": [
"# Uplifting with Decision Forests\n",
"\n",
"
\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2j8GzKvfVvF8"
},
"source": [
"Welcome to the *Uplifting* Tutorial for TensorFlow Decision Forests (TF-DF). In this tutorial, you will learn what uplifting is, why it is so important, and how to do it in TF-DF.\n",
"\n",
"This tutorial assumes you are familiar with the fundaments of TF-DF, in particular the installation procedure. The [beginner tutorial](https://www.tensorflow.org/decision_forests/tutorials/beginner_colab) is a great place to start learning about TF-DF.\n",
"\n",
"In this colab, you will:\n",
"\n",
"- Learn what an uplift modeling is.\n",
"- Train a Uplift Random Forest model on the **Hillstrom Email Marketing** dataset.\n",
"- Evaluate the quality of this model.\n"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "MQIPhTQVW19g"
},
"source": [
"## Installing TensorFlow Decision Forests\n",
"\n",
"Install TF-DF by running the following cell.\n",
"\n",
"[Wurlitzer](https://pypi.org/project/wurlitzer/) is needed to display the detailed training logs in Colabs (when using `verbose=2` in the model constructor)."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:21:57.307220Z",
"iopub.status.busy": "2024-04-20T11:21:57.306592Z",
"iopub.status.idle": "2024-04-20T11:22:00.150145Z",
"shell.execute_reply": "2024-04-20T11:22:00.149111Z"
},
"id": "oiz5HmMyWxgd"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting tensorflow_decision_forests\r\n",
" Using cached tensorflow_decision_forests-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.metadata (6.0 kB)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Collecting wurlitzer\r\n",
" Using cached wurlitzer-3.0.3-py3-none-any.whl.metadata (1.9 kB)\r\n",
"Requirement already satisfied: numpy in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow_decision_forests) (1.26.4)\r\n",
"Requirement already satisfied: pandas in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow_decision_forests) (2.2.2)\r\n",
"Requirement already satisfied: tensorflow~=2.16.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow_decision_forests) (2.16.1)\r\n",
"Requirement already satisfied: six in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow_decision_forests) (1.16.0)\r\n",
"Requirement already satisfied: absl-py in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow_decision_forests) (1.4.0)\r\n",
"Requirement already satisfied: wheel in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow_decision_forests) (0.41.2)\r\n",
"Requirement already satisfied: tf-keras~=2.16 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow_decision_forests) (2.16.0)\r\n",
"Requirement already satisfied: astunparse>=1.6.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (1.6.3)\r\n",
"Requirement already satisfied: flatbuffers>=23.5.26 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (24.3.25)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: gast!=0.5.0,!=0.5.1,!=0.5.2,>=0.2.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (0.5.4)\r\n",
"Requirement already satisfied: google-pasta>=0.1.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (0.2.0)\r\n",
"Requirement already satisfied: h5py>=3.10.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (3.11.0)\r\n",
"Requirement already satisfied: libclang>=13.0.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (18.1.1)\r\n",
"Requirement already satisfied: ml-dtypes~=0.3.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (0.3.2)\r\n",
"Requirement already satisfied: opt-einsum>=2.3.2 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (3.3.0)\r\n",
"Requirement already satisfied: packaging in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (24.0)\r\n",
"Requirement already satisfied: protobuf!=4.21.0,!=4.21.1,!=4.21.2,!=4.21.3,!=4.21.4,!=4.21.5,<5.0.0dev,>=3.20.3 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (3.20.3)\r\n",
"Requirement already satisfied: requests<3,>=2.21.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (2.31.0)\r\n",
"Requirement already satisfied: setuptools in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (69.5.1)\r\n",
"Requirement already satisfied: termcolor>=1.1.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (2.4.0)\r\n",
"Requirement already satisfied: typing-extensions>=3.6.6 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (4.11.0)\r\n",
"Requirement already satisfied: wrapt>=1.11.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (1.16.0)\r\n",
"Requirement already satisfied: grpcio<2.0,>=1.24.3 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (1.63.0rc2)\r\n",
"Requirement already satisfied: tensorboard<2.17,>=2.16 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (2.16.2)\r\n",
"Requirement already satisfied: keras>=3.0.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (3.2.1)\r\n",
"Requirement already satisfied: tensorflow-io-gcs-filesystem>=0.23.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorflow~=2.16.1->tensorflow_decision_forests) (0.36.0)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: python-dateutil>=2.8.2 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from pandas->tensorflow_decision_forests) (2.9.0.post0)\r\n",
"Requirement already satisfied: pytz>=2020.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from pandas->tensorflow_decision_forests) (2024.1)\r\n",
"Requirement already satisfied: tzdata>=2022.7 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from pandas->tensorflow_decision_forests) (2024.1)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: rich in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from keras>=3.0.0->tensorflow~=2.16.1->tensorflow_decision_forests) (13.7.1)\r\n",
"Requirement already satisfied: namex in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from keras>=3.0.0->tensorflow~=2.16.1->tensorflow_decision_forests) (0.0.8)\r\n",
"Requirement already satisfied: optree in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from keras>=3.0.0->tensorflow~=2.16.1->tensorflow_decision_forests) (0.11.0)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: charset-normalizer<4,>=2 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from requests<3,>=2.21.0->tensorflow~=2.16.1->tensorflow_decision_forests) (3.3.2)\r\n",
"Requirement already satisfied: idna<4,>=2.5 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from requests<3,>=2.21.0->tensorflow~=2.16.1->tensorflow_decision_forests) (3.7)\r\n",
"Requirement already satisfied: urllib3<3,>=1.21.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from requests<3,>=2.21.0->tensorflow~=2.16.1->tensorflow_decision_forests) (2.2.1)\r\n",
"Requirement already satisfied: certifi>=2017.4.17 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from requests<3,>=2.21.0->tensorflow~=2.16.1->tensorflow_decision_forests) (2024.2.2)\r\n",
"Requirement already satisfied: markdown>=2.6.8 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorboard<2.17,>=2.16->tensorflow~=2.16.1->tensorflow_decision_forests) (3.6)\r\n",
"Requirement already satisfied: tensorboard-data-server<0.8.0,>=0.7.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorboard<2.17,>=2.16->tensorflow~=2.16.1->tensorflow_decision_forests) (0.7.2)\r\n",
"Requirement already satisfied: werkzeug>=1.0.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from tensorboard<2.17,>=2.16->tensorflow~=2.16.1->tensorflow_decision_forests) (3.0.2)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: importlib-metadata>=4.4 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from markdown>=2.6.8->tensorboard<2.17,>=2.16->tensorflow~=2.16.1->tensorflow_decision_forests) (7.1.0)\r\n",
"Requirement already satisfied: MarkupSafe>=2.1.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from werkzeug>=1.0.1->tensorboard<2.17,>=2.16->tensorflow~=2.16.1->tensorflow_decision_forests) (2.1.5)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: markdown-it-py>=2.2.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from rich->keras>=3.0.0->tensorflow~=2.16.1->tensorflow_decision_forests) (3.0.0)\r\n",
"Requirement already satisfied: pygments<3.0.0,>=2.13.0 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from rich->keras>=3.0.0->tensorflow~=2.16.1->tensorflow_decision_forests) (2.17.2)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Requirement already satisfied: zipp>=0.5 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from importlib-metadata>=4.4->markdown>=2.6.8->tensorboard<2.17,>=2.16->tensorflow~=2.16.1->tensorflow_decision_forests) (3.18.1)\r\n",
"Requirement already satisfied: mdurl~=0.1 in /tmpfs/src/tf_docs_env/lib/python3.9/site-packages (from markdown-it-py>=2.2.0->rich->keras>=3.0.0->tensorflow~=2.16.1->tensorflow_decision_forests) (0.1.2)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Using cached tensorflow_decision_forests-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (15.5 MB)\r\n",
"Using cached wurlitzer-3.0.3-py3-none-any.whl (7.3 kB)\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Installing collected packages: wurlitzer, tensorflow_decision_forests\r\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Successfully installed tensorflow_decision_forests-1.9.0 wurlitzer-3.0.3\r\n"
]
}
],
"source": [
"!pip install tensorflow_decision_forests wurlitzer"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "2LIE3UDMXeB4"
},
"source": [
"## Importing libraries"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:00.154628Z",
"iopub.status.busy": "2024-04-20T11:22:00.154336Z",
"iopub.status.idle": "2024-04-20T11:22:02.986156Z",
"shell.execute_reply": "2024-04-20T11:22:02.985360Z"
},
"id": "ue7Q-ysiPOmG"
},
"outputs": [],
"source": [
"import tensorflow_decision_forests as tfdf\n",
"\n",
"import os\n",
"import numpy as np\n",
"import pandas as pd\n",
"import tensorflow as tf\n",
"import math\n",
"import matplotlib.pyplot as plt"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "bN7quUfTXjaA"
},
"source": [
"The hidden code cell limits the output height in colab.\n"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {
"cellView": "form",
"execution": {
"iopub.execute_input": "2024-04-20T11:22:02.990709Z",
"iopub.status.busy": "2024-04-20T11:22:02.990282Z",
"iopub.status.idle": "2024-04-20T11:22:02.994892Z",
"shell.execute_reply": "2024-04-20T11:22:02.994252Z"
},
"id": "nFP4KJ79Xl3J"
},
"outputs": [],
"source": [
"#@title\n",
"\n",
"from IPython.core.magic import register_line_magic\n",
"from IPython.display import Javascript\n",
"from IPython.display import display as ipy_display\n",
"\n",
"# Some of the model training logs can cover the full\n",
"# screen if not compressed to a smaller viewport.\n",
"# This magic allows setting a max height for a cell.\n",
"@register_line_magic\n",
"def set_cell_height(size):\n",
" ipy_display(\n",
" Javascript(\"google.colab.output.setIframeHeight(0, true, {maxHeight: \" +\n",
" str(size) + \"})\"))"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:02.998078Z",
"iopub.status.busy": "2024-04-20T11:22:02.997778Z",
"iopub.status.idle": "2024-04-20T11:22:03.001400Z",
"shell.execute_reply": "2024-04-20T11:22:03.000741Z"
},
"id": "jnpiCdRKXvir"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Found TensorFlow Decision Forests v1.9.0\n"
]
}
],
"source": [
"# Check the version of TensorFlow Decision Forests\n",
"print(\"Found TensorFlow Decision Forests v\" + tfdf.__version__)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "9SqXMEGLX0ry"
},
"source": [
"## What is uplift modeling?\n",
"\n",
"[Uplift modeling](https://en.wikipedia.org/wiki/Uplift_modelling) is a statistical modeling technique to predict the **incremental impact of an action** on a subject. The action is often referred to as a **treatment** that may or may not be applied.\n",
"\n",
"Uplift modeling is often used in targeted marketing campaigns to predict the increase in the likelihood of a person making a purchase (or any other desired action) based on the marketing exposition they receive.\n",
"\n",
"For example, uplift modeling can predict the **effect** of an email. The effect is defined as the **conditional probability**\n",
"\\begin{align}\n",
"\\text{effect}(\\text{email}) = &\\Pr(\\text{outcome}=\\text{purchase}\\ \\vert\\ \\text{treatment}=\\text{with email})\\\\ &- \\Pr(\\text{outcome}=\\text{purchase} \\ \\vert\\ \\text{treatment}=\\text{no email}),\n",
"\\end{align}\n",
"where $\\Pr(\\text{outcome}=\\text{purchase}\\ \\vert\\ ...)$\n",
"is the probability of purchase depending on the receiving or not an email.\n",
"\n",
"Compare this to a classification model: With a classification model, one can predict the probability of a purchase. However, customers with a high probability are likely to spend money in the store regardless of whether or not they received an email.\n",
"\n",
"Similarly, one can use **numerical uplifting** to predict the numerical **increase in spend** when receiving an email. In comparison, a regression model can only increase the expected spend, which is a less useful metric in many cases.\n",
"\n",
"### Defining uplift models in TF-DF\n",
"\n",
"TF-DF expects uplifting datasets to be presented in a \"flat\" format.\n",
"A dataset of customers might look like this\n",
"\n",
"treatment | outcome | feature_1 | feature_2\n",
"--------- | ------- | --------- | ---------\n",
"0 | 1 | 0.1 | blue \n",
"0 | 0 | 0.2 | blue \n",
"1 | 1 | 0.3 | blue \n",
"1 | 1 | 0.4 | blue \n",
"\n",
"\n",
"The **treatment** is a binary variable indicating whether or not the example has received treatment. In the above example, the treatment indicates if the customer has received an email or not. The **outcome** (label) indicates the status of the example after receiving the treatment (or not). TF-DF supports categorical outcomes for categorical uplifting and numerical outcomes for numerical uplifting.\n",
"\n",
"**Note**: Uplifting is also frequently used in medical contexts. Here the *treatment* can be a medical treatment (e.g. administering a vaccine), the label can be an indicator of quality of life (e.g. whether the patient got sick). This also explains the nomenclature of uplift modeling."
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "kVaDog4ldPEY"
},
"source": [
"## Training an uplifting model\n",
"\n",
"In this example, we will use the *Hillstrom Email Marketing dataset*.\n",
"\n",
"This dataset contains 64,000 customers who last purchased within twelve months. The customers were involved in an e-mail test:\n",
"\n",
"- 1/3 were randomly chosen to receive an e-mail campaign featuring Mens merchandise.\n",
"- 1/3 were randomly chosen to receive an e-mail campaign featuring Womens merchandise.\n",
"- 1/3 were randomly chosen to not receive an e-mail campaign.\n",
"\n",
"During a period of two weeks following the e-mail campaign, results were tracked. The task is to tell if the Mens or Womens e-mail campaign was successful.\n",
"\n",
"Read more about dataset [in its documentation]( https://blog.minethatdata.com/2008/03/minethatdata-e-mail-analytics-and-data.html). This tutorial uses the dataset as curated by [TensorFlow Datasets](https://www.tensorflow.org/datasets/catalog/hillstrom)."
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:03.005071Z",
"iopub.status.busy": "2024-04-20T11:22:03.004780Z",
"iopub.status.idle": "2024-04-20T11:22:05.130141Z",
"shell.execute_reply": "2024-04-20T11:22:05.128804Z"
},
"id": "IKkNy8xedOb7"
},
"outputs": [],
"source": [
"# Install the TensorFlow Datasets package\n",
"!pip install tensorflow-datasets -U --quiet"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:05.134319Z",
"iopub.status.busy": "2024-04-20T11:22:05.134024Z",
"iopub.status.idle": "2024-04-20T11:22:09.092330Z",
"shell.execute_reply": "2024-04-20T11:22:09.091494Z"
},
"id": "1veZ9nJZPGsv"
},
"outputs": [
{
"name": "stderr",
"output_type": "stream",
"text": [
"2024-04-20 11:22:09.063782: W tensorflow/core/kernels/data/cache_dataset_ops.cc:858] The calling iterator did not fully read the dataset being cached. In order to avoid unexpected truncation of the dataset, the partially cached contents of the dataset will be discarded. This can happen if you have an input pipeline similar to `dataset.cache().take(k).repeat()`. You should use `dataset.take(k).cache().repeat()` instead.\n",
"2024-04-20 11:22:09.069098: W tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence\n"
]
},
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
channel
\n",
"
conversion
\n",
"
history
\n",
"
history_segment
\n",
"
mens
\n",
"
newbie
\n",
"
recency
\n",
"
segment
\n",
"
spend
\n",
"
visit
\n",
"
womens
\n",
"
zip_code
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
b'Web'
\n",
"
0
\n",
"
29.990000
\n",
"
b'1) $0 - $100'
\n",
"
1
\n",
"
0
\n",
"
6
\n",
"
b'Womens E-Mail'
\n",
"
0.0
\n",
"
0
\n",
"
0
\n",
"
b'Surburban'
\n",
"
\n",
"
\n",
"
1
\n",
"
b'Web'
\n",
"
0
\n",
"
150.380005
\n",
"
b'2) $100 - $200'
\n",
"
0
\n",
"
1
\n",
"
9
\n",
"
b'Womens E-Mail'
\n",
"
0.0
\n",
"
0
\n",
"
1
\n",
"
b'Surburban'
\n",
"
\n",
"
\n",
"
2
\n",
"
b'Phone'
\n",
"
0
\n",
"
602.960022
\n",
"
b'5) $500 - $750'
\n",
"
1
\n",
"
1
\n",
"
4
\n",
"
b'Womens E-Mail'
\n",
"
0.0
\n",
"
0
\n",
"
0
\n",
"
b'Surburban'
\n",
"
\n",
"
\n",
"
3
\n",
"
b'Multichannel'
\n",
"
0
\n",
"
341.010010
\n",
"
b'3) $200 - $350'
\n",
"
0
\n",
"
0
\n",
"
9
\n",
"
b'Womens E-Mail'
\n",
"
0.0
\n",
"
1
\n",
"
1
\n",
"
b'Urban'
\n",
"
\n",
"
\n",
"
4
\n",
"
b'Phone'
\n",
"
0
\n",
"
97.180000
\n",
"
b'1) $0 - $100'
\n",
"
0
\n",
"
1
\n",
"
3
\n",
"
b'Womens E-Mail'
\n",
"
0.0
\n",
"
1
\n",
"
1
\n",
"
b'Surburban'
\n",
"
\n",
"
\n",
"
5
\n",
"
b'Web'
\n",
"
0
\n",
"
83.269997
\n",
"
b'1) $0 - $100'
\n",
"
1
\n",
"
0
\n",
"
5
\n",
"
b'Mens E-Mail'
\n",
"
0.0
\n",
"
0
\n",
"
0
\n",
"
b'Urban'
\n",
"
\n",
"
\n",
"
6
\n",
"
b'Web'
\n",
"
0
\n",
"
331.170013
\n",
"
b'3) $200 - $350'
\n",
"
1
\n",
"
0
\n",
"
8
\n",
"
b'Womens E-Mail'
\n",
"
0.0
\n",
"
0
\n",
"
0
\n",
"
b'Surburban'
\n",
"
\n",
"
\n",
"
7
\n",
"
b'Multichannel'
\n",
"
0
\n",
"
628.400024
\n",
"
b'5) $500 - $750'
\n",
"
1
\n",
"
1
\n",
"
9
\n",
"
b'No E-Mail'
\n",
"
0.0
\n",
"
1
\n",
"
0
\n",
"
b'Surburban'
\n",
"
\n",
"
\n",
"
8
\n",
"
b'Phone'
\n",
"
0
\n",
"
134.610001
\n",
"
b'2) $100 - $200'
\n",
"
1
\n",
"
0
\n",
"
6
\n",
"
b'No E-Mail'
\n",
"
0.0
\n",
"
1
\n",
"
0
\n",
"
b'Rural'
\n",
"
\n",
"
\n",
"
9
\n",
"
b'Web'
\n",
"
0
\n",
"
141.210007
\n",
"
b'2) $100 - $200'
\n",
"
0
\n",
"
1
\n",
"
9
\n",
"
b'Mens E-Mail'
\n",
"
0.0
\n",
"
1
\n",
"
1
\n",
"
b'Surburban'
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" channel conversion history history_segment mens newbie \\\n",
"0 b'Web' 0 29.990000 b'1) $0 - $100' 1 0 \n",
"1 b'Web' 0 150.380005 b'2) $100 - $200' 0 1 \n",
"2 b'Phone' 0 602.960022 b'5) $500 - $750' 1 1 \n",
"3 b'Multichannel' 0 341.010010 b'3) $200 - $350' 0 0 \n",
"4 b'Phone' 0 97.180000 b'1) $0 - $100' 0 1 \n",
"5 b'Web' 0 83.269997 b'1) $0 - $100' 1 0 \n",
"6 b'Web' 0 331.170013 b'3) $200 - $350' 1 0 \n",
"7 b'Multichannel' 0 628.400024 b'5) $500 - $750' 1 1 \n",
"8 b'Phone' 0 134.610001 b'2) $100 - $200' 1 0 \n",
"9 b'Web' 0 141.210007 b'2) $100 - $200' 0 1 \n",
"\n",
" recency segment spend visit womens zip_code \n",
"0 6 b'Womens E-Mail' 0.0 0 0 b'Surburban' \n",
"1 9 b'Womens E-Mail' 0.0 0 1 b'Surburban' \n",
"2 4 b'Womens E-Mail' 0.0 0 0 b'Surburban' \n",
"3 9 b'Womens E-Mail' 0.0 1 1 b'Urban' \n",
"4 3 b'Womens E-Mail' 0.0 1 1 b'Surburban' \n",
"5 5 b'Mens E-Mail' 0.0 0 0 b'Urban' \n",
"6 8 b'Womens E-Mail' 0.0 0 0 b'Surburban' \n",
"7 9 b'No E-Mail' 0.0 1 0 b'Surburban' \n",
"8 6 b'No E-Mail' 0.0 1 0 b'Rural' \n",
"9 9 b'Mens E-Mail' 0.0 1 1 b'Surburban' "
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# Load the dataset\n",
"import tensorflow_datasets as tfds\n",
"raw_train, raw_test = tfds.load('hillstrom', split=['train[:80%]', 'train[20%:]'])\n",
"\n",
"# Display the first 10 examples of the test fold.\n",
"pd.DataFrame(list(raw_test.batch(10).take(1))[0])"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "5stnFbyKaIgn"
},
"source": [
"### Dataset preprocessing\n",
"\n",
"Since TF-DF currently only supports binary treatments, combine the \"Men's Email\" and the \"Women's Email\" campaign. This tutorial uses the binary variable `conversion` as outcome. This means that the problem is a **Categorical Uplifting** problem. If we were using the numerical variable `spend`, the problem would be a **Numerical Uplifting** problem."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:09.097644Z",
"iopub.status.busy": "2024-04-20T11:22:09.096961Z",
"iopub.status.idle": "2024-04-20T11:22:09.202788Z",
"shell.execute_reply": "2024-04-20T11:22:09.202170Z"
},
"id": "dLpAw7jibIrh"
},
"outputs": [],
"source": [
"def prepare_dataset(example):\n",
" # Use a binary treatment class.\n",
" example['treatment'] = 1 if example['segment'] == b'Mens E-Mail' or example['segment'] == b'Womens E-Mail' else 0\n",
" outcome = example['conversion']\n",
" # Restrict the dataset to the input features.\n",
" input_features = ['channel', 'history', 'mens', 'womens', 'newbie', 'recency', 'zip_code', 'treatment']\n",
" example = {feature: example[feature] for feature in input_features}\n",
" return example, outcome\n",
"\n",
"train_ds = raw_train.map(prepare_dataset).batch(100)\n",
"test_ds = raw_test.map(prepare_dataset).batch(100)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "Z-mtKmd-RoOu"
},
"source": [
"### Model training\n",
"\n",
"Finally, train and evaluate the model as usual. Note that TF-DF only supports Random Forest models for uplifting."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:09.206353Z",
"iopub.status.busy": "2024-04-20T11:22:09.205894Z",
"iopub.status.idle": "2024-04-20T11:22:20.891717Z",
"shell.execute_reply": "2024-04-20T11:22:20.890807Z"
},
"id": "-OZN8t8LRn38"
},
"outputs": [
{
"data": {
"application/javascript": [
"google.colab.output.setIframeHeight(0, true, {maxHeight: 300})"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Warning: The `num_threads` constructor argument is not set and the number of CPU is os.cpu_count()=32 > 32. Setting num_threads to 32. Set num_threads manually to use more than 32 cpus.\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"WARNING:absl:The `num_threads` constructor argument is not set and the number of CPU is os.cpu_count()=32 > 32. Setting num_threads to 32. Set num_threads manually to use more than 32 cpus.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Use /tmpfs/tmp/tmppyeh4gae as temporary training directory\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Reading training dataset...\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training tensor examples:\n",
"Features: {'channel': , 'history': , 'mens': , 'womens': , 'newbie': , 'recency': , 'zip_code': , 'treatment': }\n",
"Label: Tensor(\"data_8:0\", shape=(None,), dtype=int64)\n",
"Weights: None\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Normalized tensor features:\n",
" {'channel': SemanticTensor(semantic=, tensor=), 'history': SemanticTensor(semantic=, tensor=), 'mens': SemanticTensor(semantic=, tensor=), 'womens': SemanticTensor(semantic=, tensor=), 'newbie': SemanticTensor(semantic=, tensor=), 'recency': SemanticTensor(semantic=, tensor=), 'zip_code': SemanticTensor(semantic=, tensor=)}\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training dataset read in 0:00:04.974222. Found 51200 examples.\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Training model...\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Standard output detected as not visible to the user e.g. running in a notebook. Creating a training log redirection. If training gets stuck, try calling tfdf.keras.set_training_logs_redirection(False).\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.2334 UTC kernel.cc:771] Start Yggdrasil model training\n",
"[INFO 24-04-20 11:22:14.2335 UTC kernel.cc:772] Collect training examples\n",
"[INFO 24-04-20 11:22:14.2335 UTC kernel.cc:785] Dataspec guide:\n",
"column_guides {\n",
" column_name_pattern: \"^__LABEL$\"\n",
" type: CATEGORICAL\n",
"}\n",
"default_column_guide {\n",
" categorial {\n",
" max_vocab_count: 2000\n",
" }\n",
" discretized_numerical {\n",
" maximum_num_bins: 255\n",
" }\n",
"}\n",
"ignore_columns_without_guides: false\n",
"detect_numerical_as_discretized_numerical: false\n",
"\n",
"[INFO 24-04-20 11:22:14.2339 UTC kernel.cc:391] Number of batches: 512\n",
"[INFO 24-04-20 11:22:14.2339 UTC kernel.cc:392] Number of examples: 51200\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.2463 UTC kernel.cc:792] Training dataset:\n",
"Number of records: 51200\n",
"Number of columns: 9\n",
"\n",
"Number of columns by type:\n",
"\tNUMERICAL: 5 (55.5556%)\n",
"\tCATEGORICAL: 4 (44.4444%)\n",
"\n",
"Columns:\n",
"\n",
"NUMERICAL: 5 (55.5556%)\n",
"\t2: \"history\" NUMERICAL mean:241.833 min:29.99 max:3345.93 sd:255.292\n",
"\t3: \"mens\" NUMERICAL mean:0.550391 min:0 max:1 sd:0.497454\n",
"\t4: \"newbie\" NUMERICAL mean:0.503086 min:0 max:1 sd:0.49999\n",
"\t5: \"recency\" NUMERICAL mean:5.75514 min:1 max:12 sd:3.50281\n",
"\t7: \"womens\" NUMERICAL mean:0.549687 min:0 max:1 sd:0.497525\n",
"\n",
"CATEGORICAL: 4 (44.4444%)\n",
"\t0: \"__LABEL\" CATEGORICAL integerized vocab-size:3 no-ood-item\n",
"\t1: \"channel\" CATEGORICAL has-dict vocab-size:4 zero-ood-items most-frequent:\"Web\" 22576 (44.0938%)\n",
"\t6: \"treatment\" CATEGORICAL integerized vocab-size:3 no-ood-item\n",
"\t8: \"zip_code\" CATEGORICAL has-dict vocab-size:4 zero-ood-items most-frequent:\"Surburban\" 22966 (44.8555%)\n",
"\n",
"Terminology:\n",
"\tnas: Number of non-available (i.e. missing) values.\n",
"\tood: Out of dictionary.\n",
"\tmanually-defined: Attribute whose type is manually defined by the user, i.e., the type was not automatically inferred.\n",
"\ttokenized: The attribute value is obtained through tokenization.\n",
"\thas-dict: The attribute is attached to a string dictionary e.g. a categorical attribute stored as a string.\n",
"\tvocab-size: Number of unique values.\n",
"\n",
"[INFO 24-04-20 11:22:14.2464 UTC kernel.cc:808] Configure learner\n",
"[INFO 24-04-20 11:22:14.2466 UTC kernel.cc:822] Training config:\n",
"learner: \"RANDOM_FOREST\"\n",
"features: \"^channel$\"\n",
"features: \"^history$\"\n",
"features: \"^mens$\"\n",
"features: \"^newbie$\"\n",
"features: \"^recency$\"\n",
"features: \"^womens$\"\n",
"features: \"^zip_code$\"\n",
"label: \"^__LABEL$\"\n",
"task: CATEGORICAL_UPLIFT\n",
"random_seed: 123456\n",
"uplift_treatment: \"treatment\"\n",
"metadata {\n",
" framework: \"TF Keras\"\n",
"}\n",
"pure_serving_model: false\n",
"[yggdrasil_decision_forests.model.random_forest.proto.random_forest_config] {\n",
" num_trees: 300\n",
" decision_tree {\n",
" max_depth: 16\n",
" min_examples: 5\n",
" in_split_min_examples_check: true\n",
" keep_non_leaf_label_distribution: true\n",
" num_candidate_attributes: 0\n",
" missing_value_policy: GLOBAL_IMPUTATION\n",
" allow_na_conditions: false\n",
" categorical_set_greedy_forward {\n",
" sampling: 0.1\n",
" max_num_items: -1\n",
" min_item_frequency: 1\n",
" }\n",
" growing_strategy_local {\n",
" }\n",
" categorical {\n",
" cart {\n",
" }\n",
" }\n",
" axis_aligned_split {\n",
" }\n",
" internal {\n",
" sorting_strategy: PRESORTED\n",
" }\n",
" uplift {\n",
" min_examples_in_treatment: 5\n",
" split_score: KULLBACK_LEIBLER\n",
" }\n",
" }\n",
" winner_take_all_inference: true\n",
" compute_oob_performances: true\n",
" compute_oob_variable_importances: false\n",
" num_oob_variable_importances_permutations: 1\n",
" bootstrap_training_dataset: true\n",
" bootstrap_size_ratio: 1\n",
" adapt_bootstrap_size_ratio_for_maximum_training_duration: false\n",
" sampling_with_replacement: true\n",
"}\n",
"\n",
"[INFO 24-04-20 11:22:14.2469 UTC kernel.cc:825] Deployment config:\n",
"cache_path: \"/tmpfs/tmp/tmppyeh4gae/working_cache\"\n",
"num_threads: 32\n",
"try_resume_training: true\n",
"\n",
"[INFO 24-04-20 11:22:14.2472 UTC kernel.cc:887] Train model\n",
"[INFO 24-04-20 11:22:14.2473 UTC random_forest.cc:416] Training random forest on 51200 example(s) and 7 feature(s).\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:14.3731 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n",
"[INFO 24-04-20 11:22:14.3741 UTC random_forest.cc:802] Training of tree 1/300 (tree index:2) done qini:0.000172044 auuc:0.0025137\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:14.4012 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.4027 UTC random_forest.cc:802] Training of tree 15/300 (tree index:31) done qini:1.41341e-05 auuc:0.0023575\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:14.5302 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.5327 UTC random_forest.cc:802] Training of tree 25/300 (tree index:23) done qini:-2.19346e-05 auuc:0.00235455\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:14.6034 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.6058 UTC random_forest.cc:802] Training of tree 35/300 (tree index:33) done qini:0.00013211 auuc:0.0025086\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:14.6887 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.6910 UTC random_forest.cc:802] Training of tree 45/300 (tree index:45) done qini:-2.28572e-05 auuc:0.00235363\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:14.7656 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.7680 UTC random_forest.cc:802] Training of tree 55/300 (tree index:55) done qini:-8.67727e-05 auuc:0.00228972\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:14.8354 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.8379 UTC random_forest.cc:802] Training of tree 65/300 (tree index:56) done qini:-0.000112323 auuc:0.00226417\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:14.9052 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.9077 UTC random_forest.cc:802] Training of tree 75/300 (tree index:74) done qini:-0.000109942 auuc:0.00226655\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:14.9680 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:14.9704 UTC random_forest.cc:802] Training of tree 101/300 (tree index:101) done qini:-0.000112409 auuc:0.00226408\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:15.1148 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:15.1196 UTC random_forest.cc:802] Training of tree 121/300 (tree index:118) done qini:-0.000299795 auuc:0.00207669\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:15.2280 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:15.2305 UTC random_forest.cc:802] Training of tree 131/300 (tree index:138) done qini:-0.000153133 auuc:0.00222336\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:15.3108 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:15.3155 UTC random_forest.cc:802] Training of tree 141/300 (tree index:139) done qini:-0.000173194 auuc:0.0022033\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:15.3853 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:15.3877 UTC random_forest.cc:802] Training of tree 168/300 (tree index:162) done qini:-0.000130945 auuc:0.00224554\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:15.5471 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:15.5519 UTC random_forest.cc:802] Training of tree 178/300 (tree index:178) done qini:-0.000145457 auuc:0.00223103\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:15.6367 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:15.6414 UTC random_forest.cc:802] Training of tree 188/300 (tree index:189) done qini:-0.000124566 auuc:0.00225192\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:15.6876 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:15.6901 UTC random_forest.cc:802] Training of tree 217/300 (tree index:213) done qini:-0.000161956 auuc:0.00221453\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:15.8731 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:15.8795 UTC random_forest.cc:802] Training of tree 227/300 (tree index:229) done qini:-0.000133605 auuc:0.00224288\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:15.9403 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:15.9428 UTC random_forest.cc:802] Training of tree 237/300 (tree index:239) done qini:-0.000101549 auuc:0.00227494\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:16.0044 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.0068 UTC random_forest.cc:802] Training of tree 247/300 (tree index:253) done qini:-0.000141334 auuc:0.00223516\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:16.0749 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.0773 UTC random_forest.cc:802] Training of tree 257/300 (tree index:257) done qini:-0.000135416 auuc:0.00224107\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:16.1446 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.1471 UTC random_forest.cc:802] Training of tree 267/300 (tree index:261) done qini:-0.000131112 auuc:0.00224538\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:16.2109 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.2132 UTC random_forest.cc:802] Training of tree 277/300 (tree index:275) done qini:-0.000149751 auuc:0.00222674\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:16.2724 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.2746 UTC random_forest.cc:802] Training of tree 287/300 (tree index:283) done qini:-0.000168736 auuc:0.00220775\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:16.3282 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.3306 UTC random_forest.cc:802] Training of tree 297/300 (tree index:299) done qini:-0.000181665 auuc:0.00219482\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[WARNING 24-04-20 11:22:16.3623 UTC random_forest.cc:1105] Internal error: Non empty oob evaluation\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.3646 UTC random_forest.cc:802] Training of tree 300/300 (tree index:298) done qini:-0.000173258 auuc:0.00220323\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.3680 UTC random_forest.cc:882] Final OOB metrics: qini:-0.000173258 auuc:0.00220323\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.3843 UTC kernel.cc:919] Export model in log directory: /tmpfs/tmp/tmppyeh4gae with prefix 568256236db544eb\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.4274 UTC kernel.cc:937] Save model in resources\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.4309 UTC abstract_model.cc:881] Model self evaluation:\n",
"Number of predictions (without weights): 51200\n",
"Number of predictions (with weights): 51200\n",
"Task: CATEGORICAL_UPLIFT\n",
"Label: __LABEL\n",
"\n",
"Number of treatments: 2\n",
"AUUC: 0.00220323\n",
"Qini: -0.000173258\n",
"\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.4580 UTC kernel.cc:1233] Loading model from path /tmpfs/tmp/tmppyeh4gae/model/ with prefix 568256236db544eb\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"[INFO 24-04-20 11:22:16.6557 UTC decision_forest.cc:734] Model loaded with 300 root(s), 60190 node(s), and 7 input feature(s).\n",
"[INFO 24-04-20 11:22:16.6557 UTC abstract_model.cc:1344] Engine \"RandomForestGeneric\" built\n",
"[INFO 24-04-20 11:22:16.6557 UTC kernel.cc:1061] Use fast generic engine\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model trained in 0:00:02.442514\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Compiling model...\n"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"Model compiled.\n"
]
},
{
"data": {
"text/plain": [
""
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"%set_cell_height 300\n",
"\n",
"# Configure the model and its hyper-parameters.\n",
"model = tfdf.keras.RandomForestModel(\n",
" verbose=2,\n",
" task=tfdf.keras.Task.CATEGORICAL_UPLIFT,\n",
" uplift_treatment='treatment'\n",
")\n",
"\n",
"# Train the model.\n",
"model.fit(train_ds)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "XKhtZuLhGtv_"
},
"source": [
"# Evaluating Uplift models.\n",
"\n",
"## Metrics for Uplift models\n",
"\n",
"The two most important metrics for evaluating upift models are the **AUUC** (Area Under the Uplift Curve) metric and the **Qini** (Area Under the Qini Curve) metric. This is similar to the use of AUC and accuracy for classification problems. For both metrics, the larger they are, the better.\n",
"\n",
"Both AUUC and Qini are **not** normalized metrics. This means that the best possible value of the metric can vary from dataset to dataset. This is different from, for example, the AUC matric that always varies between 0 and 1.\n",
"\n",
"A formal definition of AUUC is below. For more information about these metrics, see [Guelman](https://diposit.ub.edu/dspace/bitstream/2445/65123/1/Leo%20Guelman_PhD_THESIS.pdf) and [Betlei et al.](https://arxiv.org/pdf/2012.09897.pdf)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "AMSpNTTZmuzv"
},
"source": [
"## Model Self-Evaluation\n",
"\n",
"TF-DF Random Forest models perform self-evaluation on the out-of-bag examples of the training dataset. For uplift models, they expose the AUUC and the Qini metric. You can directly retrieve the two metrics on the training dataset through the inspector\n",
"\n",
"Later, we are going to recompute the AUUC metric \"manually\" on the test dataset. Note that two metrics are not expected to be exactly equal (out-of-bag on train vs test) since the AUUC is not a normalized metric."
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:20.895624Z",
"iopub.status.busy": "2024-04-20T11:22:20.895358Z",
"iopub.status.idle": "2024-04-20T11:22:20.901523Z",
"shell.execute_reply": "2024-04-20T11:22:20.900814Z"
},
"id": "OsN1R9mT_8T6"
},
"outputs": [
{
"data": {
"text/plain": [
"Evaluation(num_examples=51200, accuracy=None, loss=None, rmse=None, ndcg=None, aucs=None, auuc=0.0022032308892709586, qini=-0.00017325819500263418)"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"# The self-evaluation is available through the model inspector\n",
"insp = model.make_inspector()\n",
"insp.evaluation()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "WErGZZ27HWJN"
},
"source": [
"## Manually computing the AUUC\n",
"\n",
"In this section, we manually compute the AUUC and plot the uplift curves.\n",
"\n",
"The next few paragraphs explain the AUUC metric in more detail and may be skipped.\n",
"\n",
"### Computing the AUUC\n",
"\n",
"Suppose you have a labeled dataset with $|T|$ examples with treatment and $|C|$ examples without treatment, called *control* examples. For each example, the uplift model $f$ produces the conditional probability that a treatment on the example will yield a positive outcome.\n",
"\n",
"Suppose a decision-maker needs to decide which clients to send an email using an uplift model $f$. The model produces a (conditional) probability that the email will result in a conversion. The decision-maker might therefore just pick the number $k$ of emails to send and send those $k$ emails to the clients with the highest probability.\n",
"\n",
"Using a labeled test dataset, it is possible to study the impact of $k$ on the success of the campaign. First, we are interested in the ratio $\\frac{|C \\cap T|}{|T|}$ of clients that received an email that converted versus total number of clients that received an email. Here $C$ is the set of clients that received an email and converted and $T$ is the total number of clients that received an email. We plot this ratio against $k$.\n",
"\n",
"Ideally, we like to have this curve increase steeply. This would mean that the model prioritizes sending email to those clients that will generate a conversion when receiving an email."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:20.905039Z",
"iopub.status.busy": "2024-04-20T11:22:20.904791Z",
"iopub.status.idle": "2024-04-20T11:22:26.270536Z",
"shell.execute_reply": "2024-04-20T11:22:26.269802Z"
},
"id": "xUGNWKkkkl-s"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\r",
" 1/512 [..............................] - ETA: 3:28"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
" 11/512 [..............................] - ETA: 2s "
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
" 21/512 [>.............................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
" 31/512 [>.............................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
" 41/512 [=>............................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
" 51/512 [=>............................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
" 61/512 [==>...........................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
" 71/512 [===>..........................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
" 81/512 [===>..........................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
" 90/512 [====>.........................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"100/512 [====>.........................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"110/512 [=====>........................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"120/512 [======>.......................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"130/512 [======>.......................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"140/512 [=======>......................] - ETA: 2s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"150/512 [=======>......................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"159/512 [========>.....................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"169/512 [========>.....................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"179/512 [=========>....................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"189/512 [==========>...................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"199/512 [==========>...................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"209/512 [===========>..................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"218/512 [===========>..................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"228/512 [============>.................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"238/512 [============>.................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"248/512 [=============>................] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"258/512 [==============>...............] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"268/512 [==============>...............] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"278/512 [===============>..............] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"288/512 [===============>..............] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"298/512 [================>.............] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"307/512 [================>.............] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"316/512 [=================>............] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"326/512 [==================>...........] - ETA: 1s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"336/512 [==================>...........] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"346/512 [===================>..........] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"356/512 [===================>..........] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"366/512 [====================>.........] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"376/512 [=====================>........] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"386/512 [=====================>........] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"396/512 [======================>.......] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"406/512 [======================>.......] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"416/512 [=======================>......] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"426/512 [=======================>......] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"436/512 [========================>.....] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"446/512 [=========================>....] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"456/512 [=========================>....] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"466/512 [==========================>...] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"476/512 [==========================>...] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"485/512 [===========================>..] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"495/512 [============================>.] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"505/512 [============================>.] - ETA: 0s"
]
},
{
"name": "stdout",
"output_type": "stream",
"text": [
"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\r",
"512/512 [==============================] - 3s 5ms/step\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"2024-04-20 11:22:25.165808: W tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence\n"
]
},
{
"name": "stderr",
"output_type": "stream",
"text": [
"2024-04-20 11:22:25.975008: W tensorflow/core/framework/local_rendezvous.cc:404] Local rendezvous is aborting with status: OUT_OF_RANGE: End of sequence\n"
]
},
{
"data": {
"text/plain": [
""
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/png": "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",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"# Compute all predictions on the test dataset\n",
"predictions = model.predict(test_ds).flatten()\n",
"# Extract outcomes and treatments\n",
"outcomes = np.concatenate([outcome.numpy() for _, outcome in test_ds])\n",
"treatment = np.concatenate([example['treatment'].numpy() for example,_ in test_ds])\n",
"control = 1 - treatment\n",
"\n",
"num_treatments = np.sum(treatment)\n",
"# Clients without treatment are called 'control' group\n",
"num_control = np.sum(control)\n",
"num_examples = len(predictions)\n",
"\n",
"# Sort labels and treatments according to predictions in descending order\n",
"prediction_order = predictions.argsort()[::-1]\n",
"outcomes_sorted = outcomes[prediction_order]\n",
"treatment_sorted = treatment[prediction_order]\n",
"control_sorted = control[prediction_order]\n",
"ratio_treatment = np.cumsum(np.multiply(outcomes_sorted, treatment_sorted), axis=0)/num_treatments\n",
"\n",
"fig, ax = plt.subplots()\n",
"ax.plot(ratio_treatment, label='Conversion ratio of treatment')\n",
"ax.set_xlabel('k')\n",
"ax.set_ylabel('Ratio of conversion')\n",
"ax.legend()"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "97IFpq5epHsx"
},
"source": [
"Similarly, we can also compute and plot the conversion ratio of those not receiving an email, called the *control group*. Ideally, this curve is initially flat: This would mean that the model does not prioritize sending emails to clients that will generate a conversion despite **not** receiving a email"
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:26.274521Z",
"iopub.status.busy": "2024-04-20T11:22:26.273808Z",
"iopub.status.idle": "2024-04-20T11:22:26.456834Z",
"shell.execute_reply": "2024-04-20T11:22:26.456209Z"
},
"id": "bIY-oA9alwzY"
},
"outputs": [
{
"data": {
"image/png": "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",
"text/plain": [
""
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"ratio_control = np.cumsum(np.multiply(outcomes_sorted, control_sorted), axis=0)/num_control\n",
"ax.plot(ratio_control, label='Conversion ratio of control')\n",
"ax.legend()\n",
"fig"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "q9MopM5MnCK0"
},
"source": [
"The AUUC metric measures the area between these two curves, normalizing the y-axis between 0 and 1"
]
},
{
"cell_type": "code",
"execution_count": 13,
"metadata": {
"execution": {
"iopub.execute_input": "2024-04-20T11:22:26.460538Z",
"iopub.status.busy": "2024-04-20T11:22:26.460120Z",
"iopub.status.idle": "2024-04-20T11:22:26.806300Z",
"shell.execute_reply": "2024-04-20T11:22:26.805590Z"
},
"id": "99XXGsq7nQgN"
},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"The AUUC on the test dataset is 0.007513928513572819\n"
]
},
{
"data": {
"image/png": "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O3Y0cMTmyZjr3LJlSwFAhde8efMaPnAzZOzP9P2YINWcsdf50KFDQmhoqKBSqQQ/Pz9h0aJFQmlpaQNHbX6Muc4lJSXC/PnzhVatWglqtVrQaDTClClThIyMjIYP3Izs3bu30v9zy67tuHHjhD59+lTYJzg4WFAqlYKfn5+wbt26eo1RJgisAyQiIiK6H/sgEREREZXDBImIiIioHCZIREREROUwQSIiIiIqhwkSERERUTlMkIiIiIjKYYJEREREVA4TJCIiIqJymCAREf2tb9++mDlzptRhEJEJYIJEREREVA4TJCIiIqJymCAREVVhx44dcHBwwMaNG6UOhYgamIXUARARmaJNmzbhxRdfxKZNmzBkyBCpwyGiBsYaJCKiclavXo0pU6bgp59+YnJE1ESxBomI6D7ffPMNUlNTcfDgQXTr1k3qcIhIIqxBIiK6T+fOneHq6oovvvgCgiBIHQ4RSYQJEhHRfVq1aoW9e/fihx9+wPTp06UOh4gkwiY2IqJy2rRpg71796Jv376wsLDAihUrpA6JiBoYEyQiokq0bdsWe/bsQd++faFQKLBs2TKpQyKiBiQT2MhOREREZIB9kIiIiIjKYYJEREREVA4TJCIiIqJymCARERERlcMEiYiIiKgcJkhERERE5TBBIiIiIiqHCRIRERFROUyQiIiIiMphgkRERERUDhMkIiIionL+H0JGDP/fanc9AAAAAElFTkSuQmCC",
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"x = np.linspace(0, 1, num_examples)\n",
"plt.plot(x,ratio_treatment, label='Conversion ratio of treatment')\n",
"plt.plot(x,ratio_control, label='Conversion ratio of control')\n",
"plt.fill_between(x, ratio_treatment, ratio_control, where=(ratio_treatment > ratio_control), color='C0', alpha=0.3)\n",
"plt.fill_between(x, ratio_treatment, ratio_control, where=(ratio_treatment < ratio_control), color='C1', alpha=0.3)\n",
"plt.xlabel('k')\n",
"plt.ylabel('Ratio of conversion')\n",
"plt.legend()\n",
"\n",
"# Approximate the integral of the difference between the two curves.\n",
"auuc = np.trapz(ratio_treatment-ratio_control, dx=1/num_examples)\n",
"print(f'The AUUC on the test dataset is {auuc}')"
]
}
],
"metadata": {
"colab": {
"name": "uplift_colab.ipynb",
"provenance": [],
"toc_visible": true
},
"kernelspec": {
"display_name": "Python 3",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.19"
}
},
"nbformat": 4,
"nbformat_minor": 0
}