Code Monkey home page Code Monkey logo

cfrnet's Introduction

cfrnet

Counterfactual regression (CFR) by learning balanced representations, as developed by Johansson, Shalit & Sontag (2016) and Shalit, Johansson & Sontag (2016). cfrnet is implemented in Python using TensorFlow 0.12.0-rc1 and NumPy 1.11.3. The code has not been tested with TensorFlow 1.0.

Code

The core components of cfrnet, i.e. the TensorFlow graph, is contained in cfr/cfr_net.py. The training is performed by cfr_net_train.py. The file cfr_param_search.py takes a configuration file as input and allows the user to randomly sample from the supplied parameters (given that there are multiple values given in a list. See configs/example_ihdp.txt for an example.

A typical experiment uses cfr_param_search.py and evaluate.py as sub-routines. cfr_param_search is best used to randomly search the parameter space. In the output directory, it creates a log of which configurations have been used so far, so that the same experiment is not repeated. evaluate.py goes through the predictions produced by the model and evaluates the error.

cfr_param_search

The script cfr_param_search.py runs a random hyperparameter search given a configuration file.

Usage:

python cfr_param_search.py <config_file> <num_runs>

The config_file argument should contain the path to a text file where each line is a key-value pair for a CFR parameter.

The num_run argument should contain an integer to indicate how many parameter settings should be sampled. If all possible configurations should be used, this can be set arbitrarily high as the script will terminate when all have been used. If the number of possible settings is vast, a smaller value for num_runs may be appropriate.

Example:

python evaluate.py configs/example_ihdp.txt 10

Example configuration file (from configs/example_ihdp.txt):

p_alpha=[0, 1e-1]
p_lambda=[1e-3]
n_in=[2]
n_out=[2]
dropout_in=1.0
...

Note that some of the lines have square brackets to indicate lists. If a parameter list contains more than a single element, cfr_param_search will sample uniformly from these values. In this way, random parameter search can be performed.

evaluate

The script evaluate.py performs an evaluation of a trained model based on the predictions made for the training and test sets.

Usage:

python evaluate.py <config_file> [overwrite] [filters]

The parameter config_file should be the same as the one used in cfr_param_search. (Note: evaluate only uses the settings for dataform, data_test, datadir and outdir, the rest can be changed without affecting the evaluation.)

If the overwrite parameter is set to "1", the script re-computes all error estimates. If it is set to "0" it re-uses stored values, but re-prints and re-plots all results.

The argument filters accepts a string in the form of a python dict containing values of the parameters the used wishes to filter. This produces plots and text summaries only of results corresponding to configuration that matches the filter.

Example:

python evaluate.py configs/example_ihdp.txt 0 "{p_alpha: 0}"

Examples

A simple experiment example is contained in example_ihdp.sh. This file runs the model on (a subset of) the IHDP data with parameters supplied by configs/example_ihdp.txt. The data for this example can be downloaded from http://www.fredjo.com/files/ihdp_npci_1-100.train.npz (train) and http://www.fredjo.com/files/ihdp_npci_1-100.test.npz (test). For the full data (of 1000 replications) used in the ICML 2017 paper, please visit https://www.fredjo.com/.

FAQ

  • Q: What are the hyperparameters used on IHDP in the ICML 2017 paper? A: The parameters were those given in example_ihdp.txt but with p_alpha = 0.3
  • Q: I don't get the same IHDP results as in the paper when I try to replicate with the IHDP example from Github. A: The ICML 2017 results were computed over the full set of 1000 replications. The Github IHDP example uses only 100 examples as it is meant to serve as a quick demo. Please find the 1000 replications at https://www.fredjo.com/.

References

Uri Shalit, Fredrik D. Johansson & David Sontag. Estimating individual treatment effect: generalization bounds and algorithms, 34th International Conference on Machine Learning (ICML), August 2017.

Fredrik D. Johansson, Uri Shalit & David Sontag. Learning Representations for Counterfactual Inference. 33rd International Conference on Machine Learning (ICML), June 2016.

cfrnet's People

Contributors

dsontag avatar fredjoha avatar oddrose avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cfrnet's Issues

weighting treated / controlled for reweight_sample option.

Thank you for sharing the code. I am reading through the code to understand how it works.
I am wondering whether there exists a bug in implementing "reweight_sample" option.

        if FLAGS.reweight_sample:
            w_t = t / (2 * p_t)
            w_c = (1 - t) / (2 * 1 - p_t)
            sample_weight = w_t + w_c
        else:
            sample_weight = 1.0

It looks like p_t is the proportion of treated instances -- so if it is 0.5, w_t and w_c would yield the same weight for the treated & controlled instances. If this is true, I think

w_c = (1-t)/(2*1-p_t)

should be w_c = (1 - t) / (2 * (1 - p_t))

Error when using wass

Thanks for sharing your code and excellent work!

I try to run your code on other experimental data.
However, I run into an error when using wass. The code works when other imb_funs (mmd2_rbf) are used.

Attached is the error log. Do you have any idea about what might cause this error so that I could fix it?

Traceback (most recent call last):
File "cfr_net_train.py", line 427, in main
run(outdir)
File "cfr_net_train.py", line 374, in run
D_exp_test, logfile, i_exp)
File "cfr_net_train.py", line 142, in train
CFR.r_alpha: FLAGS.p_alpha, CFR.r_lambda: FLAGS.p_lambda, CFR.p_t: p_treated})
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 766, in run
run_metadata_ptr)
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 964, in _run
feed_dict_string, options, run_metadata)
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 1014, in _do_run
target_list, options, run_metadata)
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/client/session.py", line 1034, in _do_call
raise type(e)(node_def, op, message)
InvalidArgumentError: ConcatOp : Dimensions of inputs should match: shape[0] = [0,10] vs. shape[1] = [1,1]
[[Node: concat_2 = Concat[N=2, T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/gpu:0"](concat_2/concat_dim, concat_1, concat)]]
[[Node: gradients/Cast_2/_111 = _Recvclient_terminated=false, recv_device="/job:localhost/replica:0/task:0/cpu:0", send_device="/job:localhost/replica:0/task:0/gpu:0", send_device_incarnation=1, tensor_name="edge_588_gradients/Cast_2", tensor_type=DT_INT64, _device="/job:localhost/replica:0/task:0/cpu:0"]]

Caused by op u'concat_2', defined at:
File "cfr_net_train.py", line 434, in
tf.app.run()
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/platform/app.py", line 43, in run
sys.exit(main(sys.argv[:1] + flags_passthrough))
File "cfr_net_train.py", line 427, in main
run(outdir)
File "cfr_net_train.py", line 283, in run
CFR = cfr.cfr_net(x, t, y_, p, FLAGS, r_alpha, r_lambda, do_in, do_out, dims)
File "/home/siyuan/git/cfrnet/cfr/cfr_net.py", line 25, in init
self.build_graph(x, t, y , p_t, FLAGS, r_alpha, r_lambda, do_in, do_out, dims)
File "/home/siyuan/git/cfrnet/cfr/cfr_net.py", line 185, in _build_graph
imb_dist, imb_mat = wasserstein(h_rep_norm,t,p_ipm,lam=FLAGS.wass_lambda,its=FLAGS.wass_iterations,sq=False,backpropT=FLAGS.wass_bpt)
File "/home/siyuan/git/cfrnet/cfr/util.py", line 230, in wasserstein
Mt = tf.concat(1,[Mt,col])
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/ops/array_ops.py", line 1080, in concat
name=name)
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/ops/gen_array_ops.py", line 438, in _concat
values=values, name=name)
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/framework/op_def_library.py", line 759, in apply_op
op_def=op_def)
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 2240, in create_op
original_op=self._default_original_op, op_def=op_def)
File "/home/siyuan/.virtualenvs/tf012/lib/python2.7/site-packages/tensorflow/python/framework/ops.py", line 1128, in init
self._traceback = _extract_stack()

InvalidArgumentError (see above for traceback): ConcatOp : Dimensions of inputs should match: shape[0] = [0,10] vs. shape[1] = [1,1]
[[Node: concat_2 = Concat[N=2, T=DT_FLOAT, _device="/job:localhost/replica:0/task:0/gpu:0"](concat_2/concat_dim, concat_1, concat)]]
[[Node: gradients/Cast_2/_111 = _Recvclient_terminated=false, recv_device="/job:localhost/replica:0/task:0/cpu:0", send_device="/job:localhost/replica:0/task:0/gpu:0", send_device_incarnation=1, tensor_name="edge_588_gradients/Cast_2", tensor_type=DT_INT64, _device="/job:localhost/replica:0/task:0/cpu:0"]]

A Question about the Noiseless True Effect

Hi Fredrik,

Thanks for your interesting work. I'm recently reading your paper, but have one confuison in my mind that can not go away. The confusion is, in the experiment part, you use the IHDP data set with setting "A" to generate treatment response (which is a linear response surface as declared by Hill in her 2011 BART paper, NPCI package also follows this convention).

As stated in your paper, "Following Hill (2011), we use the noiseless outcome to compute the true effect". Presumably, for one individual, the difference between two noiseless outcome: mu1 - mu0 (mu1 and mu0 for treated and control respectively) should strictly be 4 isn't it? But when I check the data provided, the difference between these two across all the samples is not a constant 4. It seems like the mu1 and mu0 provided also with noise?

I provided snapshot for them as follows:
Screen Shot 2022-05-15 at 2 13 57 am

I understand that the treatment response Y1 and Y0 (with one of them being counterfactual for each individual) come with noise, thus, there difference not necessarily being 4. But why mu1 - mu0 not strictly being 4?

Thanks for any reply!

usage of cfr_net_train.py

Hi, I'd like to use cfrnet code to run counterfactual analysis. Shall we use cfr_net_train.py to train a model? If so, then what's the usage to call this script? I tried the default setting, but it failed with errors to find files. Thanks for your answer.

errors in the examples

Hi,
I am running a linux mint machine in a virtual enviroment.

(python27) andrewcz@andrewcz-PORTEGE-Z30t-B ~/cfrnet $ cd ~
(python27) andrewcz@andrewcz-PORTEGE-Z30t-B ~ $ export TF_BINARY_URL=https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.10.0-cp27-none-linux_x86_64.whl
(python27) andrewcz@andrewcz-PORTEGE-Z30t-B ~ $ pip install --ignore-installed --upgrade $TF_BINARY_URL
Collecting tensorflow==0.10.0 from https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.10.0-cp27-none-linux_x86_64.whl
Using cached https://storage.googleapis.com/tensorflow/linux/cpu/tensorflow-0.10.0-cp27-none-linux_x86_64.whl
Collecting six>=1.10.0 (from tensorflow==0.10.0)
Using cached six-1.10.0-py2.py3-none-any.whl
Collecting numpy>=1.8.2 (from tensorflow==0.10.0)
Using cached numpy-1.12.1-cp27-cp27mu-manylinux1_x86_64.whl
Collecting mock>=2.0.0 (from tensorflow==0.10.0)
Using cached mock-2.0.0-py2.py3-none-any.whl
Collecting wheel (from tensorflow==0.10.0)
Downloading wheel-0.29.0-py2.py3-none-any.whl (66kB)
100% |████████████████████████████████| 71kB 1.9MB/s
Collecting protobuf==3.0.0b2 (from tensorflow==0.10.0)
Using cached protobuf-3.0.0b2-py2.py3-none-any.whl
Collecting funcsigs>=1; python_version < "3.3" (from mock>=2.0.0->tensorflow==0.10.0)
Downloading funcsigs-1.0.2-py2.py3-none-any.whl
Collecting pbr>=0.11 (from mock>=2.0.0->tensorflow==0.10.0)
Using cached pbr-3.0.0-py2.py3-none-any.whl
Collecting setuptools (from protobuf==3.0.0b2->tensorflow==0.10.0)
Using cached setuptools-35.0.2-py2.py3-none-any.whl
Collecting packaging>=16.8 (from setuptools->protobuf==3.0.0b2->tensorflow==0.10.0)
Using cached packaging-16.8-py2.py3-none-any.whl
Collecting appdirs>=1.4.0 (from setuptools->protobuf==3.0.0b2->tensorflow==0.10.0)
Using cached appdirs-1.4.3-py2.py3-none-any.whl
Collecting pyparsing (from packaging>=16.8->setuptools->protobuf==3.0.0b2->tensorflow==0.10.0)
Using cached pyparsing-2.2.0-py2.py3-none-any.whl
Installing collected packages: six, numpy, funcsigs, pbr, mock, wheel, pyparsing, packaging, appdirs, setuptools, protobuf, tensorflow
Successfully installed appdirs-1.4.3 funcsigs-1.0.2 mock-2.0.0 numpy-1.12.1 packaging-16.8 pbr-3.0.0 protobuf-3.0.0b2 pyparsing-2.2.0 setuptools-35.0.2 six-1.10.0 tensorflow-0.10.0 wheel-0.29.0
(python27) andrewcz@andrewcz-PORTEGE-Z30t-B ~ $ git clone https://github.com/clinicalml/cfrnet.git
fatal: destination path 'cfrnet' already exists and is not an empty directory.
(python27) andrewcz@andrewcz-PORTEGE-Z30t-B ~ $ git clone https://github.com/clinicalml/cfrnet.git
Cloning into 'cfrnet'...
remote: Counting objects: 100, done.
remote: Total 100 (delta 0), reused 0 (delta 0), pack-reused 100
Receiving objects: 100% (100/100), 3.34 MiB | 596.00 KiB/s, done.
Resolving deltas: 100% (42/42), done.
Checking connectivity... done.
(python27) andrewcz@andrewcz-PORTEGE-Z30t-B ~ $ ./example_ihdp.sh
bash: ./example_ihdp.sh: No such file or directory
(python27) andrewcz@andrewcz-PORTEGE-Z30t-B ~ $ cd cfrnet/
(python27) andrewcz@andrewcz-PORTEGE-Z30t-B ~/cfrnet $ ./example_ihdp.sh

Run 1 of 20:

p_alpha: 0
Training with hyperparameters: alpha=0, lambda=0.0001
Training data: data/ihdp_npci_1-100.train.npz
Test data: data/ihdp_npci_1-100.test.npz
Loaded data with shape [672,25]
Defining graph...

Traceback (most recent call last):
File "cfr_net_train.py", line 428, in
tf.app.run()
File "/home/andrewcz/miniconda3/envs/python27/lib/python2.7/site-packages/tensorflow/python/platform/app.py", line 30, in run
sys.exit(main(sys.argv))
File "cfr_net_train.py", line 421, in main
run(outdir)
File "cfr_net_train.py", line 277, in run
CFR = cfr.cfr_net(x, t, y_, p, FLAGS, r_alpha, r_lambda, do_in, do_out, dims)
File "/home/andrewcz/cfrnet/cfr/cfr_net.py", line 25, in init
self.build_graph(x, t, y , p_t, FLAGS, r_alpha, r_lambda, do_in, do_out, dims)
File "/home/andrewcz/cfrnet/cfr/cfr_net.py", line 129, in _build_graph
h_rep_norm = h_rep / safe_sqrt(tf.reduce_sum(tf.square(h_rep), axis=1, keep_dims=True))
TypeError: reduce_sum() got an unexpected keyword argument 'axis'
Configuration used, skipping
Configuration used, skipping

Run 4 of 20:

p_alpha: 1
Training with hyperparameters: alpha=1, lambda=0.0001
Training data: data/ihdp_npci_1-100.train.npz
Test data: data/ihdp_npci_1-100.test.npz
Loaded data with shape [672,25]
Defining graph...

Traceback (most recent call last):
File "cfr_net_train.py", line 428, in
tf.app.run()
File "/home/andrewcz/miniconda3/envs/python27/lib/python2.7/site-packages/tensorflow/python/platform/app.py", line 30, in run
sys.exit(main(sys.argv))
File "cfr_net_train.py", line 421, in main
run(outdir)
File "cfr_net_train.py", line 277, in run
CFR = cfr.cfr_net(x, t, y_, p, FLAGS, r_alpha, r_lambda, do_in, do_out, dims)
File "/home/andrewcz/cfrnet/cfr/cfr_net.py", line 25, in init
self.build_graph(x, t, y , p_t, FLAGS, r_alpha, r_lambda, do_in, do_out, dims)
File "/home/andrewcz/cfrnet/cfr/cfr_net.py", line 129, in _build_graph
h_rep_norm = h_rep / safe_sqrt(tf.reduce_sum(tf.square(h_rep), axis=1, keep_dims=True))
TypeError: reduce_sum() got an unexpected keyword argument 'axis'
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping
Configuration used, skipping

Evaluating experiment results/example_ihdp...
Loading results from results/example_ihdp...
Found 0 experiment configurations.
Traceback (most recent call last):
File "evaluate.py", line 97, in
evaluate(config_file, overwrite, filters=filters)
File "evaluate.py", line 59, in evaluate
binary=binary)
File "/home/andrewcz/cfrnet/cfr/evaluation.py", line 332, in evaluate
raise Exception('No finished results found.')
Exception: No finished results found.
(python27) andrewcz@andrewcz-PORTEGE-Z30t-B ~/cfrnet $

Im not sure whats going on . all the errors come when i try and run the shell example.
Many thanks,
Andrew

Reported results

Hi,

I ran the simulation using the provided configuration and observed results that appear to differ from the results reported in your paper. Despite my efforts to investigate the cause of this discrepancy, I have been unable to determine why these results differ.

I have used the following configuration:

p_alpha=[0.3]
p_lambda=[1e-4]
n_in=[3]
n_out=[3]
nonlin='elu'
lrate=[1e-3]
batch_size=[100]
dim_in=[200]
dim_out=[100]
batch_norm=[0]
normalization=['divide']
imb_fun=['wass']
experiments=1000
reweight_sample=[1]
split_output=[1]
rep_weight_decay=[0]
dropout_in=1.0
dropout_out=1.0
rbf_sigma=0.1
lrate_decay=0.97
decay=0.3
optimizer='Adam'
wass_lambda=10.0
wass_iterations=10
wass_bpt=1
use_p_correction=0
iterations=3000
weight_init=[0.1]
outdir='results/example_ihdp'
datadir='data/'
dataform='ihdp_npci_1-1000.train.npz'
data_test='ihdp_npci_1-1000.test.npz'
pred_output_delay=200
loss='l2'
sparse=0
varsel=0
repetitions=1
val_part=0.3

and I got the following results:

Mode: Train
| Pehe | Bias_ate | Rmse_fact | Rmse_cfact | Rmse_ite | Objective | Pehe_nn

0 | 0.785 +/- 0.052 | 0.219 +/- 0.031 | 1.135 +/- 0.045 | 1.188 +/- 0.020 | 1.164 +/- 0.021 | 0.994 +/- 0.036 | 4.895 +/- 0.613

Mode: Valid
| Pehe | Bias_ate | Rmse_fact | Rmse_cfact | Rmse_ite | Objective | Pehe_nn

0 | 0.884 +/- 0.084 | 0.224 +/- 0.031 | 1.363 +/- 0.091 | 1.206 +/- 0.032 | 1.201 +/- 0.032 | 1.995 +/- 0.402 | 5.661 +/- 0.799

Mode: Test
| Pehe | Bias_ate | Rmse_fact | Rmse_cfact | Rmse_ite | Pehe_nn

0 | 0.833 +/- 0.056 | 0.236 +/- 0.032 | 1.287 +/- 0.065 | 1.182 +/- 0.024 | 1.183 +/- 0.022 | 5.456 +/- 0.682

Thank you for your attention to this matter, and I look forward to your response.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.