TensorFlow Dağılım Şekillerini Anlama

TensorFlow.org'da görüntüleyin Google Colab'da çalıştırın Kaynağı GitHub'da görüntüleyin Not defterini indir
import collections

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

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

temel bilgiler

TensorFlow Dağılımları şekilleri ile ilişkili üç önemli kavram vardır:

  • Olay şekli dağılımı tek çizmek şeklini tarif eder; boyutlar arasında bağımlı olabilir. Sayıl dağılımlar için, olay şekildir [] . 5-boyutlu MultivariateNormal için, etkinlik şekli [5] .
  • Toplu şekli aynı dağılımların bir "toplu" aka çizer dağıtılan değil, bağımsız açıklar.
  • Numune şekli, aynı dağıtılan bağımsız açıklar dağıtım aileden serilerin çizer.

Olay şekli ve toplu şekli özellikleri olan Distribution örnek şekil için özel bir çağrı ile ilişkili olan ise, nesne sample veya log_prob .

Bu defterin amacı, bu kavramları örneklerle açıklamaktır, bu yüzden bu hemen açık değilse endişelenmeyin!

Bu kavramların başka kavramsal bakış için bkz bu blog yazısı .

TensorFlow Hevesli hakkında bir not.

Bu, tüm dizüstü kullanılarak yazılır istekli TensorFlow . Zaman istekli, dağıtım kesikli ve olay şekilleri değerlendirildi (ve dolayısıyla da bilinir) vardır ile her ne kadar kavramların hiçbiri, istekli güvenmek sunulan Distribution nesne Python oluşturulur grafiktir (non-istekli modu) ise, dağılımları tanımlamak mümkündür olay ve toplu şekiller grafik çalıştırılana kadar belirsizdir.

Skaler Dağılımlar

Yukarıda belirtildiği gibi, bir Distribution nesnesinin olay ve toplu şekiller tanımlamıştır. Dağıtımları açıklamak için bir yardımcı programla başlayacağız:

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

Bu bölümde sayısal dağılımlarını inceleyeceğiz: dağılımlarını bir olay şeklinde [] . Tipik bir örnek olarak belirtilen Poisson dağılımı, bir 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)

, Olay şekli her zaman çok Poisson dağılımı, bir skaler dağılımıdır [] . Daha fazla oran belirtirsek, bunlar parti şeklinde görünür. Son örnek çifti ilginçtir: yalnızca tek bir oran vardır, ancak bu oran boş olmayan şekle sahip bir numpy dizisine gömülü olduğundan, bu şekil toplu şekil olur.

Standart Normal dağılım da bir skalerdir. It olay şekli [] sadece Poisson için olduğu gibi, ama biz yayın bizim ilk örneğini görmek için onunla oynayacağız. Normal kullanılarak belirtilir loc ve scale parametrelerine:

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)

İlginç bir örnek üzerinde olduğu Broadcasting Scale dağılımı. loc parametresi şekline sahip [4] , ve scale parametre şekle sahiptir [2, 1] . Kullanma Numpy yayın kuralları , toplu şekli [2, 4] . Tanımlamak için bir eşdeğer (ama daha az zarif ve-önerilmez) yolu "Broadcasting Scale" dağıtımı olacaktır:

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)

Aynı zamanda bir baş ağrısı ve hata kaynağı olmasına rağmen, yayın gösteriminin neden yararlı olduğunu görebiliriz.

Skaler Dağılımları Örnekleme

Biz dağılımları ile yapabileceğiniz iki şey vardır: biz edebilirsiniz sample onlardan ve biz hesaplayabilir log_prob s. Önce örneklemeyi inceleyelim. Temel kural bir dağılımdan örnek zaman, elde edilen tensör şekle sahip olmasıdır [sample_shape, batch_shape, event_shape] , batch_shape ve event_shape tarafından sağlanan Distribution nesnesi ve sample_shape çağrısı ile sağlanır sample . Skalar dağılımlar için, event_shape = [] , bu yüzden tensör şekle sahip olacaktır numuneden geri [sample_shape, batch_shape] . Hadi deneyelim:

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)

Hakkında söylenecek var tüm ilgili en That sample : döndürdü örnek tansörler şekle sahip [sample_shape, batch_shape, event_shape] .

Bilgisayar log_prob Skaler Dağılımları İçin

Şimdi de tabloya bakalım log_prob biraz daha zordur. log_prob girdi olarak hesaplamak için hangi yer (ler) temsil eden bir (boş olmayan) tensörü alır log_prob dağıtımı için. En basit durumda bu tensör formunun bir şekle sahip olacaktır [sample_shape, batch_shape, event_shape] , burada batch_shape ve event_shape eşleme dağılımının toplu ve olay şekilleri. Hatırlama kez daha o sayıl dağılımlar için, event_shape = [] , giriş tensör şekline sahiptir, böylece [sample_shape, batch_shape] Bu durumda, şeklin bir tensörünü geri almak [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)>

Not İlk örnekte, giriş ve çıkış şekline sahip nasıl [2, 3] ve şekle sahip ikinci bir örnekte [1, 1, 2, 3] .

Yayın için olmasaydı, söylenecek tek şey bu olurdu. İşte yayıncılığı hesaba kattığımızda kurallar. Bunu tam bir genellemeyle açıklıyoruz ve skaler dağılımlar için sadeleştirmeleri not ediyoruz:

  1. Tanımlama n = len(batch_shape) + len(event_shape) . (Skalar dağılımlar için, len(event_shape)=0 ).
  2. Giriş tensör Eğer t den az olan n büyüklükte boyutları ekleyerek boyutları, ped şeklini 1 sol tam olarak sahip olana kadar n boyutları. Ortaya çıkan tensör Çağrı t' .
  3. Yayın n en sağdaki boyutları t' karşı [batch_shape, event_shape] bir işlem konum dağılımının log_prob için. Daha ayrıntılı olarak: boyutlar için t' zaten dağılımını maçları, hiçbir şey yapmak ve boyutlar t' , kopyalayan a tek sahip olduğu zamanlarda uygun sayıda tekil. Diğer herhangi bir durum bir hatadır. (Skaler dağılımlar için, biz sadece karşı yayın batch_shape event_shape = beri, [] .)
  4. Artık nihayet hesaplamak mümkün olacaktır log_prob . Elde edilen tensör şekle sahip olacaktır [sample_shape, batch_shape] , sample_shape herhangi boyutları olarak tanımlanır t veya t' sağdan sola n : -rightmost boyutları sample_shape = shape(t)[:-n] .

Ne anlama geldiğini bilmiyorsanız bu bir karışıklık olabilir, o yüzden bazı örnekler üzerinde çalışalım:

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

Tensör [10.] (şekle sahip [1] ) boyunca yayın batch_shape biz 10 değeri her üç Poisson log olasılık değerlendirmek, böylece 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)>

Yukarıdaki örnekte, giriş tensör şekle sahiptir [2, 2, 1] dağılımları nesnenin her biri için 3 So bir parti biçimindeyken [2, 2] Örnek boyutlar, temin edilen tek bir değer her bir broadcats alır üç Poisson'dan.

Bir muhtemelen yararlı bir yol düşünmek çünkü: three_poissons sahip batch_shape = [2, 3] , bir çağrı log_prob son boyut, ya 1 ya da 3 olan bir Tensörü almalıdır; başka bir şey bir hatadır. (Numpy yayın kuralları şekilli bir Tensörün tamamen eşdeğer olarak bir sayısal özel bir durumunu tedavi [1] ).

Daha karmaşık Poisson dağılımına sahip oynayarak pirzola Let test 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)>

Yukarıdaki örnekler, yığın üzerinden yayın yapmayı içeriyordu, ancak numune şekli boştu. Bir değerler koleksiyonumuz olduğunu ve partideki her noktada her değerin günlük olasılığını elde etmek istediğimizi varsayalım. Bunu manuel olarak yapabiliriz:

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)>

Veya yayının son toplu iş boyutunu ele almasına izin verebiliriz:

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)>

Ayrıca (belki daha az doğal olarak) yayının yalnızca ilk toplu iş boyutunu ele almasına izin verebiliriz:

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)>

Ya da sap hem toplu boyutlarını yayın izin verebilir:

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)>

İstediğimiz yalnızca iki değere sahip olduğumuzda yukarıdakiler işe yaradı, ancak her parti noktasında değerlendirmek istediğimiz uzun bir değer listemiz olduğunu varsayalım. Bunun için, şeklin sağ tarafına ekstra boyut 1 ekleyen aşağıdaki gösterim son derece yararlıdır:

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)>

Bu bir örneğidir strided dilim gösterimde bilerek değer.

Dönersek three_poissons tamlığı için, aynı örnek görünüyor gibi:

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)>

Çok değişkenli dağılımlar

Şimdi boş olmayan olay şekline sahip çok değişkenli dağılımlara dönüyoruz. Şimdi çok terimli dağılımlara bakalım.

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)

Not son üç örneklerde, batch_shape daima nasıl [2] , ama biz var paylaşılan birine yayın kullanabilirsiniz total_count veya paylaşılan probs başlık altında aynı şekle sahip yayın, çünkü (veya hiçbiri).

Halihazırda bildiklerimiz göz önüne alındığında, örnekleme basittir:

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)

Günlük olasılıklarını hesaplamak da aynı derecede basittir. Çapraz Çok Değişkenli Normal dağılımlarla bir örnek üzerinde çalışalım. (Sayılar ve olasılıklar üzerindeki kısıtlamalar, yayının genellikle kabul edilemez değerler üreteceği anlamına geldiğinden, çok terimli ifadeler çok yayın dostu değildir.) Aynı ortalama ancak farklı ölçekler (standart sapmalar) ile 2 adet 3 boyutlu dağılım toplu kullanacağız:

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>

(Biz terazi kimlik katları olan dağılımları kullanılabilir, ancak bu bir kısıtlama değildir Not, biz geçebileceği scale yerine scale_identity_multiplier .)

Şimdi her parti noktasının günlük olasılığını kendi ortalamasında ve kaydırılmış bir ortalamada değerlendirelim:

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)>

Tam eşdeğer olarak kullanabileceğimiz https://www.tensorflow.org/api_docs/cc/class/tensorflow/ops/strided-slice fazladan bir şekle = bir sabit ortasında 1 boyut eklemek için:

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)>

Ekstra bir boyut uç değil, diğer yandan, biz geçmesi [1., 2., 3.] ilk parti noktasına ve [3., 4., 5.] ikinci:

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)>

Şekil Manipülasyon Teknikleri

Yeniden Şekillendirme Bijektörü

Reshape bijector Bir dağılımın event_shape yeniden şekillendirmek için de kullanılabilir. Bir örnek görelim:

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>

Biz bir olay şeklinde bir katlıterimini yarattı [6] . Yeniden şekillendirme Bijector bize ait bir olay şeklinde bir dağıtım olarak tedavi sağlar [2, 3] .

Bir Bijector açık alt kümesini türevlenebilir, bire bir fonksiyonu temsil \({\mathbb R}^n\). Bijectors ile bağlantılı olarak kullanılan TransformedDistribution , bu model bir dağıtım \(p(y)\) bir baz dağılımı açısından \(p(x)\) ve Bijector temsil \(Y = g(X)\). Eylemde görelim:

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>

Bu tek şey Reshape bijector yapabilir: bu toplu boyutları veya tersi olarak etkinlik boyutları dönemez.

Bağımsız Dağıtım

Independent dağılımı tek bir dağılım olarak bağımsız bir,-mutlaka-özdeş olmayan toplanması (aka bir toplu) dağılımları tedavi etmek için kullanılır. Daha öz, Independent boyutları dönüştürmek sağlar batch_shape içinde boyutlara event_shape . Örnekle açıklayacağız:

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>

Bunu, tura olasılıklarıyla ilişkili ikişer beşlik madeni para dizisi olarak düşünebiliriz. Belirli, rastgele bir birler ve sıfırlar kümesinin olasılığını değerlendirelim:

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)>

Biz kullanabilirsiniz Independent biz madalyonun bir "satır" dikkate alınmasını istiyorsanız, kullanışlı olduğu iki farklı "beş Bernoulli setleri" çevirmeye çevirir tek bir sonuç olarak, belirli bir desende geliyor:

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>

Matematiksel olarak, kümedeki beş "bağımsız" yazı turasının log olasılıklarını toplayarak her bir "kümenin" log olasılığını hesaplıyoruz; bu, dağılımın adını aldığı yerdir:

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

Hatta daha ileri giderek kullanabilirsiniz Independent bireysel olaylar iki tarafından beş Bernoulli bir dizi olduğu bir dağılım oluşturmak için:

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>

Perspektifinden belirterek It değerinde sample kullanılarak Independent şey değiştirir:

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)

Okuyucu için bir veda egzersiz olarak, bir vektör toplu arasındaki farklılıkları ve benzerlikleri dikkate öneririz Normal dağılımlar ve MultivariateNormalDiag bir örnekleme ve günlük olasılık açısından dağılımı. Nasıl kullanabilirsiniz Independent bir inşa etmek MultivariateNormalDiag Bir grup Normal s? (Not MultivariateNormalDiag gerçekten de bu şekilde uygulanmadı.)