我想对具有多个链的多元Bernouilli(维D)进行简单的推断。下面的代码可以正常工作并正确推断唯一链的参数值。 我怀疑我错误地定义了我的模型。我没有找到任何简单的伯努利推断的简单例子。
返回的错误是:
ValueError: Dimension must be 3 but is 2 for 'mcmc_sample_chain/simple_step_size_adaptation___init__/_bootstrap_results/mh_bootstrap_results/hmc_kernel_bootstrap_results/maybe_call_fn_and_grads/value_and_gradients/mcmc_sample_chain_simple_step_size_adaptation___init____bootstrap_results_mh_bootstrap_results_hmc_kernel_bootstrap_results_maybe_call_fn_and_grads_value_and_gradients_Samplemcmc_sample_chain_simple_step_size_adaptation___init____bootstrap_results_mh_bootstrap_results_hmc_kernel_bootstrap_results_maybe_call_fn_and_grads_value_and_gradients_Independentmcmc_sample_chain_simple_step_size_adaptation___init____bootstrap_results_mh_bootstrap_results_hmc_kernel_bootstrap_results_maybe_call_fn_and_grads_value_and_gradients_Bernoulli/log_prob/transpose' (op: 'Transpose') with input shapes: [1,5000,2], [2].
这是一个简单的示例,其中D = 2,N = 5000(训练集中的样本数)。
import numpy as np
import tensorflow as tf
import tensorflow_probability as tfp
import functools
tfd = tfp.distributions
# ---------- DATA Generator ------------#
def generate_bernouilli(N,p):
return np.array([np.random.binomial(size=N, n=1, p = probability) for probability in p ]).T
D = 2
N = 5000
p = np.sort(np.random.random(D))
observations = generate_bernouilli(N,p)
# ---------- Model ------------#
def make_likelihood(theta):
one_y = tfd.Independent(
distribution = tfd.Bernoulli(probs=theta),
reinterpreted_batch_ndims=1)
y = tfd.Sample(one_y,
sample_shape=(N,))
return y
def joint_log_prob(observations, theta):
return (tf.reduce_sum(make_likelihood(theta).log_prob(observations)))
posterior_log_prob = functools.partial(joint_log_prob, observations)
# ---------- MCMC sampling ------------#
num_results = int(10e3)
num_burnin_steps = int(1e3)
n_chains = 5
adaptive_hmc = tfp.mcmc.SimpleStepSizeAdaptation(
tfp.mcmc.HamiltonianMonteCarlo(
target_log_prob_fn=posterior_log_prob,
num_leapfrog_steps=3,
step_size=1.),
target_accept_prob=tf.constant(.8),
num_adaptation_steps=int(num_burnin_steps * 0.8))
@tf.function
def run_chain():
# Run the chain (with burn-in).
samples, is_accepted = tfp.mcmc.sample_chain(
num_results=num_results,
num_burnin_steps=num_burnin_steps,
current_state=tf.ones([n_chains,2])/10,
kernel=adaptive_hmc,
trace_fn=lambda _, pkr: pkr.inner_results.is_accepted)
is_accepted = tf.reduce_mean(tf.cast(is_accepted, dtype=tf.float32))
return samples, is_accepted
# ---------- Run ------------#
with tf.device('/CPU:0'):
samples, is_accepted = run_chain()
如果我们用current_state=tf.ones([2])/10
替换current_state(从而删除独立的链采样。),代码将完美地工作。
我有几个问题,非常感谢您的帮助: +我的模型是否正确实施? +有没有办法在tf中调试这种类型的错误? python调试器没有太大帮助。
谢谢!
答案 0 :(得分:0)
首先,我显然不是张量流概率方面的专家,所以这个答案很可能不是最佳实践,我只是在尝试了解更多张量流概率的前提下,使用了我在库中所掌握的有限知识进行了工作我。
第二,我只想回答关于模型及其实现的部分问题,以回答有关调试tensorflow的回答,或者谷歌稍微介绍一下它,看看是否有关于它的一些教程,再问另一个问题我觉得这是一个完全不同的问题。
关于模型,它看起来已正确实现,并且我能够对其进行较大的改动,但是,出于两个原因,我建议明确地在theta
上使用Priority。第一个是,即使您未设置它,也使用了先验(通常是统一的,它是一个常数,在这种情况下,绝对是统一的先验,而无界的统一先验),您可能不知道它是哪个是或假设您使用的模型与已实现的模型不同。第二个问题是,在使用先验不合适的方法时,您可能会遇到意想不到的问题。例如,这里theta
是维数D
的向量,必须在0
和1
之间,但是,在您的实现中theta
可以采用超出此范围的值范围;幸运的是,如果tfd.Bernoulli
的参数不在(0,1)
范围内,tensorflow只会返回nan
,但是并非总是如此,它可能会引发错误(在< em> random 迭代,其中theta位于(0,1)
之外,否则您可能仅仅获得不可理解的结果,而正面概率为1.3
。
因此,我添加了一个先验并修改了以下几点代码:
observations
添加了一个额外的维度,以便可以正确广播distribution.log_prob()
的{{1}}而不是log_prob
。我尝试直接使用tfd.Sample
,但是我很难理解log_prob
的工作方式以及它如何影响原始发行版的tfd.Sample
,因此我沿用了我所了解的内容。log_prog
。这不会产生任何错误,因为tf.reduce_sum
是在执行之前并失败的,但是这是因为使用多个链时,每个链都是独立的,因此每个链都有其对数后验概率。 log_prob
必须返回长度为posterior_log_prob
的张量,不再是标量。以下是省略未修改部分的结果代码:
n_chains