Прежде всего, я явно не эксперт в вероятности тензорного потока, поэтому этот ответ, скорее всего, не будет наилучшей практикой, я просто заставил его работать с ограниченными знаниями в библиотеке, пытаясь узнать больше о вероятности тензорного потокасебя.
Во-вторых, я всего лишь хочу ответить на часть вопроса, касающегося модели и ее реализации, на ответ об отладке tenorflow, либо немного погуглите об этом, чтобы увидеть, есть ли какие-то учебники по этому вопросу,задайте другой вопрос, поскольку я чувствую, что это совсем другой вопрос.
Что касается модели, то она выглядит правильно реализованной, и я смог заставить ее работать без особых изменений, однако я бы порекомендовал явно использовать предшествующий theta
по двум причинам. Во-первых, даже если вы не установите его, используется априор (в общем, униформа, которая является константой, в данном случае, безусловно, униформа априора и неограниченный униформ априор), и вы можете не знать, какой онили вы используете модель, отличную от реализованной. Во-вторых, вы можете столкнуться с неожиданными проблемами, когда используете предыдущую версию, не подходящую для данной проблемы. Например, здесь theta
- это вектор измерения D
, который должен быть между 0
и 1
, однако в вашей реализации theta
может принимать значения вне этого диапазона;к счастью, если параметр tfd.Bernoulli
находится за пределами (0,1)
тензор потока просто возвращает nan
, но это может не всегда иметь место, это может привести к ошибке (которая будет срабатывать при random итерации, где тэта находится за пределами (0,1)
), или вы можете просто получить непонятные результаты, где вероятность голов составляет 1.3
.
Таким образом, я добавил априор и изменил следующие пункты кода:
- Я добавил дополнительное измерение к
observations
, чтобы оно могло быть правильно передано - Я использовал
distribution.log_prob()
вместо log_prob
из tfd.Sample
. Я пытался использовать log_prob
напрямую, но мне трудно понять, как tfd.Sample
работает и как это влияет на log_prog
исходного дистрибутива, поэтому я согласился с тем, что знаю лучше. - Я установилось до
tf.reduce_sum
. Это не дало никакой ошибки, потому что log_prob
было выполнено раньше и не удалось, но это произошло бы потому, что при использовании нескольких цепочек каждая цепочка независима, поэтому каждая цепочка имеет свою логарифмическую вероятностную вероятность. posterior_log_prob
должен возвращать тензор длины n_chains
, больше не скаляр.
Вот полученный код, исключающий неизмененные части:
observations = generate_bernouilli(N,p)[:, None, :]
# ---------- Model ------------#
def make_prior(D):
one_theta = tfd.Independent(
distribution=tfd.Uniform(low=tf.zeros(D)),
reinterpreted_batch_ndims=1
)
return one_theta
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, D, theta):
return (
make_prior(D).log_prob(theta) +
tf.reduce_sum(
make_likelihood(theta).distribution.log_prob(observations),
axis=0
)
)
posterior_log_prob = functools.partial(joint_log_prob, observations, D)
# Small comment, for coherence I would also modify the following line
current_state=tf.ones([n_chains,D])/10,
# otherwise, D != 2 would not work