1代码来源
github:https://github.com/SUwonglab/CausalEGM/tree/main/src
pip:Tutorial for Python Users — CausalEGM documentation
安装:Installation — CausalEGM documentation
版本:
2原理
关于CausalEGM
根据观察数据,推断治疗的因果效应对于许多科学和工程问题至关重要,并引起了各个领域的巨大兴趣。了解因果关系的最有效方法是进行随机对照试验(RCT)。然而,RCT 耗时、昂贵且普遍性存在问题。相比之下,观察性研究可以提供有价值的证据并检查“现实世界”环境中的效果。在现实世界的应用中,由于混杂因素引入的选择偏差,治疗通常不是随机分配的。准确估计因果效应涉及处理混杂因素,这可能会影响治疗和结果。未能针对混杂效应进行调整可能会导致估计偏差和错误结论。
Density estimation using deep generative neural networks
CausalEGM(Causal Effect Generative Model)是一种用于因果推断的方法,旨在从观察数据中估计因果效应。它结合了生成模型和因果推断的思想,可以用于处理因果关系的估计、预测和决策问题。以下是CausalEGM的一般原理:
-
生成模型基础: CausalEGM基于生成模型的思想,意味着它试图对数据生成的过程进行建模。它假设数据是从一个潜在的生成过程中产生的,这个生成过程可以包括真实的因果关系。
-
结构方程模型: CausalEGM使用结构方程模型(SEM)来描述数据的生成过程。SEM是一种用于建立潜在因果关系的模型,它描述了变量之间的依赖关系、直接影响和随机噪声。
-
因果图: CausalEGM可以通过因果图表示潜在的因果关系。因果图是一个有向图,节点代表变量,边代表因果关系。通过观察数据,CausalEGM可以估计因果图的结构和参数。
-
因果效应估计: CausalEGM的主要目标是估计因果效应,即某个变量对另一个变量的影响。它通过分析结构方程模型和因果图来估计不同变量之间的因果关系。
-
反事实推断: 一种重要的应用是反事实推断,即在观察数据的基础上估计干预的效果。通过修改因果图中的某些变量,CausalEGM可以估计如果某个干预发生了,会对数据产生什么样的影响。
-
数据生成和预测: 完成因果效应估计后,CausalEGM可以用来生成新的数据样本或进行预测。生成的数据样本可以用于模拟不同因果关系下的数据分布。
总之,CausalEGM是一种将生成模型与因果推断相结合的方法,通过对结构方程模型和因果图的分析,估计数据中的因果效应。它可以用于估计干预效果、预测和决策问题,特别是在具有潜在因果关系的情况下。请注意,CausalEGM的具体实现和算法可能因版本而异,因此在使用时应查阅相关文档或论文。
意义
抽象的
loss
def train_step(self, data_z, data_v, data_x, data_y):
"""Training step in the Variational CausalEGM model.
Parameters
----------
data_z
Numpy.ndarray denoting latent features with shape [batch_size, z_dim].
data_v
Numpy.ndarray denoting covariants with shape [batch_size, v_dim].
data_x
Numpy.ndarray denoting treatment data with shape [batch_size, 1].
data_y
Numpy.ndarray denoting outcome data with shape [batch_size, 1].
Returns
--------
logpv_z
Float denoting likelihood for covariates.
kl_loss
Float denoting KL-divengence between p(z) and q(z|v).
elbo
Float denoting evidence lower bound (ELBO) loss.
l2_loss_x
Float denoting treatment reconstruction loss.
l2_loss_y
Float denoting outcome reconstruction loss.
g_e_loss
Float denoting G E combined loss.
"""
with tf.GradientTape(persistent=True) as gen_tape:
data_v_ = self.g_net(data_z)
mean, logvar = self.encode(data_v)
data_z_ = self.reparameterize(mean, logvar)
data_v__ = self.g_net(data_z_)
logpv_z = -tf.reduce_mean((data_v - data_v__)**2,axis=1)
logqz_v = self.log_normal_pdf(data_z_, mean, logvar)
logpz = self.log_normal_pdf(data_z_, 0., 0.)
kl_loss = logqz_v-logpz # here it is not the formula of KL_loss, so will result in negative values
elbo = tf.reduce_mean(logpv_z - kl_loss)
data_z0 = data_z_[:,:self.params['z_dims'][0]]
data_z1 = data_z_[:,self.params['z_dims'][0]:sum(self.params['z_dims'][:2])]
data_z2 = data_z_[:,sum(self.params['z_dims'][:2]):sum(self.params['z_dims'][:3])]
data_z3 = data_z_[:-self.params['z_dims'][3]:]
data_y_ = self.f_net(tf.concat([data_z0, data_z2, data_x], axis=-1))
data_x_ = self.h_net(tf.concat([data_z0, data_z1], axis=-1))
if self.params['binary_treatment']:
data_x_ = tf.sigmoid(data_x_)
l2_loss_x = tf.reduce_mean((data_x_ - data_x)**2)
l2_loss_y = tf.reduce_mean((data_y_ - data_y)**2)
g_e_loss = -elbo + self.params['beta']*(l2_loss_x+l2_loss_y)
# Calculate the gradients for generators and discriminators
g_e_gradients = gen_tape.gradient(g_e_loss, self.g_net.trainable_variables+self.e_net.trainable_variables+\
self.f_net.trainable_variables+self.h_net.trainable_variables)
# Apply the gradients to the optimizer
self.g_e_optimizer.apply_gradients(zip(g_e_gradients, self.g_net.trainable_variables+self.e_net.trainable_variables+\
self.f_net.trainable_variables+self.h_net.trainable_variables))
return tf.reduce_mean(logpv_z), tf.reduce_mean(kl_loss), elbo, l2_loss_x, l2_loss_y, g_e_loss
CausalEGM能非常灵活处理不同类型的干预,只需要调整 H网络的最后一层的激活函数。
parser.add_argument('-beta', dest='beta', type=float, default=1.,
help="Coefficient for treatment and outcome MSE loss (default: 1).")
if self.params['binary_treatment']:
data_x_pred = tf.sigmoid(data_x_pred)
mse_x = np.mean((data_x-data_x_pred)**2)
mse_y = np.mean((data_y-data_y_pred)**2)
def evaluate(self, data, nb_intervals=200):
"""Internal evaluation in the training process of variational CausalEGM.
Parameters
----------
data
List denoting the triplet data [X,Y,V] to be evaluated.
nb_intervals
Int object denoting number of intervals in continous treatment settings. Default: ``200``.
Returns
--------
causal_pre
Numpy.ndarray denoting the predicted individual treatment effect (ITE) or
values of average dose response function (ADRF).
mse_x
Float denoting treatment reconstruction loss.
mse_y
Float denoting outcome reconstruction loss.
"""
data_x, data_y, data_v = data
data_z = self.z_sampler.get_batch(len(data_x))
mean, logvar = self.encode(data_v)
data_z_ = self.reparameterize(mean, logvar)
data_z0 = data_z_[:,:self.params['z_dims'][0]]
data_z1 = data_z_[:,self.params['z_dims'][0]:sum(self.params['z_dims'][:2])]
data_z2 = data_z_[:,sum(self.params['z_dims'][:2]):sum(self.params['z_dims'][:3])]
data_y_pred = self.f_net.predict(tf.concat([data_z0, data_z2, data_x], axis=-1),verbose=0)
data_x_pred = self.h_net.predict(tf.concat([data_z0, data_z1], axis=-1),verbose=0)
if self.params['binary_treatment']:
data_x_pred = tf.sigmoid(data_x_pred)
mse_x = np.mean((data_x-data_x_pred)**2)
mse_y = np.mean((data_y-data_y_pred)**2)
if self.params['binary_treatment']:
#individual treatment effect (ITE) && average treatment effect (ATE)
y_pred_pos = self.f_net.predict(tf.concat([data_z0, data_z2, np.ones((len(data_x),1))], axis=-1),verbose=0)
y_pred_neg = self.f_net.predict(tf.concat([data_z0, data_z2, np.zeros((len(data_x),1))], axis=-1),verbose=0)
ite_pre = y_pred_pos-y_pred_neg
return ite_pre, mse_x, mse_y
else:
#average dose response function (ADRF)
dose_response = []
for x in np.linspace(self.params['x_min'], self.params['x_max'], nb_intervals):
data_x = np.tile(x, (len(data_x), 1))
y_pred = self.f_net.predict(tf.concat([data_z0, data_z2, data_x], axis=-1),verbose=0)
dose_response.append(np.mean(y_pred))
return np.array(dose_response), mse_x, mse_y
3配置 CausalEGM 模型
在创建 CausalEGM 模型之前,dict
应创建一个 python 对象来部署 CausalEGM 模型的超参数,其中包括潜在特征的维度、神经网络架构等。
详细的超参数描述如下。
配置参数 | 描述 |
---|---|
输出目录 | 输出目录用于保存模型训练过程中的结果。默认: ”。” |
数据集 | 用于指示输入数据的数据集名称。默认值:“我的数据” |
z_尺寸 | 编码器输出的潜在维度 (e(V)_0~3)。默认值:[3,3,6,6] |
v_dim | 协变量的维度。 |
LR | 学习率。默认值:0.0002 |
g_单位 | 解码器/生成器网络 G 的单元数量。默认值: [64,64,64,64,64]。 |
e_单位 | 编码器网络 E 的单元数量。默认值: [64,64,64,64,64]。 |
f_单位 | F 网络的单元数量。默认值:[64,32,8]。 |
h_单位 | H 网络的单元数量。默认值:[64,32,8]。 |
dz_单位 | 潜在空间中鉴别器网络的单元数量。默认值:[64,32,8]。 |
dz_单位 | 协变量空间中鉴别器网络的单元数。默认值:[64,32,8]。 |
α | 重建损失系数。 默认值:1。 |
贝塔 | 往返损耗系数。默认值:1。 |
伽玛 | 梯度惩罚损失系数。默认值:10。 |
g_d_频率 | 更新鉴别器和生成器的频率。默认值:5。 |
保存资源 | 模型训练过程中是否保存结果。 默认值: True。 |
保存模型 | 是否保存模型权重。默认值: False。 |
二进制处理 | 是否使用二元处理设置。 默认值: True。 |
使用_z_rec | 使用潜在特征的重建。默认值: True。 |
使用_v_gan | 使用协变量的 GAN 分布匹配。 默认值: True。 |
x_最小值 | 连续治疗环境中剂量反应间隔的左界。默认值:0。 |
最大x | 连续治疗环境中剂量反应间隔的右界。默认值:3。 |
配置参数对于创建 CausalEGM 模型是必需的。以下是配置参数的一些技巧。
-
z_dims对性能有显着影响,请参阅src/configs获取指导。
-
如果save_res为True,训练期间的结果将保存在output_dir中
-
建议use_v_gan在二元治疗设置下为True ,在连续治疗设置下为False。
4baseline
import CausalEGM as cegm
print("Currently use version v%s of CausalEGM."%cegm.__version__)
import yaml
params = yaml.safe_load(open('../../src/configs/Semi_acic.yaml', 'r'))
print(params)
#{'dataset': 'Semi_acic', 'output_dir': '.', 'v_dim': 100, 'z_dims': [3, 3, 6, 6], 'lr': 0.0002, 'alpha': 1, 'beta': 1, 'gamma': 10, 'g_d_freq': 5, 'g_units': [64, 64, 64, 64, 64], 'e_units': [64, 64, 64, 64, 64], 'f_units': [64, 32, 8], 'h_units': [64, 32, 8], 'dz_units': [64, 32, 8], 'dv_units': [64, 32, 8], 'save_res': True, 'save_model': False, 'binary_treatment': False, 'use_z_rec': True, 'use_v_gan': True, 'x_min': 0, 'x_max': 3}
model = cegm.CausalEGM(params=params,random_seed=123)
#get the data from the ACIC 2018 competition dataset with a specified ufid.
#ds = Semi_acic_sampler(path='../data/ACIC_2018',ufid='d5bd8e4814904c58a79d7cdcd7c2a1bb')
# >>> ds = Base_sampler(x=x,y=y,v=v)
# >>> batch = ds.next_batch() # get a batch of data
# >>> data = ds.load_all() # get all data as a triplet
# x,y,v = cegm.Semi_acic_sampler(path='../../../../data/ACIC_2018',ufid='d5bd8e4814904c58a79d7cdcd7c2a1bb').load_all()
#x,y,v = cegm.Semi_acic_sampler(path='../../../../data/ACIC_2018',ufid='d5bd8e4814904c58a79d7cdcd7c2a1bb').load_all()
import numpy as np
x = np.random.normal(size=(2000,))
y = np.random.normal(size=(2000,))
v = np.random.normal(size=(2000,100))
print(x.shape,y.shape,v.shape)
model.train(data=[x,y,v],n_iter=100,save_format='npy',verbose=False)
错误
这个错误信息表明在你的代码中存在一个占位符张量(placeholder tensor) 'Placeholder/_10'
,它的 dtype 是 float,形状是 [2000, 10],但是在执行过程中没有为它提供必要的数据值。
在 TensorFlow 中,占位符张量是一种特殊的张量,它在图构建阶段没有具体的值,而是在运行阶段通过 feed_dict
或者 tf.data
来提供数据。根据错误信息,你需要在执行代码时,确保为占位符 'Placeholder/_10'
提供一个正确形状和 dtype 的数据值。
要解决这个问题,你可以使用 feed_dict
来为占位符提供数据,例如:
import tensorflow as tf
# 创建占位符
placeholder = tf.placeholder(dtype=tf.float32, shape=[2000, 10], name='Placeholder')
# 创建一个 TensorFlow 会话
with tf.Session() as sess:
# 使用 feed_dict 为占位符提供数据
data = ... # 替换成你的数据
result = sess.run(placeholder, feed_dict={placeholder: data})
5ACIC
-
Estimating Treatment Effects over Time with Causal Forests:An application to the ACIC 2022 Data Challenge
参考
- CausalEGM:通过编码生成建模的通用因果推理框架
- Project MUSE - Estimating Treatment Effects over Time with Causal Forests: An application to the ACIC 2022 Data Challenge
-
Estimating Treatment Effects over Time with Causal Forests:An application to the ACIC 2022 Data Challenge
-
https://github.com/SUwonglab/CausalEGM/blob/main/src/CausalEGM/causalEGM.py