<jupyter_start><jupyter_text>Uplift Tree Visualization  IntroductionThis example notebooks illustrates how to visualize uplift trees for interpretation and diagnosis.  Supported ModelsThese visualization functions work only for tree-based algorithms:- Uplift tree/random forests on KL divergence, Euclidean Distance, and Chi-Square- Uplift tree/random forests on Contextual Treatment SelectionCurrently, they are NOT supporting Meta-learner algorithms- S-learner- T-learner- X-learner- R-learner Supported UsageThis notebook will show how to use visualization for:- Uplift Tree and Uplift Random Forest    - Visualize a trained uplift classification tree model    - Visualize an uplift tree in a trained uplift random forests- Training and Validation Data    - Visualize the validation tree: fill the trained uplift classification tree with validation (or testing) data, and show the statistics for both training data and validation data    - One Treatment Group and Multiple Treatment Groups    - Visualize the case where there are one control group and one treatment group    - Visualize the case where there are one control group and multiple treatment groups  Step 1 Load Modules  Load CausalML modules<jupyter_code>from causalml.dataset import make_uplift_classification
from causalml.inference.tree import UpliftTreeClassifier, UpliftRandomForestClassifier
from causalml.inference.tree import uplift_tree_string, uplift_tree_plot<jupyter_output><empty_output><jupyter_text>Load standard modules<jupyter_code>import numpy as np
import pandas as pd
from IPython.display import Image
from sklearn.model_selection import train_test_split<jupyter_output><empty_output><jupyter_text>One Control + One Treatment for Uplift Classification Tree<jupyter_code># Data generation
df, x_names = make_uplift_classification()

df.head()

df = df[df['treatment_group_key'].isin(['control','treatment1'])]

# Look at the conversion rate and sample size in each group
df.pivot_table(values='conversion',
               index='treatment_group_key',
               aggfunc=[np.mean, np.size],
               margins=True)
# Split data to training and testing samples for model validation (next section)
df_train, df_test = train_test_split(df, test_size=0.2, random_state=111)

# Train uplift tree
uplift_model = UpliftTreeClassifier(max_depth = 5, min_samples_leaf = 200, min_samples_treatment = 50, n_reg = 100, evaluationFunction='KL', control_name='control')

uplift_model.fit(df_train[x_names].values,
                 treatment=df_train['treatment_group_key'].values,
                 y=df_train['conversion'].values)
# Print uplift tree as a string
result = uplift_tree_string(uplift_model.fitted_uplift_tree, x_names)<jupyter_output>x18_uplift_increase >= -1.3039248112755226?
yes -> x1_informative >= -0.8277030695336565?
		yes -> x7_irrelevant >= -0.5541554186274725?
				yes -> x19_increase_mix >= -0.782381242022013?
						yes -> {'treatment1': 0.526316, 'control': 0.541667}
						no  -> {'treatment1': 0.618644, 'control': 0.43609}
				no  -> {'treatment1': 0.503067, 'control': 0.5}
		no  -> {'treatment1': 0.438017, 'control': 0.548148}
no  -> {'treatment1': 0.413174, 'control': 0.529412}<jupyter_text>Read the tree- First line: node split condition- impurity: the value for the loss function- total_sample: total sample size in this node- group_sample: sample size by treatment group- uplift score: the treatment effect between treatment and control (when there are multiple treatment groups, this is the maximum of the treatment effects)- uplift p_value: the p_value for the treatment effect- validation uplift score: when validation data is filled in the tree, this reflects the uplift score based on the - validation data. It can be compared with the uplift score (for training data) to check if there are over-fitting issue.<jupyter_code># Plot uplift tree
graph = uplift_tree_plot(uplift_model.fitted_uplift_tree,x_names)
Image(graph.create_png())<jupyter_output><empty_output><jupyter_text>Visualize Validation Tree: One Control + One Treatment for Uplift Classification TreeNote the validation uplift score will update.<jupyter_code>### Fill the trained tree with testing data set 
# The uplift score based on testing dataset is shown as validation uplift score in the tree nodes
uplift_model.fill(X=df_test[x_names].values, treatment=df_test['treatment_group_key'].values, y=df_test['conversion'].values)

# Plot uplift tree
graph = uplift_tree_plot(uplift_model.fitted_uplift_tree,x_names)
Image(graph.create_png())<jupyter_output><empty_output><jupyter_text>Visualize a Tree in Random Forest<jupyter_code># Split data to training and testing samples for model validation (next section)
df_train, df_test = train_test_split(df, test_size=0.2, random_state=111)

# Train uplift tree
uplift_model = UpliftRandomForestClassifier(n_estimators=5, max_depth = 5, min_samples_leaf = 200, min_samples_treatment = 50, n_reg = 100, evaluationFunction='KL', control_name='control')

uplift_model.fit(df_train[x_names].values,
                 treatment=df_train['treatment_group_key'].values,
                 y=df_train['conversion'].values)
# Specify a tree in the random forest (the index can be any integer from 0 to n_estimators-1)
uplift_tree = uplift_model.uplift_forest[0]
# Print uplift tree as a string
result = uplift_tree_string(uplift_tree.fitted_uplift_tree, x_names)
# Plot uplift tree
graph = uplift_tree_plot(uplift_tree.fitted_uplift_tree,x_names)
Image(graph.create_png())<jupyter_output><empty_output><jupyter_text>Fill the tree with validation data<jupyter_code>### Fill the trained tree with testing data set 
# The uplift score based on testing dataset is shown as validation uplift score in the tree nodes
uplift_tree.fill(X=df_test[x_names].values, treatment=df_test['treatment_group_key'].values, y=df_test['conversion'].values)

# Plot uplift tree
graph = uplift_tree_plot(uplift_tree.fitted_uplift_tree,x_names)
Image(graph.create_png())<jupyter_output><empty_output><jupyter_text>One Control + Multiple Treatments<jupyter_code># Data generation
df, x_names = make_uplift_classification()
# Look at the conversion rate and sample size in each group
df.pivot_table(values='conversion',
               index='treatment_group_key',
               aggfunc=[np.mean, np.size],
               margins=True)
# Split data to training and testing samples for model validation (next section)
df_train, df_test = train_test_split(df, test_size=0.2, random_state=111)

# Train uplift tree
uplift_model = UpliftTreeClassifier(max_depth = 3, min_samples_leaf = 200, min_samples_treatment = 50, n_reg = 100, evaluationFunction='KL', control_name='control')

uplift_model.fit(df_train[x_names].values,
                 treatment=df_train['treatment_group_key'].values,
                 y=df_train['conversion'].values)
# Plot uplift tree
# The uplift score represents the best uplift score among all treatment effects
graph = uplift_tree_plot(uplift_model.fitted_uplift_tree,x_names)
Image(graph.create_png())<jupyter_output><empty_output><jupyter_text>Save the Plot<jupyter_code># Save the graph as pdf
graph.write_pdf("tbc.pdf")
# Save the graph as png
graph.write_png("tbc.png")<jupyter_output><empty_output>
{'fraction_non_alphanumeric': 0.08291805094130676, 'fraction_numerical': 0.02630121816168328, 'mean_word_length': 5.616300366300366, 'pattern_counts': {'":': 0, '<': 36, '<?xml version=': 0, '>': 48, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '9', 'dir': 'jupyter-structured-clean-dedup', 'id': '197899', 'license': 'Apache-2.0', 'n_tokens_mistral': 2433, 'n_tokens_neox': 2171, 'n_words': 650, 'path': 'examples/uplift_tree_visualization.ipynb', 'repo_name': 'TomaszZamacinski/causalml', 'size': '7224'}