<jupyter_start><jupyter_text>Qiita ~ 傾向スコアを用いて観察データからUpliftをモデリングする~<jupyter_code>import numpy as np
import pandas as pd
import sklearn
import statsmodels.api as sm
import random
import sys
sys.path.append("/home/yuta_saito/notebook/qiita/uplift-modeling/uplift_tools/")
from metrics import *

from operator import itemgetter
from pandas import DataFrame, Series
from plotly.offline import iplot, plot, init_notebook_mode
from plotly.graph_objs import Histogram, Box, Scatter, Figure, Layout, Bar

from sklearn.cross_validation import train_test_split, cross_val_score, StratifiedKFold
from sklearn.decomposition import PCA
from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor
from sklearn.feature_selection import SelectFromModel, SelectKBest
from sklearn.kernel_ridge import KernelRidge
from sklearn.linear_model import LogisticRegression, LinearRegression, ElasticNet, Ridge
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score, roc_curve, auc, confusion_matrix, precision_recall_curve
from sklearn.model_selection import KFold, TimeSeriesSplit, GridSearchCV, RandomizedSearchCV
from sklearn.preprocessing import StandardScaler, RobustScaler, Normalizer
from sklearn.pipeline import Pipeline
from sklearn.svm import SVR, LinearSVR<jupyter_output><empty_output><jupyter_text>Regression Uplift Modeling ~ Separate Model Approach ~<jupyter_code># データの読み込み
data_df = pd.read_csv('https://github.com/iwanami-datascience/vol3/raw/master/kato%26hoshino/q_data_x.csv')
#data_df.head()
# 説明変数と目的変数を指定
cols = ["child_dummy", "area_kanto", "area_tokai", "area_keihanshin",
        "T", "F1", "F2", "F3", "M1", "M2"]

X = data_df[cols]
y = DataFrame(data_df.gamesecond)
# CMありをtreatment, CMなしをcontrolとする
treat = (data_df.cm_dummy == 1).tolist()
# train, test半分ずつに分ける
y_train, y_test, train_treat, test_treat, X_train, X_test = train_test_split(y.values, treat, X, test_size=0.5, random_state=2)
# indexをリセット
X_train = X_train.reset_index(drop=True)
X_test = X_test.reset_index(drop=True)
# Separate Model Approach
# 学習用に用いるデータを生成
num = len(y_train)
treat_y = np.reshape(np.array([y_train[i] for i in range(num) if train_treat[i] is True]), -1)
control_y = np.reshape(np.array([y_test[i] for i in range(num) if train_treat[i] is False]), -1)
treat_X = DataFrame([X_train.loc[i] for i in range(num) if train_treat[i] is True])
control_X = DataFrame([X_train.loc[i] for i in range(num) if train_treat[i] is False])
# ランダムフォレスト回帰を用いる
params_rf = {"max_depth": [10, 50, 100, 200, 500]}
gs_rf_treat = GridSearchCV(RandomForestRegressor(n_estimators=500),
                           param_grid=params_rf, cv=5)
gs_rf_control = GridSearchCV(RandomForestRegressor(n_estimators=500),
                             param_grid=params_rf, cv=5)

# 介入群と非介入群それぞれでパラメータチューニング及びスマホアプリ利用時間を予測するモデルを構築
gs_rf_treat.fit(treat_X, treat_y)
gs_rf_control.fit(control_X, control_y)
# uplift-scoreの算出
# CMを見た場合のアプリ利用時間
pred_treat = gs_rf_treat.predict(X_test)

# CMを見なかった場合のアプリ利用時間
pred_control = gs_rf_control.predict(X_test)

# 今回は、(CMを見た場合のアプリ利用時間) - (CMを見なかった場合のアプリ利用時間) をuplift_scoreとする。
uplift_score = pred_treat - pred_control
uplift_df = uplift_frame_reg(y_test.T.tolist()[0], test_treat, uplift_score)
#uplift_curve(uplift_df)
lr = LinearRegression()
lr.fit(X_test, uplift_score)
for feature, coef in zip(X_train.columns, lr.coef_):
    print(f"{feature} / {round(coef, 4)}")<jupyter_output>child_dummy / 929.3386
area_kanto / -1396.441
area_tokai / -3068.5063
area_keihanshin / 635.3306
T / 12180.1861
F1 / 1299.7327
F2 / 1779.0302
F3 / 895.7932
M1 / 2782.9887
M2 / 3498.1391<jupyter_text>Uplift Modeling ~Transformed Outcome Tree Model~<jupyter_code># データの読み込み
data_df = pd.read_csv('https://github.com/iwanami-datascience/vol3/raw/master/kato%26hoshino/q_data_x.csv')
#data_df.head()
# 傾向スコアを求める
# 説明変数
cols_ = ["age", "sex", "TVwatch_day", "marry_dummy", "child_dummy", "inc", "pmoney",
         "area_kanto", "area_tokai", "area_keihanshin",
         "job_dummy1", "job_dummy2", "job_dummy3", "job_dummy4", "job_dummy5", "job_dummy6",
         "fam_str_dummy1", "fam_str_dummy2", "fam_str_dummy3", "fam_str_dummy4"]

X_ = data_df[cols_].copy()

# 切片の導入
X_.loc[:, "Intercept"] = 1

# CM視聴有無ダミー
z1 = data_df.cm_dummy
# StatsModelsのLogitにより傾向スコアを推定
glm = sm.Logit(z1, X_)
result = glm.fit()
ps = result.predict(X_)
#ps
# Propensity Scoreで補正された目的変数のカラムを作成
data_df.loc[:, "ps"] = ps
data_df.loc[:, "adj_gamesecond"] = 0
data_df.loc[data_df.cm_dummy == 1, "adj_gamesecond"] = data_df.loc[data_df.cm_dummy == 1, "gamesecond"] / data_df.loc[data_df.cm_dummy == 1, "ps"]
data_df.loc[data_df.cm_dummy == 0, "adj_gamesecond"] = -data_df.loc[data_df.cm_dummy == 0, "gamesecond"] / (1 - data_df.loc[data_df.cm_dummy == 0, "ps"])
adj_y = data_df[["gamesecond", "adj_gamesecond"]]
# CMありをtreatment, CMなしをcontrolとする
treat = (data_df.cm_dummy == 1).tolist()
# train, test半分ずつに分ける
adj_y_train, adj_y_test, train_treat, test_treat, X_train, X_test = train_test_split(adj_y, treat, X, test_size=0.5, random_state=2)
# indexをリセット
X_train = X_train.reset_index(drop=True)
X_test = X_test.reset_index(drop=True)
adj_y_train = adj_y_train.reset_index(drop=True)
adj_y_test = adj_y_test.reset_index(drop=True)
# ランダムフォレスト回帰を用いる
params_rf = {"max_depth": [10, 50, 100, 200, 500]}
gs_rf = GridSearchCV(RandomForestRegressor(n_estimators=500), param_grid=params_rf, cv=5)

# パラメータチューニング及び補正スマホアプリ利用時間を予測するモデルを構築
gs_rf.fit(X_train, adj_y_train.adj_gamesecond)

# 補正uplift_scoreを求める
adj_uplift_score = gs_rf.predict(X_test)
adj_uplift_df = uplift_frame_reg(adj_y_test.gamesecond.tolist(), test_treat, adj_uplift_score)
#uplift_curve(adj_uplift_df, "Adj-Uplift Score")
lr = LinearRegression()
lr.fit(X_train, gs_rf.predict(X_train))
for feature, coef in zip(X_train.columns, lr.coef_):
    print(f"{feature} / {round(coef, 4)}")<jupyter_output>child_dummy / -7845.8122
area_kanto / -2572.0754
area_tokai / -4473.9973
area_keihanshin / 11648.8147
T / 4738.0588
F1 / 465.9719
F2 / 3207.2909
F3 / -630.0232
M1 / -5634.8067
M2 / 11468.2376
StarcoderdataJupyterStructuredCleanDedup