Форма события преобразования тензорного потока-вероятности для JointDistribution

Я хотел бы создать распределение для n категориальных переменных C_1, .., C_n, форма события которых равна n. При использовании JointDistributionSequentialAutoBatched измерение события представляет собой список [[], .., []]. Например, для n = 2

import tensorflow_probability.python.distributions as tfd

probs = [
    [0.8, 0.2], # C_1 in {0,1}
    [0.3, 0.3, 0.4] # C_2 in {0,1,2}
    ]

D = tfd.JointDistributionSequentialAutoBatched([tfd.Categorical(probs=p) for p in probs])

>>> D
<tfp.distributions.JointDistributionSequentialAutoBatched 'JointDistributionSequentialAutoBatched' batch_shape=[] event_shape=[[], []] dtype=[int32, int32]>

Как мне изменить его, чтобы получить форму события [2]?


person abes    schedule 05.02.2021    source источник


Ответы (1)


Здесь могут работать несколько разных подходов:

  1. Создайте пакет категориальных распределений, а затем используйте tfd.Independent, чтобы повторно интерпретировать измерение пакета как событие:
vector_dist = tfd.Independent(
  tfd.Categorical(
    probs=[
      [0.8, 0.2, 0.0],  # C_1 in {0,1}
      [0.3, 0.3, 0.4]  # C_2 in {0,1,2}
    ]),
  reinterpreted_batch_ndims=1)

Здесь я добавил дополнительный ноль для заполнения probs, чтобы оба распределения могли быть представлены одним категориальным объектом.

  1. Используйте распределение Blockwise, которое помещает свои распределения компонентов в один вектор (в отличие от классов JointDistribution, которые возвращают их как отдельные значения):
vector_dist = tfd.Blockwise([tfd.Categorical(probs=p) for p in probs])
  1. Самый близкий к прямому ответу на ваш вопрос - применить биектор Split, обратный которому Concat, к совместному распределению:
tfb = tfp.bijectors
D = tfd.JointDistributionSequentialAutoBatched(
  [tfd.Categorical(probs=[p] for p in probs])
vector_dist = tfb.Invert(tfb.Split(2))(D)

Обратите внимание, что мне пришлось неловко написать probs=[p] вместо просто probs=p. Это связано с тем, что биектор Concat, как и tf.concat, не может изменять тензорный ранг своего аргумента - он может объединять небольшие векторы в большой вектор, но не скаляры в вектор - поэтому мы должны гарантировать, что его входные данные сами являются векторами. Этого можно было бы избежать, если бы у TFP был Stack биектор, аналогичный tf.stack / tf.unstack (в настоящее время его нет, но нет причин, по которым этого не могло быть).

person Dave Moore    schedule 21.02.2021
comment
Спасибо, что указали на tfd.Blockwise, в моем коде я фактически использовал JointDistributionCoroutine с обучаемыми задачами, поэтому я не мог использовать решение 1.. В итоге я использовал tfd.Blockwise, как в его строках документации: joint =tfd.JointDistributionCoroutine(model), d = tfd.Blockwise(joint) ` - person abes; 01.03.2021