Я пытаюсь построить простейший пример байесовской сети с несколькими дискретными случайными величинами и условными вероятностями («Студенческая сеть» из книги Коллера, см. 1 )
Хотянемного громоздко, мне удалось построить эту сеть, используя pymc3.В частности, создание CPD не так просто в pymc3, см. Фрагмент ниже:
import pymc3 as pm
...
with pm.Model() as basic_model:
# parameters for categorical are indexed as [0, 1, 2, ...]
difficulty = pm.Categorical(name='difficulty', p=[0.6, 0.4])
intelligence = pm.Categorical(name='intelligence', p=[0.7, 0.3])
grade = pm.Categorical(name='grade',
p=pm.math.switch(
theano.tensor.eq(intelligence, 0),
pm.math.switch(
theano.tensor.eq(difficulty, 0),
[0.3, 0.4, 0.3], # I=0, D=0
[0.05, 0.25, 0.7] # I=0, D=1
),
pm.math.switch(
theano.tensor.eq(difficulty, 0),
[0.9, 0.08, 0.02], # I=1, D=0
[0.5, 0.3, 0.2] # I=1, D=1
)
)
)
letter = pm.Categorical(name='letter', p=pm.math.switch(
...
Но я понятия не имею, как построить эту сеть, используя вероятность вероятности падения (версии: tfp-nightly==0.7.0.dev20190517
, tf-nightly-2.0-preview==2.0.0.dev20190517
)
Для безусловных бинарных переменных можно использовать категориальное распределение, например
from tensorflow_probability import distributions as tfd
from tensorflow_probability import edward2 as ed
difficulty = ed.RandomVariable(
tfd.Categorical(
probs=[0.6, 0.4],
name='difficulty'
)
)
Но как построить CPD?
В классе мало классов / методовтензор-вероятность вероятности, которая может иметь значение (в tensorflow_probability/python/distributions/deterministic.py
или устаревшей ConditionalDistribution
), но документация довольно скудна (требуется глубокое понимание tfp).
--- Обновленный вопрос ---
Ответ Криса - хорошая отправная точка.Тем не менее, все еще немного неясно даже для очень простой модели с двумя переменными.
Это хорошо работает:
jdn = tfd.JointDistributionNamed(dict(
dist_x=tfd.Categorical([0.2, 0.8], validate_args=True),
dist_y=lambda dist_x: tfd.Bernoulli(probs=tf.gather([0.1, 0.9], indices=dist_x), validate_args=True)
))
print(jdn.sample(10))
, но эта ошибка не получается
jdn = tfd.JointDistributionNamed(dict(
dist_x=tfd.Categorical([0.2, 0.8], validate_args=True),
dist_y=lambda dist_x: tfd.Categorical(probs=tf.gather_nd([[0.1, 0.9], [0.5, 0.5]], indices=[dist_x]))
))
print(jdn.sample(10))
(Я пытаюсь смоделировать категориально во втором примере только для целей обучения)
- Обновление: решено ---
Очевидно, последний пример неправильно использовал tf.gather_nd
вместоtf.gather
, так как мы хотели выбрать только первую или вторую строку на основе dist_x
.Этот код работает сейчас:
jdn = tfd.JointDistributionNamed(dict(
dist_x=tfd.Categorical([0.2, 0.8], validate_args=True),
dist_y=lambda dist_x: tfd.Categorical(probs=tf.gather([[0.1, 0.9], [0.5, 0.5]], indices=[dist_x]))
))
print(jdn.sample(10))