├── data ├── gen_data.test.npz └── gen_data.train.npz ├── __pycache__ ├── MyNeuralNet.cpython-36.pyc ├── MyTrainer.cpython-36.pyc └── MyUtility.cpython-36.pyc ├── .idea ├── misc.xml ├── vcs.xml ├── modules.xml ├── MyCFRNet.iml └── workspace.xml ├── readMe ├── MyUtility.py ├── PrepareData.py ├── Run.py ├── MyNeuralNet.py └── MyTrainer.py /data/gen_data.test.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ankits0207/Learning-representations-for-counterfactual-inference-MyImplementation/HEAD/data/gen_data.test.npz -------------------------------------------------------------------------------- /data/gen_data.train.npz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ankits0207/Learning-representations-for-counterfactual-inference-MyImplementation/HEAD/data/gen_data.train.npz -------------------------------------------------------------------------------- /__pycache__/MyNeuralNet.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ankits0207/Learning-representations-for-counterfactual-inference-MyImplementation/HEAD/__pycache__/MyNeuralNet.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/MyTrainer.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ankits0207/Learning-representations-for-counterfactual-inference-MyImplementation/HEAD/__pycache__/MyTrainer.cpython-36.pyc -------------------------------------------------------------------------------- /__pycache__/MyUtility.cpython-36.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ankits0207/Learning-representations-for-counterfactual-inference-MyImplementation/HEAD/__pycache__/MyUtility.cpython-36.pyc -------------------------------------------------------------------------------- /.idea/misc.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /.idea/vcs.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /readMe: -------------------------------------------------------------------------------- 1 | This repo contains the neural network based counterfactual regression implementation for Ad attribution. Simulated data has been used as the input to PrepareData.py which would be followed by the execution of Run.py. 2 | Note: Create a results directory before executing Run.py. 3 | -------------------------------------------------------------------------------- /.idea/modules.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /.idea/MyCFRNet.iml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 11 | -------------------------------------------------------------------------------- /MyUtility.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import numpy as np 3 | 4 | 5 | class Parameter: 6 | def __init__(self, num_layers, input_dimensions, num_hidden_nodes, init_weights, p_ipm): 7 | self.num_layers = num_layers 8 | self.input_dimensions = input_dimensions 9 | self.num_hidden_nodes = num_hidden_nodes 10 | self.init_weights = init_weights 11 | self.p_ipm = p_ipm 12 | 13 | 14 | class Utility: 15 | @staticmethod 16 | def get_ipm(X, p, t): 17 | lbound = 1e-10 18 | it = tf.where(t > 0)[:, 0] 19 | ic = tf.where(t < 1)[:, 0] 20 | Xc = tf.gather(X, ic) 21 | Xt = tf.gather(X, it) 22 | mean_control = tf.reduce_mean(Xc, reduction_indices=0) 23 | mean_treated = tf.reduce_mean(Xt, reduction_indices=0) 24 | c = tf.square(2 * p - 1) * 0.25 25 | f = tf.sign(p - 0.5) 26 | mmd = tf.reduce_sum(tf.square(p * mean_treated - (1 - p) * mean_control)) 27 | mmd = f * (p - 0.5) + tf.sqrt(tf.clip_by_value(c + mmd, lbound, np.inf)) 28 | return mmd 29 | 30 | @staticmethod 31 | def load_data(fname): 32 | data_in = np.load(fname) 33 | data = {'x': data_in['x'], 't': data_in['t'], 'yf': data_in['yf'], 'ycf': data_in['ycf']} 34 | data['n'] = data['x'].shape[0] 35 | data['dim'] = data['x'].shape[1] 36 | return data -------------------------------------------------------------------------------- /PrepareData.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | from sklearn.model_selection import train_test_split 3 | import numpy as np 4 | 5 | experiments = 20 6 | 7 | df = pd.read_csv('D2.csv') 8 | train, test = train_test_split(df, test_size=0.3) 9 | 10 | splittedTrain = np.array_split(train, experiments) 11 | splittedTest = np.array_split(test, experiments) 12 | 13 | # Prepare train data 14 | xTrainList = [] 15 | yfTrainList = [] 16 | ycfTrainList = [] 17 | tTrainList = [] 18 | 19 | for trainSplit in splittedTrain: 20 | x = trainSplit[['bought_sim', 'bought_same', 'clicked', 'searched']].values 21 | yf = trainSplit[['buy']].values 22 | ycf = trainSplit[['buy_CF']].values 23 | t = trainSplit[['adv']].values 24 | xTrainList.append(x) 25 | yfTrainList.append(yf) 26 | ycfTrainList.append(ycf) 27 | tTrainList.append(t) 28 | 29 | xTrain = np.dstack(xTrainList) 30 | yfTrain = np.concatenate(yfTrainList, axis=1) 31 | ycfTrain = np.concatenate(ycfTrainList, axis=1) 32 | tTrain = np.concatenate(tTrainList, axis=1) 33 | np.savez('gen_data.train.npz', x=xTrain, yf=yfTrain, ycf=ycfTrain, t=tTrain) 34 | 35 | # Prepare test data 36 | xTestList = [] 37 | yfTestList = [] 38 | ycfTestList = [] 39 | tTestList = [] 40 | 41 | for testSplit in splittedTest: 42 | x = testSplit[['bought_sim', 'bought_same', 'clicked', 'searched']].values 43 | yf = testSplit[['buy']].values 44 | ycf = testSplit[['buy_CF']].values 45 | t = testSplit[['adv']].values 46 | xTestList.append(x) 47 | yfTestList.append(yf) 48 | ycfTestList.append(ycf) 49 | tTestList.append(t) 50 | 51 | xTest = np.dstack(xTestList) 52 | yfTest = np.concatenate(yfTestList, axis=1) 53 | ycfTest = np.concatenate(ycfTestList, axis=1) 54 | tTest = np.concatenate(tTestList, axis=1) 55 | np.savez('gen_data.test.npz', x=xTest, yf=yfTest, ycf=ycfTest, t=tTest) 56 | 57 | print('Done') 58 | -------------------------------------------------------------------------------- /Run.py: -------------------------------------------------------------------------------- 1 | import MyTrainer 2 | import numpy as np 3 | import pandas as pd 4 | from sklearn.model_selection import ParameterGrid 5 | 6 | # Fixed configuration section 7 | dataset = 'D2' 8 | num_layers = [2, 2] 9 | input_dimensions = 4 10 | num_hidden_nodes = [200, 100] 11 | init_weights = 0.01 12 | p_ipm = 0.5 13 | num_iter_per_decay = 100 14 | datadir = 'data/' 15 | train_file_name = 'gen_data.test.npz' 16 | test_file_name = 'gen_data.train.npz' 17 | outdir = 'results/' 18 | experiments = 20 19 | iterations = 200000 20 | batch_size = 100 21 | validation_size = 0.3 22 | 23 | # Grid search parameters 24 | dropout_range = np.linspace(0.5, 0.75, num=5) 25 | my_dropout_list = [] 26 | for e1 in dropout_range: 27 | for e2 in dropout_range: 28 | my_dropout_list.append([e1, e2]) 29 | my_alpha_list = np.linspace(0.001, 0.01, num=10) 30 | my_lambda_list = np.linspace(0.001, 0.01, num=10) 31 | my_l_rate_list = np.linspace(0.001, 0.01, num=10) 32 | my_l_rate_decay_list = np.linspace(0.8, 1, num=10) 33 | 34 | param_grid = { 35 | 'dropout': my_dropout_list, 36 | 'alpha': my_alpha_list, 37 | 'lambda': my_lambda_list, 38 | 'l_rate': my_l_rate_list, 39 | 'l_rate_decay': my_l_rate_decay_list 40 | } 41 | combinations = list(ParameterGrid(param_grid)) 42 | 43 | dropout_list = [] 44 | alpha_list = [] 45 | lambda_list = [] 46 | l_rate_list = [] 47 | l_rate_decay_list = [] 48 | train_f_error_list = [] 49 | train_cf_error_list = [] 50 | val_f_error_list = [] 51 | val_cf_error_list = [] 52 | ate_list = [] 53 | 54 | i = 0 55 | for combination in combinations: 56 | print('Evaluating ' + str(i) + ' out of ' + str(len(combinations)) + ' combinations...') 57 | result = MyTrainer.TrainCFRNet(num_layers, input_dimensions, num_hidden_nodes, init_weights, combination['dropout'], 58 | p_ipm, combination['alpha'], combination['lambda'], combination['l_rate'], 59 | combination['l_rate_decay'], num_iter_per_decay, datadir, train_file_name, 60 | test_file_name, outdir, experiments, iterations, batch_size, validation_size) 61 | dropout_list.append(str(combination['dropout'])) 62 | alpha_list.append(str(combination['alpha'])) 63 | lambda_list.append(str(combination['lambda'])) 64 | l_rate_list.append(str(combination['l_rate'])) 65 | l_rate_decay_list.append(str(combination['l_rate_decay'])) 66 | train_f_error_list.append(result.avg_train_f_error) 67 | train_cf_error_list.append(result.avg_train_cf_error) 68 | val_f_error_list.append(result.avg_val_f_error) 69 | val_cf_error_list.append(result.avg_val_cf_error) 70 | ate_list.append(result.ate) 71 | i += 1 72 | myDf = pd.DataFrame() 73 | myDf['Dropout'] = dropout_list 74 | myDf['Alpha'] = alpha_list 75 | myDf['Lambda'] = lambda_list 76 | myDf['Learning rate'] = l_rate_list 77 | myDf['Learning rate decay'] = l_rate_decay_list 78 | myDf['Train F error'] = train_f_error_list 79 | myDf['Train CF error'] = train_cf_error_list 80 | myDf['Val F error'] = val_f_error_list 81 | myDf['Val CF error'] = val_cf_error_list 82 | myDf['ATE'] = ate_list 83 | myDf.to_csv('Result' + dataset + '.csv', index=False) 84 | print('Done') 85 | -------------------------------------------------------------------------------- /MyNeuralNet.py: -------------------------------------------------------------------------------- 1 | import tensorflow as tf 2 | import numpy as np 3 | import MyUtility 4 | 5 | 6 | class MyNeuralNet(): 7 | def __init__(self, x, t, y_true, net_alpha, net_lambda, net_dropout_layer_set_1, net_dropout_layer_set_2, 8 | net_treatment_prob, params): 9 | self.x = x 10 | self.t = t 11 | self.y_true = y_true 12 | self.net_alpha = net_alpha 13 | self.net_lambda = net_lambda 14 | self.net_dropout_layer_set_1 = net_dropout_layer_set_1 15 | self.net_dropout_layer_set_2 = net_dropout_layer_set_2 16 | self.net_treatment_prob = net_treatment_prob 17 | 18 | self.variables = {} 19 | self.wd_loss = 0 20 | self._build_network(x, t, y_true, net_treatment_prob, net_alpha, net_lambda, net_dropout_layer_set_1, 21 | net_dropout_layer_set_2, params) 22 | 23 | # Adds a variable to the internal 'variables' dict with variable name as the key and variable expression as the 24 | # value 25 | def _add_variable(self, var, name): 26 | self.variables[name] = var 27 | 28 | # Create a variable 29 | def _create_variable(self, var, name): 30 | var = tf.Variable(var, name=name) 31 | self._add_variable(var, name) 32 | return var 33 | 34 | # Create a variable with an impact(l2 loss) over weight decay loss 35 | def _create_variable_with_weight_decay(self, initializer, name, wd): 36 | var = self._create_variable(initializer, name) 37 | self.wd_loss += wd*tf.nn.l2_loss(var) 38 | return var 39 | 40 | # The build network method which takes the feature vector, treatment, true output, treatment probability 41 | # and parameters as the input 42 | def _build_network(self, x, t, y_true, p_t,net_alpha, net_lambda, net_dropout_layer_set_1, net_dropout_layer_set_2, 43 | params): 44 | # Initialize weights and biases 45 | weights_in = [] 46 | biases_in = [] 47 | 48 | # Initializing the hypothesis with x 49 | h_in = [x] 50 | # Construct input layers 51 | for iter in range(params.num_layers[0]): 52 | # Configuring the first layer 53 | if iter == 0: 54 | weights_in.append(tf.Variable(tf.random_normal([params.input_dimensions, params.num_hidden_nodes[0]], 55 | stddev=params.init_weights / np.sqrt(params.input_dimensions)))) 56 | else: 57 | weights_in.append(tf.Variable(tf.random_normal([params.num_hidden_nodes[0], params.num_hidden_nodes[0]], 58 | stddev=params.init_weights / np.sqrt(params.num_hidden_nodes[0])))) 59 | biases_in.append(tf.Variable(tf.zeros([1, params.num_hidden_nodes[0]]))) 60 | z = tf.matmul(h_in[iter], weights_in[iter]) + biases_in[iter] 61 | h_in.append(tf.nn.relu(z)) 62 | h_in[iter+1] = tf.nn.dropout(h_in[iter+1], net_dropout_layer_set_1) 63 | h_rep = h_in[len(h_in)-1] 64 | 65 | # Construct output layers 66 | h_out = [tf.concat([h_rep, t], 1)] 67 | weights_out = [] 68 | biases_out = [] 69 | for iter in range(params.num_layers[1]): 70 | if iter == 0: 71 | w = tf.random_normal([h_out[0].shape[1].value, params.num_hidden_nodes[1]], 72 | stddev=params.init_weights / np.sqrt(h_out[0].shape[1].value)) 73 | weights_out.append(self._create_variable_with_weight_decay(w, 'w_out' + str(iter), 1.0)) 74 | else: 75 | w = tf.random_normal([params.num_hidden_nodes[1], params.num_hidden_nodes[1]], 76 | stddev=params.init_weights / np.sqrt(params.num_hidden_nodes[1])) 77 | weights_out.append(self._create_variable_with_weight_decay(w, 'w_out' + str(iter), 1.0)) 78 | biases_out.append(tf.Variable(tf.zeros([1, params.num_hidden_nodes[1]]))) 79 | z = tf.matmul(h_out[iter], weights_out[iter]) + biases_out[iter] 80 | h_out.append(tf.nn.relu(z)) 81 | h_out[iter+1] = tf.nn.dropout(h_out[iter+1], net_dropout_layer_set_2) 82 | 83 | # Get predictions 84 | weights_pred = self._create_variable(tf.Variable((tf.random_normal([params.num_hidden_nodes[1], 1], 85 | stddev=params.init_weights / np.sqrt(params.num_hidden_nodes[1])))), 'w_pred') 86 | bias_pred = self._create_variable(tf.Variable(tf.zeros([1])), 'b_pred') 87 | h_pred = h_out[-1] 88 | y_pred = tf.matmul(h_pred, weights_pred) + bias_pred 89 | 90 | # Compute risk 91 | w_t = t / (2 * p_t) 92 | w_c = (1 - t) / (2 * (1 - p_t)) 93 | sample_weight = w_t + w_c 94 | risk = tf.reduce_mean(sample_weight * tf.square(y_true - y_pred)) 95 | 96 | # Compute factual prediction error and IPM 97 | pred_error = tf.sqrt(tf.reduce_mean(tf.square(y_true - y_pred))) 98 | imb_error = MyUtility.Utility.get_ipm(h_rep, params.p_ipm, t) * net_alpha 99 | 100 | # Objective function to be minimized 101 | total_error = risk + imb_error + net_lambda * self.wd_loss 102 | 103 | # Setting output to variables 104 | self.output = y_pred # Prediction 105 | self.weights_in = weights_in # Weights of input network 106 | self.weights_out = weights_out # Weights of output network 107 | self.weights_pred = weights_pred # Prediction weights 108 | self.h_rep = h_rep # Phi 109 | self.tot_loss = total_error # Objective function to be minimised 110 | self.pred_loss = pred_error # Prediction loss 111 | self.imb_dist = imb_error # Imbalance between treatment and control distributions 112 | -------------------------------------------------------------------------------- /MyTrainer.py: -------------------------------------------------------------------------------- 1 | import os 2 | import random 3 | import datetime 4 | import MyUtility 5 | import MyNeuralNet 6 | import numpy as np 7 | import tensorflow as tf 8 | 9 | 10 | class TrainCFRNet: 11 | def __init__(self, num_layers, input_dimensions, num_hidden_nodes, init_weights, dropout, p_ipm, my_alpha, 12 | my_lambda, l_rate, l_rate_decay, num_iter_per_decay, datadir, train_file_name, test_file_name, outdir, 13 | experiments, iterations, batch_size, validation_size): 14 | # Load the data 15 | train = MyUtility.Utility.load_data(datadir + train_file_name) 16 | test = MyUtility.Utility.load_data(datadir + test_file_name) 17 | 18 | # Creating directory to save the results 19 | timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S-%f") 20 | outdir = outdir+timestamp+'/' 21 | os.mkdir(outdir) 22 | 23 | # Create tensorflow session object 24 | my_session = tf.Session() 25 | 26 | # Initialize input placeholders 27 | x = tf.placeholder("float", shape=[None, train['dim']], name='x') 28 | t = tf.placeholder("float", shape=[None, 1], name='t') 29 | y = tf.placeholder("float", shape=[None, 1], name='y') 30 | 31 | # Initialize parameter placeholders 32 | p_alpha = tf.placeholder("float", name='p_alpha') 33 | p_lambda = tf.placeholder("float", name='p_lambda') 34 | p_dropout_layer_set_1 = tf.placeholder("float", name='p_dropout_layer_set_1') 35 | p_dropout_layer_set_2 = tf.placeholder("float", name='p_dropout_layer_set_2') 36 | p_treatment_prob = tf.placeholder("float", name='p_treatment_prob') 37 | 38 | # Create parameters object and link parameter placeholders to MyNeuralNet 39 | params = MyUtility.Parameter(num_layers, input_dimensions, num_hidden_nodes, init_weights, p_ipm) 40 | # Create graph object 41 | my_nn = MyNeuralNet.MyNeuralNet(x, t, y, p_alpha, p_lambda, p_dropout_layer_set_1, p_dropout_layer_set_2, 42 | p_treatment_prob, params) 43 | 44 | # Setup optimizer 45 | my_step = tf.Variable(0, trainable=False) 46 | my_lr = tf.train.exponential_decay(l_rate, my_step, num_iter_per_decay, 47 | l_rate_decay, staircase=True) 48 | my_optimizer = tf.train.AdamOptimizer(my_lr) 49 | train_step = my_optimizer.minimize(my_nn.tot_loss, global_step=my_step) 50 | 51 | # Train/Val split 52 | row_count = train['x'].shape[0] 53 | valid_row_count = int(validation_size*row_count) 54 | train_row_count = row_count - valid_row_count 55 | indices = np.random.permutation(range(0, row_count)) 56 | train_indices = indices[:train_row_count] 57 | valid_indices = indices[train_row_count:] 58 | 59 | val = {'x': train['x'][valid_indices, :, :], 't': train['t'][valid_indices, :], 60 | 'yf': train['yf'][valid_indices, :], 'ycf': train['ycf'][valid_indices, :]} 61 | tr = {'x': train['x'][train_indices, :, :], 't': train['t'][train_indices, :], 62 | 'yf': train['yf'][train_indices, :], 'ycf': train['ycf'][train_indices, :]} 63 | 64 | # Averaged errors over all experiments 65 | avg_train_f_error = 0 66 | avg_train_cf_error = 0 67 | avg_val_f_error = 0 68 | avg_val_cf_error = 0 69 | 70 | # Create lists for losses 71 | predictions_from_all_experiments = [] 72 | for i in range(experiments): 73 | print('Experiment: ' + str(i) + ', training in progress! ') 74 | l, p = self.trainer(my_nn, my_session, train_step, tr, val, test, iterations, batch_size, i, dropout, 75 | my_alpha, my_lambda, train_row_count, valid_row_count) 76 | losses_at_convergence = l[-1:][0] 77 | avg_train_f_error += losses_at_convergence[1] 78 | avg_train_cf_error += losses_at_convergence[3] 79 | avg_val_f_error += losses_at_convergence[5] 80 | avg_val_cf_error += losses_at_convergence[7] 81 | predictions_from_all_experiments.append(p) 82 | self.avg_train_f_error = avg_train_f_error/experiments 83 | self.avg_train_cf_error = avg_train_cf_error/experiments 84 | self.avg_val_f_error = avg_val_f_error/experiments 85 | self.avg_val_cf_error = avg_val_cf_error/experiments 86 | self.ate = self.get_ate(test, predictions_from_all_experiments) 87 | my_session.close() 88 | tf.reset_default_graph() 89 | 90 | def trainer(self, network, session, training_step, train_data, validation_data, test_data, iterations, batch_size, 91 | exp_id, dropout, my_alpha, my_lambda, train_row_count, valid_row_count): 92 | treat_prob = np.mean(train_data['t']) 93 | 94 | # Setup dictionary to be fed 95 | dict_factual = {network.x: train_data['x'][:, :, exp_id], network.t: train_data['t'][:, exp_id].reshape(train_row_count, 1), 96 | network.y_true: train_data['yf'][:, exp_id].reshape(train_row_count, 1), network.net_alpha: my_alpha, 97 | network.net_lambda: my_lambda, network.net_treatment_prob: treat_prob, 98 | network.net_dropout_layer_set_1: dropout[0], network.net_dropout_layer_set_2: dropout[1]} 99 | dict_counter_factual = {network.x: train_data['x'][:, :, exp_id], network.t: 1 - train_data['t'][:, exp_id].reshape(train_row_count, 1), 100 | network.y_true: train_data['ycf'][:, exp_id].reshape(train_row_count, 1), 101 | network.net_dropout_layer_set_1: dropout[0], network.net_dropout_layer_set_2: dropout[1]} 102 | dict_valid_factual = {network.x: validation_data['x'][:, :, exp_id], network.t: validation_data['t'][:, exp_id].reshape(valid_row_count, 1), 103 | network.y_true: validation_data['yf'][:, exp_id].reshape(valid_row_count, 1), network.net_alpha: my_alpha, 104 | network.net_lambda: my_lambda, network.net_treatment_prob: treat_prob, 105 | network.net_dropout_layer_set_1: dropout[0], network.net_dropout_layer_set_2: dropout[1]} 106 | dict_valid_counter_factual = {network.x: validation_data['x'][:, :, exp_id], network.t: 1 - validation_data['t'][:, exp_id].reshape(valid_row_count, 1), 107 | network.y_true: validation_data['ycf'][:, exp_id].reshape(valid_row_count, 1), network.net_dropout_layer_set_1: dropout[0], 108 | network.net_dropout_layer_set_2: dropout[1]} 109 | 110 | # Initialize tensorflow variables 111 | session.run(tf.global_variables_initializer()) 112 | 113 | # Losses 114 | losses=[] 115 | 116 | # Predictions 117 | preds = [] 118 | 119 | # Convergence configuration 120 | gap = 0.05 121 | convergence_iterations = 1500 122 | train_f_list = [] 123 | train_cf_list = [] 124 | val_f_list = [] 125 | val_cf_list = [] 126 | 127 | # Train for multiple iterations 128 | for i in range(iterations): 129 | batch_indices = random.sample(range(0, train_row_count), batch_size) 130 | x_batch = train_data['x'][:, :, exp_id][batch_indices, :] 131 | t_batch = train_data['t'][:, exp_id][batch_indices] 132 | y_batch = train_data['yf'][:, exp_id][batch_indices] 133 | 134 | session.run(training_step, feed_dict={network.x: x_batch, network.t: t_batch.reshape(batch_size, 1), network.y_true: y_batch.reshape(batch_size, 1), 135 | network.net_alpha: my_alpha, network.net_lambda: my_lambda, network.net_treatment_prob: treat_prob, 136 | network.net_dropout_layer_set_1: dropout[0], network.net_dropout_layer_set_2: dropout[1]}) 137 | 138 | # Loss 139 | obj, f_error, imb_error = session.run([network.tot_loss, network.pred_loss, network.imb_dist], 140 | feed_dict=dict_factual) 141 | cf_error = session.run(network.pred_loss, feed_dict=dict_counter_factual) 142 | valid_obj, valid_f_error, valid_imb = session.run([network.tot_loss, network.pred_loss, 143 | network.imb_dist], feed_dict=dict_valid_factual) 144 | valid_cf_error = session.run(network.pred_loss, feed_dict=dict_valid_counter_factual) 145 | 146 | losses.append([obj, f_error, imb_error, cf_error, valid_obj, valid_f_error, valid_imb, valid_cf_error]) 147 | loss_str = str(i) + ' Obj: ' + str(obj) + ' Fact: ' + str(f_error) + ' CFact: ' \ 148 | + str(cf_error) + ' Imb: ' + str(imb_error) + ' VObj: ' + str(valid_obj) \ 149 | + ' VFact: ' + str(valid_f_error) + ' VCFact: ' + str(valid_cf_error) + ' VImb: ' + \ 150 | str(valid_imb) 151 | 152 | # Populating lists for checking convergence 153 | train_f_list.append(f_error) 154 | train_cf_list.append(cf_error) 155 | val_f_list.append(valid_f_error) 156 | val_cf_list.append(valid_cf_error) 157 | 158 | # Prediction 159 | test_size = test_data['x'].shape[0] 160 | y_pred_f_test = session.run(network.output, feed_dict={network.x: test_data['x'][:, :, exp_id], 161 | network.t: test_data['t'][:, exp_id].reshape( 162 | test_size, 1), 163 | network.net_dropout_layer_set_1: dropout[0], 164 | network.net_dropout_layer_set_2: dropout[1]}) 165 | y_pred_cf_test = session.run(network.output, feed_dict={network.x: test_data['x'][:, :, exp_id], 166 | network.t: 1 - test_data['t'][:, exp_id].reshape( 167 | test_size, 1), 168 | network.net_dropout_layer_set_1: dropout[0], 169 | network.net_dropout_layer_set_2: dropout[1]}) 170 | predictions = np.concatenate((y_pred_f_test, y_pred_cf_test), axis=1) 171 | preds.append(predictions) 172 | 173 | convergence_tracker = self.check_convergence([train_f_list, train_cf_list, val_f_list, val_cf_list], 174 | convergence_iterations, gap) 175 | # Check convergence over 1000 iterations 176 | if convergence_tracker: 177 | loss_str += ' Converged' 178 | print(loss_str) 179 | break 180 | if i == iterations - 1: 181 | loss_str += ' Iteration overshoot' 182 | print(loss_str) 183 | break 184 | if i % 250 == 0: 185 | print(loss_str) 186 | return losses, preds 187 | 188 | def check_convergence(self, losses, convergence_iterations, gap): 189 | if len(losses[0]) >= convergence_iterations: 190 | f = losses[0][(-1*convergence_iterations):] 191 | cf = losses[1][(-1*convergence_iterations):] 192 | vf = losses[2][(-1*convergence_iterations):] 193 | vcf = losses[3][(-1*convergence_iterations):] 194 | variations_f = max(f) - min(f) 195 | variations_cf = max(cf) - min(cf) 196 | variations_vf = max(vf) - min(vf) 197 | variations_vcf = max(vcf) - min(vcf) 198 | if variations_f <= gap and variations_cf <= gap and variations_vf <= gap and variations_vcf <= gap: 199 | return True 200 | else: 201 | return False 202 | else: 203 | return False 204 | 205 | def get_ate(self, test, predictions): 206 | factualGroundTruth = test['yf'] 207 | treatment = test['t'] 208 | ate_treatment = 0 209 | ate_control = 0 210 | for i in range(len(predictions)): 211 | t = treatment[:, i] 212 | zeroIndices = np.where(t == 0)[0].tolist() 213 | nonZeroIndices = np.where(t == 1)[0].tolist() 214 | 215 | f = factualGroundTruth[:, i] 216 | pcf = predictions[i][-1:][0][:, 1] 217 | 218 | # If t = 0(factual) 219 | a = np.take(pcf, zeroIndices) 220 | b = np.take(f, zeroIndices) 221 | diff = a - b 222 | ate_control += np.mean(diff) 223 | 224 | # If t = 1(factual) 225 | a = np.take(f, nonZeroIndices) 226 | b = np.take(pcf, nonZeroIndices) 227 | diff = a - b 228 | ate_treatment += np.mean(diff) 229 | return (ate_control/len(predictions)+ate_treatment/len(predictions))/2 230 | -------------------------------------------------------------------------------- /.idea/workspace.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 57 | 58 | 59 | 60 | params 61 | run 62 | imb_err 63 | p_trea 64 | num_layers 65 | num_hidden_nodes 66 | dropout 67 | shape 68 | np.sqrt 69 | f 70 | train_data 71 | my_alpha 72 | cf 73 | losses 74 | 75 | 76 | 77 | 79 | 80 | 93 | 94 | 95 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 |