TensorFlow 분포 모양 이해하기

TensorFlow.org에서 보기 Google Colab에서 실행 GitHub에서 소스 보기 노트북 다운로드
import collections

import tensorflow as tf
tf.compat.v2.enable_v2_behavior()

import tensorflow_probability as tfp
tfd = tfp.distributions
tfb = tfp.bijectors

기초

TensorFlow Distributions 모양과 관련된 세 가지 중요한 개념이 있습니다.

  • 이벤트 모양 분포에서 하나의 무승부의 모양을 설명; 차원에 따라 다를 수 있습니다. 스칼라 분포를 들어, 이벤트의 형상은 [] . 5 차원 MultivariateNormal 들어, 이벤트 형상이다 [5] .
  • 배치 형태는 동일하게 분포의 "배치"일명립니다 배포되지 독립에 대해 설명합니다.
  • 샘플 형태는 동일하게 분산 독립적 인 설명 배포 가족 배치의립니다.

이벤트 형상 및 배치 형태는의 재산 Distribution 샘플 형상에 특정 통화와 관련되는 반면, 오브젝트 sample 또는 log_prob .

이 노트북의 목적은 예제를 통해 이러한 개념을 설명하는 것이므로 즉시 명확하지 않더라도 걱정하지 마십시오!

이러한 개념의 또 다른 개념에 대한 개요를 참조하십시오 이 블로그 게시물을 .

TensorFlow Eager에 대한 참고 사항입니다.

이 전체 노트북을 사용하여 작성 열망 TensorFlow을 . 때 열망 분산 배치 이벤트 형상 평가 (따라서 공지)되어 함께 비록 개념 없음 열망에 의존 제시되지 Distribution 개체 파이썬 생성 그래프 (비 열망 모드)하는 반면, 그 분포를 정의 할 수있다 그래프가 실행될 때까지 이벤트 및 배치 모양이 결정되지 않습니다.

스칼라 분포

우리가 위에서 언급 한 것처럼, Distribution 객체는 이벤트 및 배치 형태를 정의하고있다. 배포를 설명하는 유틸리티로 시작하겠습니다.

def describe_distributions(distributions):
  print('\n'.join([str(d) for d in distributions]))

이 섹션에서는 스칼라 분포를 살펴볼 것이다 : 분포의 이벤트 형상 [] . 전형적인 예로는에 의해 지정된 푸 아송 분포이다 rate :

poisson_distributions = [
    tfd.Poisson(rate=1., name='One Poisson Scalar Batch'),
    tfd.Poisson(rate=[1., 10., 100.], name='Three Poissons'),
    tfd.Poisson(rate=[[1., 10., 100.,], [2., 20., 200.]],
                name='Two-by-Three Poissons'),
    tfd.Poisson(rate=[1.], name='One Poisson Vector Batch'),
    tfd.Poisson(rate=[[1.]], name='One Poisson Expanded Batch')
]

describe_distributions(poisson_distributions)
tfp.distributions.Poisson("One_Poisson_Scalar_Batch", batch_shape=[], event_shape=[], dtype=float32)
tfp.distributions.Poisson("Three_Poissons", batch_shape=[3], event_shape=[], dtype=float32)
tfp.distributions.Poisson("Two_by_Three_Poissons", batch_shape=[2, 3], event_shape=[], dtype=float32)
tfp.distributions.Poisson("One_Poisson_Vector_Batch", batch_shape=[1], event_shape=[], dtype=float32)
tfp.distributions.Poisson("One_Poisson_Expanded_Batch", batch_shape=[1, 1], event_shape=[], dtype=float32)

그 이벤트 형상이 항상 있도록 푸 아송 분포는 스칼라 분포 [] . 더 많은 비율을 지정하면 배치 형태로 표시됩니다. 마지막 예제 쌍은 흥미롭습니다. 단 하나의 비율만 있지만 해당 비율이 비어 있지 않은 모양의 numpy 배열에 포함되어 있기 때문에 해당 모양은 배치 모양이 됩니다.

표준 정규 분포도 스칼라입니다. 그것은의 이벤트 모양이다 [] 단지 포아송에 대한처럼, 그러나 우리는 방송의 첫 번째 예제를보고 그것으로 재생할 수 있습니다. 보통은 사용하여 지정 locscale 매개 변수를 :

normal_distributions = [
    tfd.Normal(loc=0., scale=1., name='Standard'),
    tfd.Normal(loc=[0.], scale=1., name='Standard Vector Batch'),
    tfd.Normal(loc=[0., 1., 2., 3.], scale=1., name='Different Locs'),
    tfd.Normal(loc=[0., 1., 2., 3.], scale=[[1.], [5.]],
               name='Broadcasting Scale')
]

describe_distributions(normal_distributions)
tfp.distributions.Normal("Standard", batch_shape=[], event_shape=[], dtype=float32)
tfp.distributions.Normal("Standard_Vector_Batch", batch_shape=[1], event_shape=[], dtype=float32)
tfp.distributions.Normal("Different_Locs", batch_shape=[4], event_shape=[], dtype=float32)
tfp.distributions.Normal("Broadcasting_Scale", batch_shape=[2, 4], event_shape=[], dtype=float32)

흥미로운 예는 상기 인 Broadcasting Scale 분포. loc 파라미터 형태 갖는다 [4] , 상기 scale 파라미터는 형상 갖는 [2, 1] . 사용 NumPy와 방송 규칙을 일괄 형상이다 [2, 4] . 정의 등가 (미만 우아하고-권장하지 않음) 방법 "Broadcasting Scale" 유통은 다음과 같습니다

describe_distributions(
    [tfd.Normal(loc=[[0., 1., 2., 3], [0., 1., 2., 3.]],
                scale=[[1., 1., 1., 1.], [5., 5., 5., 5.]])])
tfp.distributions.Normal("Normal", batch_shape=[2, 4], event_shape=[], dtype=float32)

브로드캐스팅 표기법이 골칫거리와 버그의 원인이기도 하지만 왜 유용한지 알 수 있습니다.

스칼라 분포 샘플링

우리가 분포로 할 수있는 두 가지 주요 가지가있다 : 우리가 할 수 있습니다 sample 그들로부터 우리가 계산할 수 있습니다 log_prob 들. 먼저 샘플링을 살펴보겠습니다. 기본적인 규칙은 우리가 분포로부터 샘플링 될 때, 결과 텐서 형상한다는 것이다 [sample_shape, batch_shape, event_shape] , batch_shapeevent_shape 에 의해 제공되는 Distribution 개체를 sample_shape 호출에 의해 제공되는 sample . 스칼라 분포 들어 event_shape = [] , 그래서 텐서 형상 것이다 샘플로부터 리턴 [sample_shape, batch_shape] . 해 보자:

def describe_sample_tensor_shape(sample_shape, distribution):
    print('Sample shape:', sample_shape)
    print('Returned sample tensor shape:',
          distribution.sample(sample_shape).shape)

def describe_sample_tensor_shapes(distributions, sample_shapes):
    started = False
    for distribution in distributions:
      print(distribution)
      for sample_shape in sample_shapes:
        describe_sample_tensor_shape(sample_shape, distribution)
      print()

sample_shapes = [1, 2, [1, 5], [3, 4, 5]]
describe_sample_tensor_shapes(poisson_distributions, sample_shapes)
tfp.distributions.Poisson("One_Poisson_Scalar_Batch", batch_shape=[], event_shape=[], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1,)
Sample shape: 2
Returned sample tensor shape: (2,)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5)

tfp.distributions.Poisson("Three_Poissons", batch_shape=[3], event_shape=[], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 3)
Sample shape: 2
Returned sample tensor shape: (2, 3)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 3)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 3)

tfp.distributions.Poisson("Two_by_Three_Poissons", batch_shape=[2, 3], event_shape=[], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 2, 3)
Sample shape: 2
Returned sample tensor shape: (2, 2, 3)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 2, 3)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 2, 3)

tfp.distributions.Poisson("One_Poisson_Vector_Batch", batch_shape=[1], event_shape=[], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 1)
Sample shape: 2
Returned sample tensor shape: (2, 1)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 1)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 1)

tfp.distributions.Poisson("One_Poisson_Expanded_Batch", batch_shape=[1, 1], event_shape=[], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 1, 1)
Sample shape: 2
Returned sample tensor shape: (2, 1, 1)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 1, 1)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 1, 1)
describe_sample_tensor_shapes(normal_distributions, sample_shapes)
tfp.distributions.Normal("Standard", batch_shape=[], event_shape=[], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1,)
Sample shape: 2
Returned sample tensor shape: (2,)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5)

tfp.distributions.Normal("Standard_Vector_Batch", batch_shape=[1], event_shape=[], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 1)
Sample shape: 2
Returned sample tensor shape: (2, 1)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 1)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 1)

tfp.distributions.Normal("Different_Locs", batch_shape=[4], event_shape=[], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 4)
Sample shape: 2
Returned sample tensor shape: (2, 4)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 4)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 4)

tfp.distributions.Normal("Broadcasting_Scale", batch_shape=[2, 4], event_shape=[], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 2, 4)
Sample shape: 2
Returned sample tensor shape: (2, 2, 4)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 2, 4)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 2, 4)

에 대해 말하는이 모든 약의 것으로 sample : 반환 샘플 텐서는 모양이 [sample_shape, batch_shape, event_shape] .

계산 log_prob 스칼라 배포판의 경우

이제 살펴 보자 log_prob 다소 까다 롭습니다. log_prob 입력으로 계산할 수있는 위치 (S)를 나타내는 (비어) 텐서 얻어 log_prob 분포를 들어. 가장 간단한 경우에는,이 텐서 형태의 형상 것 [sample_shape, batch_shape, event_shape] 어디 batch_shapeevent_shape 매치 분포의 배치 및 형상 이벤트. 리콜 한번 그 스칼라 분포 들면 event_shape = [] , 입력 텐서 형상 갖도록 [sample_shape, batch_shape] 이 경우에, 우리는 형상의 텐서 돌아올 [sample_shape, batch_shape] :

three_poissons = tfd.Poisson(rate=[1., 10., 100.], name='Three Poissons')
three_poissons
<tfp.distributions.Poisson 'Three_Poissons' batch_shape=[3] event_shape=[] dtype=float32>
three_poissons.log_prob([[1., 10., 100.], [100., 10., 1]])  # sample_shape is [2].
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[  -1.       ,   -2.0785608,   -3.2223587],
       [-364.73938  ,   -2.0785608,  -95.39484  ]], dtype=float32)>
three_poissons.log_prob([[[[1., 10., 100.], [100., 10., 1.]]]])  # sample_shape is [1, 1, 2].
<tf.Tensor: shape=(1, 1, 2, 3), dtype=float32, numpy=
array([[[[  -1.       ,   -2.0785608,   -3.2223587],
         [-364.73938  ,   -2.0785608,  -95.39484  ]]]], dtype=float32)>

참고 첫 번째 예에서, 입력 및 출력은 형상이 방법 [2, 3] 그들이 형상이 두 번째 예에서 [1, 1, 2, 3] .

방송만 아니었다면 할 말은 이 정도였다. 방송을 고려했을 때의 규칙은 다음과 같습니다. 우리는 그것을 완전히 일반화하고 스칼라 분포에 대한 단순화에 주목합니다.

  1. 정의 n = len(batch_shape) + len(event_shape) . (라 분포를 들어, len(event_shape)=0 ).
  2. 입력 텐서하면 t 보다 적게 갖는 n 크기의 기준 치수에 추가하여, 패드의 형상을 1 왼쪽에 정확히 보유까지 n 차원. 결과 텐서 전화 t' .
  3. 브로드 캐스팅 n 의 오른쪽 치수 t' 에 대한 [batch_shape, event_shape] 당신이 계산하고있는 유통의 log_prob 를 들어. 구체적으로 : 치수에 대한 t' 이미 유통 일치, 아무것도 할 수없고, 치수 t' , 복제를 싱글 톤을 가지고 그 시대의 적절한 수의 싱글. 다른 모든 상황은 오류입니다. (라 분포를 들어, 우리는에 대해 방송 batch_shape event_shape = 때문에, [] ).
  4. 이제 우리는 마지막으로 계산할 수있어 log_prob . 얻어진 텐서 형상 것 [sample_shape, batch_shape] , sample_shape 어떤 기준으로 정의된다 t 또는 t' 상기 왼쪽에 n : -rightmost 치수 sample_shape = shape(t)[:-n] .

의미를 모르는 경우 혼란스러울 수 있으므로 몇 가지 예를 들어보겠습니다.

three_poissons.log_prob([10.])
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([-16.104412 ,  -2.0785608, -69.05272  ], dtype=float32)>

텐서 [10.] (형상은 [1] )를 통해 방송되는 batch_shape 우리가 값 10 세 물고기 자리 '로그 확률을 평가하므로, 3.

three_poissons.log_prob([[[1.], [10.]], [[100.], [1000.]]])
<tf.Tensor: shape=(2, 2, 3), dtype=float32, numpy=
array([[[-1.0000000e+00, -7.6974149e+00, -9.5394836e+01],
        [-1.6104412e+01, -2.0785608e+00, -6.9052719e+01]],

       [[-3.6473938e+02, -1.4348087e+02, -3.2223587e+00],
        [-5.9131279e+03, -3.6195427e+03, -1.4069575e+03]]], dtype=float32)>

위의 예에서, 입력 텐서 형상 갖는 [2, 2, 1] 분포 오브젝트가 각각 3 정도의 배치 형상되었지만, [2, 2] 샘플의 크기를 제공하는 하나의 값을 각각 broadcats을 얻는다을 세 포아송 중.

가능성이있는 유용한 방법이 생각 : 때문에 three_poissons 보유 batch_shape = [2, 3] , 호출 log_prob 마지막 차원 1 또는 3 텐서를 취한다; 다른 것은 오류입니다. 합니다 (NumPy와 방송 규칙 형상의 텐서로 완전히 동등한 것으로 스칼라의 특별 케이스를 취급 [1] ).

와 더 복잡한 포아송 분포를 연주하여 우리의 갈비하자 시험 batch_shape = [2, 3] :

poisson_2_by_3 = tfd.Poisson(
    rate=[[1., 10., 100.,], [2., 20., 200.]],
    name='Two-by-Three Poissons')
poisson_2_by_3.log_prob(1.)
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[  -1.       ,   -7.697415 ,  -95.39484  ],
       [  -1.3068528,  -17.004269 , -194.70169  ]], dtype=float32)>
poisson_2_by_3.log_prob([1.])  # Exactly equivalent to above, demonstrating the scalar special case.
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[  -1.       ,   -7.697415 ,  -95.39484  ],
       [  -1.3068528,  -17.004269 , -194.70169  ]], dtype=float32)>
poisson_2_by_3.log_prob([[1., 1., 1.], [1., 1., 1.]])  # Another way to write the same thing. No broadcasting.
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[  -1.       ,   -7.697415 ,  -95.39484  ],
       [  -1.3068528,  -17.004269 , -194.70169  ]], dtype=float32)>
poisson_2_by_3.log_prob([[1., 10., 100.]])  # Input is [1, 3] broadcast to [2, 3].
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[ -1.       ,  -2.0785608,  -3.2223587],
       [ -1.3068528,  -5.14709  , -33.90767  ]], dtype=float32)>
poisson_2_by_3.log_prob([[1., 10., 100.], [1., 10., 100.]])  # Equivalent to above. No broadcasting.
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[ -1.       ,  -2.0785608,  -3.2223587],
       [ -1.3068528,  -5.14709  , -33.90767  ]], dtype=float32)>
poisson_2_by_3.log_prob([[1., 1., 1.], [2., 2., 2.]])  # No broadcasting.
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[  -1.       ,   -7.697415 ,  -95.39484  ],
       [  -1.3068528,  -14.701683 , -190.09653  ]], dtype=float32)>
poisson_2_by_3.log_prob([[1.], [2.]])  # Equivalent to above. Input shape [2, 1] broadcast to [2, 3].
<tf.Tensor: shape=(2, 3), dtype=float32, numpy=
array([[  -1.       ,   -7.697415 ,  -95.39484  ],
       [  -1.3068528,  -14.701683 , -190.09653  ]], dtype=float32)>

위의 예에는 일괄 처리에 대한 브로드캐스팅이 포함되어 있지만 샘플 모양은 비어 있습니다. 값 모음이 있고 배치의 각 지점에서 각 값의 로그 확률을 얻으려고 한다고 가정합니다. 수동으로 할 수 있습니다.

poisson_2_by_3.log_prob([[[1., 1., 1.], [1., 1., 1.]], [[2., 2., 2.], [2., 2., 2.]]])  # Input shape [2, 2, 3].
<tf.Tensor: shape=(2, 2, 3), dtype=float32, numpy=
array([[[  -1.       ,   -7.697415 ,  -95.39484  ],
        [  -1.3068528,  -17.004269 , -194.70169  ]],

       [[  -1.6931472,   -6.087977 ,  -91.48282  ],
        [  -1.3068528,  -14.701683 , -190.09653  ]]], dtype=float32)>

또는 브로드캐스팅이 마지막 배치 차원을 처리하도록 할 수 있습니다.

poisson_2_by_3.log_prob([[[1.], [1.]], [[2.], [2.]]])  # Input shape [2, 2, 1].
<tf.Tensor: shape=(2, 2, 3), dtype=float32, numpy=
array([[[  -1.       ,   -7.697415 ,  -95.39484  ],
        [  -1.3068528,  -17.004269 , -194.70169  ]],

       [[  -1.6931472,   -6.087977 ,  -91.48282  ],
        [  -1.3068528,  -14.701683 , -190.09653  ]]], dtype=float32)>

또한 브로드캐스팅이 첫 번째 배치 차원만 처리하도록 할 수도 있습니다.

poisson_2_by_3.log_prob([[[1., 1., 1.]], [[2., 2., 2.]]])  # Input shape [2, 1, 3].
<tf.Tensor: shape=(2, 2, 3), dtype=float32, numpy=
array([[[  -1.       ,   -7.697415 ,  -95.39484  ],
        [  -1.3068528,  -17.004269 , -194.70169  ]],

       [[  -1.6931472,   -6.087977 ,  -91.48282  ],
        [  -1.3068528,  -14.701683 , -190.09653  ]]], dtype=float32)>

아니면 핸들을 모두 배치 크기를 방송 할 수있다 :

poisson_2_by_3.log_prob([[[1.]], [[2.]]])  # Input shape [2, 1, 1].
<tf.Tensor: shape=(2, 2, 3), dtype=float32, numpy=
array([[[  -1.       ,   -7.697415 ,  -95.39484  ],
        [  -1.3068528,  -17.004269 , -194.70169  ]],

       [[  -1.6931472,   -6.087977 ,  -91.48282  ],
        [  -1.3068528,  -14.701683 , -190.09653  ]]], dtype=float32)>

위의 방법은 원하는 값이 두 개뿐일 때 제대로 작동했지만 모든 배치 지점에서 평가하려는 값의 긴 목록이 있다고 가정합니다. 이를 위해 모양의 오른쪽에 크기 1의 추가 차원을 추가하는 다음 표기법이 매우 유용합니다.

poisson_2_by_3.log_prob(tf.constant([1., 2.])[..., tf.newaxis, tf.newaxis])
<tf.Tensor: shape=(2, 2, 3), dtype=float32, numpy=
array([[[  -1.       ,   -7.697415 ,  -95.39484  ],
        [  -1.3068528,  -17.004269 , -194.70169  ]],

       [[  -1.6931472,   -6.087977 ,  -91.48282  ],
        [  -1.3068528,  -14.701683 , -190.09653  ]]], dtype=float32)>

이것은의 인스턴스 스트라이드 슬라이스 표기법 아는 가치가있다.

다시가는 three_poissons 완성도, 같은 예를 들어, 외모와 같은 :

three_poissons.log_prob([[1.], [10.], [50.], [100.]])
<tf.Tensor: shape=(4, 3), dtype=float32, numpy=
array([[  -1.       ,   -7.697415 ,  -95.39484  ],
       [ -16.104412 ,   -2.0785608,  -69.05272  ],
       [-149.47777  ,  -43.34851  ,  -18.219261 ],
       [-364.73938  , -143.48087  ,   -3.2223587]], dtype=float32)>
three_poissons.log_prob(tf.constant([1., 10., 50., 100.])[..., tf.newaxis])  # Equivalent to above.
<tf.Tensor: shape=(4, 3), dtype=float32, numpy=
array([[  -1.       ,   -7.697415 ,  -95.39484  ],
       [ -16.104412 ,   -2.0785608,  -69.05272  ],
       [-149.47777  ,  -43.34851  ,  -18.219261 ],
       [-364.73938  , -143.48087  ,   -3.2223587]], dtype=float32)>

다변수 분포

이제 비어 있지 않은 이벤트 모양을 가진 다변량 분포로 전환합니다. 다항 분포를 살펴보겠습니다.

multinomial_distributions = [
    # Multinomial is a vector-valued distribution: if we have k classes,
    # an individual sample from the distribution has k values in it, so the
    # event_shape is `[k]`.
    tfd.Multinomial(total_count=100., probs=[.5, .4, .1],
                    name='One Multinomial'),
    tfd.Multinomial(total_count=[100., 1000.], probs=[.5, .4, .1],
                    name='Two Multinomials Same Probs'),
    tfd.Multinomial(total_count=100., probs=[[.5, .4, .1], [.1, .2, .7]],
                    name='Two Multinomials Same Counts'),
    tfd.Multinomial(total_count=[100., 1000.],
                    probs=[[.5, .4, .1], [.1, .2, .7]],
                    name='Two Multinomials Different Everything')

]

describe_distributions(multinomial_distributions)
tfp.distributions.Multinomial("One_Multinomial", batch_shape=[], event_shape=[3], dtype=float32)
tfp.distributions.Multinomial("Two_Multinomials_Same_Probs", batch_shape=[2], event_shape=[3], dtype=float32)
tfp.distributions.Multinomial("Two_Multinomials_Same_Counts", batch_shape=[2], event_shape=[3], dtype=float32)
tfp.distributions.Multinomial("Two_Multinomials_Different_Everything", batch_shape=[2], event_shape=[3], dtype=float32)

참고 마지막 세 가지 예에서, batch_shape는 항상 방법 [2] , 그러나 우리는이 공유 하나에 방송 사용할 수 있습니다 total_count 또는 공유 probs 후드가 같은 형상으로 방송되기 때문에, (또는 둘 다).

우리가 이미 알고 있는 것을 감안할 때 샘플링은 간단합니다.

describe_sample_tensor_shapes(multinomial_distributions, sample_shapes)
tfp.distributions.Multinomial("One_Multinomial", batch_shape=[], event_shape=[3], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 3)
Sample shape: 2
Returned sample tensor shape: (2, 3)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 3)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 3)

tfp.distributions.Multinomial("Two_Multinomials_Same_Probs", batch_shape=[2], event_shape=[3], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 2, 3)
Sample shape: 2
Returned sample tensor shape: (2, 2, 3)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 2, 3)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 2, 3)

tfp.distributions.Multinomial("Two_Multinomials_Same_Counts", batch_shape=[2], event_shape=[3], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 2, 3)
Sample shape: 2
Returned sample tensor shape: (2, 2, 3)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 2, 3)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 2, 3)

tfp.distributions.Multinomial("Two_Multinomials_Different_Everything", batch_shape=[2], event_shape=[3], dtype=float32)
Sample shape: 1
Returned sample tensor shape: (1, 2, 3)
Sample shape: 2
Returned sample tensor shape: (2, 2, 3)
Sample shape: [1, 5]
Returned sample tensor shape: (1, 5, 2, 3)
Sample shape: [3, 4, 5]
Returned sample tensor shape: (3, 4, 5, 2, 3)

로그 확률을 계산하는 것도 마찬가지로 간단합니다. 대각선 다변량 정규 분포의 예를 살펴보겠습니다. (다항식은 카운트와 확률에 대한 제약이 종종 허용할 수 없는 값을 생성한다는 것을 의미하기 때문에 브로드캐스트 친화적이지 않습니다.) 평균은 같지만 척도(표준 편차)가 다른 2개의 3차원 분포 배치를 사용할 것입니다.

two_multivariate_normals = tfd.MultivariateNormalDiag(loc=[1., 2., 3.], scale_identity_multiplier=[1., 2.])
two_multivariate_normals
<tfp.distributions.MultivariateNormalDiag 'MultivariateNormalDiag' batch_shape=[2] event_shape=[3] dtype=float32>

(우리는 스케일 신원의 배수로 있었다 분포를 이용하지만, 이것에 제한되는 것은 아니다 우리가 통과 할 수 scale 대신 scale_identity_multiplier ).

이제 평균과 이동 평균에서 각 배치 포인트의 로그 확률을 평가해 보겠습니다.

two_multivariate_normals.log_prob([[[1., 2., 3.]], [[3., 4., 5.]]])  # Input has shape [2,1,3].
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[-2.7568154, -4.836257 ],
       [-8.756816 , -6.336257 ]], dtype=float32)>

정확히 동등하게, 우리가 사용할 수 있습니다 https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/strided-slice을 추가 모양 = 상수의 중간에 한 차원을 삽입 :

two_multivariate_normals.log_prob(
    tf.constant([[1., 2., 3.], [3., 4., 5.]])[:, tf.newaxis, :])  # Equivalent to above.
<tf.Tensor: shape=(2, 2), dtype=float32, numpy=
array([[-2.7568154, -4.836257 ],
       [-8.756816 , -6.336257 ]], dtype=float32)>

우리는 여분의 차원 삽입하지 않으면 다른 한편으로, 우리가 통과 [1., 2., 3.] 첫 번째 일괄 포인트와 [3., 4., 5.] 두 번째로 :

two_multivariate_normals.log_prob(tf.constant([[1., 2., 3.], [3., 4., 5.]]))
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([-2.7568154, -6.336257 ], dtype=float32)>

모양 조작 기법

리셰이프 바이젝터

Reshape bijector는 분포의 event_shape 모양을 변경하는 데 사용할 수 있습니다. 예를 들어 보겠습니다.

six_way_multinomial = tfd.Multinomial(total_count=1000., probs=[.3, .25, .2, .15, .08, .02])
six_way_multinomial
<tfp.distributions.Multinomial 'Multinomial' batch_shape=[] event_shape=[6] dtype=float32>

우리의 일정 모양으로 다항식을 작성 [6] . 모양 변경 Bijector은 우리의 이벤트 형상의 분포로이를 처리 할 수 [2, 3] .

Bijector 의 개방 서브셋에 미분 일대일 함수 나타내는 \({\mathbb R}^n\). Bijectors 함께 사용되어 TransformedDistribution 어느 모델 분배 \(p(y)\) 베이스 분포 환산 \(p(x)\) 및 Bijector 나타내는 \(Y = g(X)\). 실제로 작동해 보겠습니다.

transformed_multinomial = tfd.TransformedDistribution(
    distribution=six_way_multinomial,
    bijector=tfb.Reshape(event_shape_out=[2, 3]))
transformed_multinomial
<tfp.distributions.TransformedDistribution 'reshapeMultinomial' batch_shape=[] event_shape=[2, 3] dtype=float32>
six_way_multinomial.log_prob([500., 100., 100., 150., 100., 50.])
<tf.Tensor: shape=(), dtype=float32, numpy=-178.22021>
transformed_multinomial.log_prob([[500., 100., 100.], [150., 100., 50.]])
<tf.Tensor: shape=(), dtype=float32, numpy=-178.22021>

이것은 유일한 일이 Reshape bijector 할 수 있습니다 : 그것은 배치 차원 또는 그 반대에 이벤트 차원을 켤 수 없습니다.

독립 배포

Independent 분포는 단일 분포로서 독립적-반드시 동일하지 아니 컬렉션 (일명 배치) 분포를 치료하는데 사용된다. 더 간결하게, Independent 의 크기를 변환 할 수 있습니다 batch_shape 의 차원에 event_shape . 예를 들어 설명하겠습니다.

two_by_five_bernoulli = tfd.Bernoulli(
    probs=[[.05, .1, .15, .2, .25], [.3, .35, .4, .45, .5]],
    name="Two By Five Bernoulli")
two_by_five_bernoulli
<tfp.distributions.Bernoulli 'Two_By_Five_Bernoulli' batch_shape=[2, 5] event_shape=[] dtype=int32>

우리는 이것을 앞면의 확률과 관련된 2x5 동전 배열로 생각할 수 있습니다. 임의의 1과 0 집합의 확률을 평가해 보겠습니다.

pattern = [[1., 0., 0., 1., 0.], [0., 0., 1., 1., 1.]]
two_by_five_bernoulli.log_prob(pattern)
<tf.Tensor: shape=(2, 5), dtype=float32, numpy=
array([[-2.9957323 , -0.10536052, -0.16251892, -1.609438  , -0.2876821 ],
       [-0.35667497, -0.4307829 , -0.9162907 , -0.7985077 , -0.6931472 ]],
      dtype=float32)>

우리가 사용할 수있는 Independent 우리가 동전의 "행"을 고려할 경우, 유용하는 두 개의 서로 다른 "오 베르누이의 집합"이 점을 설정하는 플립 하나의 결과로 주어진 패턴에서 오는 :

two_sets_of_five = tfd.Independent(
    distribution=two_by_five_bernoulli,
    reinterpreted_batch_ndims=1,
    name="Two Sets Of Five")
two_sets_of_five
<tfp.distributions.Independent 'Two_Sets_Of_Five' batch_shape=[2] event_shape=[5] dtype=int32>

수학적으로, 우리는 집합에서 5개의 "독립적인" 동전 던지기의 로그 확률을 합산하여 5의 각 "집합"의 로그 확률을 계산하고 있습니다. 여기서 분포는 이름을 얻습니다.

two_sets_of_five.log_prob(pattern)
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([-5.160732 , -3.1954036], dtype=float32)>

우리는 심지어 더 나아가 사용할 수있는 Independent 개별 이벤트는 두 개의 별 다섯 베르누이의 집합 어디에 분포를 만들 :

one_set_of_two_by_five = tfd.Independent(
    distribution=two_by_five_bernoulli, reinterpreted_batch_ndims=2,
    name="One Set Of Two By Five")
one_set_of_two_by_five.log_prob(pattern)
<tf.Tensor: shape=(), dtype=float32, numpy=-8.356134>

의 관점에서 그 지적이의 가치가 sample 사용하여 Independent 아무것도 변경되지 않습니다 :

describe_sample_tensor_shapes(
    [two_by_five_bernoulli,
     two_sets_of_five,
     one_set_of_two_by_five],
    [[3, 5]])
tfp.distributions.Bernoulli("Two_By_Five_Bernoulli", batch_shape=[2, 5], event_shape=[], dtype=int32)
Sample shape: [3, 5]
Returned sample tensor shape: (3, 5, 2, 5)

tfp.distributions.Independent("Two_Sets_Of_Five", batch_shape=[2], event_shape=[5], dtype=int32)
Sample shape: [3, 5]
Returned sample tensor shape: (3, 5, 2, 5)

tfp.distributions.Independent("One_Set_Of_Two_By_Five", batch_shape=[], event_shape=[2, 5], dtype=int32)
Sample shape: [3, 5]
Returned sample tensor shape: (3, 5, 2, 5)

독자 파팅 운동으로, 우리는 벡터의 배치의 차이와 유사점을 고려 제안 Normal 분포 및 MultivariateNormalDiag 샘플링 및 로그 확률 분포의 관점에서. 우리는 어떻게 사용할 수있는 Independent 구축 MultivariateNormalDiag 의 배치에서 Normal 의? (참고 MultivariateNormalDiag 실제로이 방법을 구현되지 않습니다.)