You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现Wang与Blei的Deconfounder时遇Tensor损失需tape的ValueError求助

问题:Deconfounder实现中TensorFlow优化器报错处理

我正在实现Wang和Blei提出的Deconfounder,执行代码行train = optimizer.minimize(-elbo,var_list=[qb, qw, qw2, qz])时触发错误:

ValueError: tape is required when a Tensor loss is passed. Received: loss=1950770.5, tape=None

不确定minimize()的var_list参数是否正确,尝试用tf.GradientTape()也没解决,求帮助。

相关代码如下:

def variational_model(qb_mean, qb_stddv, qw_mean, qw_stddv, 
                      qw2_mean, qw2_stddv, qz_mean, qz_stddv):
    qb = ed.Normal(loc=qb_mean, scale=qb_stddv, name="qb")
    qw = ed.Normal(loc=qw_mean, scale=qw_stddv, name="qw")
    qw2 = ed.Normal(loc=qw2_mean, scale=qw2_stddv, name="qw2")
    qz = ed.Normal(loc=qz_mean, scale=qz_stddv, name="qz")
    return qb, qw, qw2, qz


log_q = ed.make_log_joint_fn(variational_model)

def target(b, w, w2, z):
    """Unnormalized target density as a function of the parameters."""
    return log_joint(data_dim=data_dim,
                   latent_dim=latent_dim,
                   num_datapoints=num_datapoints,
                   stddv_datapoints=stddv_datapoints,
                   mask=1-holdout_mask,
                   w=w, z=z, w2=w2, b=b, x=x_train)

def target_q(qb, qw, qw2, qz):
    return log_q(qb_mean=qb_mean, qb_stddv=qb_stddv,
                 qw_mean=qw_mean, qw_stddv=qw_stddv,
                 qw2_mean=qw2_mean, qw2_stddv=qw2_stddv,
                 qz_mean=qz_mean, qz_stddv=qz_stddv,
                 qw=qw, qz=qz, qw2=qw2, qb=qb)

qb_mean = tf.Variable(np.ones([1, data_dim]), dtype=tf.float32)
qw_mean = tf.Variable(np.ones([latent_dim, data_dim]), dtype=tf.float32)
qw2_mean = tf.Variable(np.ones([latent_dim, data_dim]), dtype=tf.float32)
qz_mean = tf.Variable(np.ones([num_datapoints, latent_dim]), dtype=tf.float32)
qb_stddv = tf.nn.softplus(tf.Variable(0 * np.ones([1, data_dim]), dtype=tf.float32))
qw_stddv = tf.nn.softplus(tf.Variable(-4 * np.ones([latent_dim, data_dim]), dtype=tf.float32))
qw2_stddv = tf.nn.softplus(tf.Variable(-4 * np.ones([latent_dim, data_dim]), dtype=tf.float32))
qz_stddv = tf.nn.softplus(tf.Variable(-4 * np.ones([num_datapoints, latent_dim]), dtype=tf.float32))

qb, qw, qw2, qz = variational_model(qb_mean=qb_mean, qb_stddv=qb_stddv,
                                    qw_mean=qw_mean, qw_stddv=qw_stddv,
                                    qw2_mean=qw2_mean, qw2_stddv=qw2_stddv,
                                    qz_mean=qz_mean, qz_stddv=qz_stddv)


energy = target(qb, qw, qw2, qz)
entropy = -target_q(qb, qw, qw2, qz)

elbo = energy + entropy


optimizer = tf.optimizers.Adam(learning_rate = 0.05)
train = optimizer.minimize(-elbo,var_list=[qb, qw, qw2, qz])

init = tf.global_variables_initializer()

t = []

num_epochs = 500

with tf.Session() as sess:
    sess.run(init)

    for i in range(num_epochs):
        sess.run(train)
        if i % 5 == 0:
            t.append(sess.run([elbo]))

        b_mean_inferred = sess.run(qb_mean)
        b_stddv_inferred = sess.run(qb_stddv)
        w_mean_inferred = sess.run(qw_mean)
        w_stddv_inferred = sess.run(qw_stddv)
        w2_mean_inferred = sess.run(qw2_mean)
        w2_stddv_inferred = sess.run(qw2_stddv)
        z_mean_inferred = sess.run(qz_mean)
        z_stddv_inferred = sess.run(qz_stddv)
        
print("Inferred axes:")
print(w_mean_inferred)
print("Standard Deviation:")
print(w_stddv_inferred)

plt.plot(range(1, num_epochs, 5), t)
plt.show()

def replace_latents(b, w, w2, z):

    def interceptor(rv_constructor, *rv_args, **rv_kwargs):
        """Replaces the priors with actual values to generate samples from."""
        name = rv_kwargs.pop("name")
        if name == "b":
            rv_kwargs["value"] = b
        elif name == "w":
            rv_kwargs["value"] = w
        elif name == "w":
            rv_kwargs["value"] = w2
        elif name == "z":
            rv_kwargs["value"] = z
        return rv_constructor(*rv_args, **rv_kwargs)

    return interceptor

核心问题分析

  • 变量列表错误:var_list传入的是Edward的随机变量(qb, qw等),但TensorFlow优化器需要优化的是TensorFlow可训练变量(即你定义的qb_mean, qb_stddv这类变量),随机变量本身不是可训练参数。
  • TF版本模式冲突:代码混合了TensorFlow 1.x的tf.Session()和TF2.x的tf.optimizers.Adam,minimize在即时执行模式下需要梯度带,而旧版会话模式不兼容。

修复步骤

1. 修正优化变量列表

把var_list替换为实际的可训练TF变量:

var_list = [qb_mean, qw_mean, qw2_mean, qz_mean,
            qb_stddv.variables[0], qw_stddv.variables[0], 
            qw2_stddv.variables[0], qz_stddv.variables[0]]

注:qb_stddv是tf.nn.softplus包装的,需要取其内部的变量(variables[0])作为可训练参数。

2. 适配TF会话模式的优化流程

TF1.x风格的会话中,不能直接用TF2.x的optimizer.minimize,需要手动计算梯度并更新:

optimizer = tf.train.AdamOptimizer(learning_rate=0.05)
grads = tf.gradients(-elbo, var_list)
train_op = optimizer.apply_gradients(zip(grads, var_list))

之后在会话中运行train_op代替原来的train。

3. 完整训练循环修正

把原来的训练部分替换为:

optimizer = tf.train.AdamOptimizer(learning_rate=0.05)
var_list = [qb_mean, qw_mean, qw2_mean, qz_mean,
            qb_stddv.variables[0], qw_stddv.variables[0], 
            qw2_stddv.variables[0], qz_stddv.variables[0]]
grads = tf.gradients(-elbo, var_list)
train_op = optimizer.apply_gradients(zip(grads, var_list))

init = tf.global_variables_initializer()

t = []
num_epochs = 500

with tf.Session() as sess:
    sess.run(init)
    for i in range(num_epochs):
        sess.run(train_op)
        if i % 5 == 0:
            current_elbo = sess.run(elbo)
            t.append(current_elbo)
            print(f"Epoch {i}, ELBO: {current_elbo}")
    
    # 最后一次性获取所有推断结果,避免循环内重复计算
    b_mean_inferred, b_stddv_inferred, w_mean_inferred, w_stddv_inferred, \
    w2_mean_inferred, w2_stddv_inferred, z_mean_inferred, z_stddv_inferred = sess.run([
        qb_mean, qb_stddv, qw_mean, qw_stddv,
        qw2_mean, qw2_stddv, qz_mean, qz_stddv
    ])

4. 修复其他小问题

replace_latents函数里有重复的elif name == "w":,把第二个改成name == "w2":

elif name == "w2":
    rv_kwargs["value"] = w2

内容的提问来源于stack exchange,提问作者thomas41on1

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.05 22:05:25