TensorFlow.org'da görüntüleyin | Google Colab'da çalıştırın | Kaynağı GitHub'da görüntüleyin | Not defterini indir |
Bu not defterinde TensorFlow Dağıtımlarını (kısaca TFD) keşfedeceğiz. Bu not defterinin amacı, TFD'nin tensör şekillerini nasıl ele aldığını anlamak da dahil olmak üzere, sizi öğrenme eğrisinde yavaşça yukarıya çıkarmaktır. Bu defter, soyut kavramlardan ziyade örnekleri önceden sunmaya çalışır. İlk önce işleri yapmanın kanonik kolay yollarını sunacağız ve en genel soyut görünümü sona saklayacağız. Eğer daha soyut ve referans tarzı öğretici tercih türünü iseniz, kontrol TensorFlow Dağılımları Şekilleri anlama . Burada materyalin hakkında herhangi bir sorunuz varsa, temas tereddüt (veya katılmak) yok TensorFlow Olasılık posta listesi . Yardım etmekten mutluluk duyarız.
Başlamadan önce uygun kütüphaneleri içe aktarmamız gerekiyor. Bizim genel kütüphane tensorflow_probability
. Geleneksel olarak, biz genelde dağılımları kütüphanesine bakın tfd
.
Tensorflow Hevesli TensorFlow için bir zorunluluk yürütme ortamıdır. TensorFlow istekli'de her TF işlemi anında değerlendirilir ve bir sonuç üretir. Bu, TensorFlow'un TF işlemlerinin daha sonra yürütülecek bir grafiğe düğümler eklediği standart "graf" modunun aksinedir. Bu not defterinin tamamı TF Eager kullanılarak yazılmıştır, ancak burada sunulan kavramların hiçbiri buna dayanmaz ve TFP grafik modunda kullanılabilir.
import collections
import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions
try:
tf.compat.v1.enable_eager_execution()
except ValueError:
pass
import matplotlib.pyplot as plt
Temel Tek Değişkenli Dağılımlar
Hemen konuya girelim ve normal bir dağılım oluşturalım:
n = tfd.Normal(loc=0., scale=1.)
n
<tfp.distributions.Normal 'Normal' batch_shape=[] event_shape=[] dtype=float32>
Ondan bir örnek alabiliriz:
n.sample()
<tf.Tensor: shape=(), dtype=float32, numpy=0.25322816>
Birden fazla örnek çizebiliriz:
n.sample(3)
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([-1.4658079, -0.5653636, 0.9314412], dtype=float32)>
Bir günlük probunu değerlendirebiliriz:
n.log_prob(0.)
<tf.Tensor: shape=(), dtype=float32, numpy=-0.9189385>
Birden çok günlük olasılığını değerlendirebiliriz:
n.log_prob([0., 2., 4.])
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([-0.9189385, -2.9189386, -8.918939 ], dtype=float32)>
Geniş bir dağıtım yelpazemiz var. Bir Bernoulli deneyelim:
b = tfd.Bernoulli(probs=0.7)
b
<tfp.distributions.Bernoulli 'Bernoulli' batch_shape=[] event_shape=[] dtype=int32>
b.sample()
<tf.Tensor: shape=(), dtype=int32, numpy=1>
b.sample(8)
<tf.Tensor: shape=(8,), dtype=int32, numpy=array([1, 0, 0, 0, 1, 0, 1, 0], dtype=int32)>
b.log_prob(1)
<tf.Tensor: shape=(), dtype=float32, numpy=-0.35667497>
b.log_prob([1, 0, 1, 0])
<tf.Tensor: shape=(4,), dtype=float32, numpy=array([-0.35667497, -1.2039728 , -0.35667497, -1.2039728 ], dtype=float32)>
Çok Değişkenli Dağılımlar
Çapraz kovaryanslı çok değişkenli bir normal oluşturacağız:
nd = tfd.MultivariateNormalDiag(loc=[0., 10.], scale_diag=[1., 4.])
nd
<tfp.distributions.MultivariateNormalDiag 'MultivariateNormalDiag' batch_shape=[] event_shape=[2] dtype=float32>
Bunu daha önce yarattığımız tek değişkenli normalle karşılaştırırsak, farklı olan ne?
tfd.Normal(loc=0., scale=1.)
<tfp.distributions.Normal 'Normal' batch_shape=[] event_shape=[] dtype=float32>
Biz tek değişkenli Normal bir olduğunu görüyoruz event_shape
ait ()
bu bir sayıl dağıtım olduğunu belirtmek. Çok değişkenli normal bir sahiptir event_shape
arasında 2
bu dağılımın temel [etkinlik alanı] (https://en.wikipedia.org/wiki/Event_ (probability_theory)) gösteren, iki boyutludur.
Örnekleme daha önce olduğu gibi çalışır:
nd.sample()
<tf.Tensor: shape=(2,), dtype=float32, numpy=array([-1.2489667, 15.025171 ], dtype=float32)>
nd.sample(5)
<tf.Tensor: shape=(5, 2), dtype=float32, numpy= array([[-1.5439653 , 8.9968405 ], [-0.38730723, 12.448896 ], [-0.8697963 , 9.330035 ], [-1.2541095 , 10.268944 ], [ 2.3475595 , 13.184147 ]], dtype=float32)>
nd.log_prob([0., 10])
<tf.Tensor: shape=(), dtype=float32, numpy=-3.2241714>
Çok değişkenli normaller genel olarak köşegen kovaryansa sahip değildir. TFD, burada kullandığımız tam kovaryans belirtimi dahil olmak üzere çok değişkenli normaller oluşturmak için birden çok yol sunar.
nd = tfd.MultivariateNormalFullCovariance(
loc = [0., 5], covariance_matrix = [[1., .7], [.7, 1.]])
data = nd.sample(200)
plt.scatter(data[:, 0], data[:, 1], color='blue', alpha=0.4)
plt.axis([-5, 5, 0, 10])
plt.title("Data set")
plt.show()
Çoklu Dağıtımlar
İlk Bernoulli dağıtımımız tek bir adil yazı turasını temsil ediyordu. Ayrıca bağımsız Bernoulli dağıtımlarının toplu oluşturabilir, kendi parametreleri ile her biri tek içinde Distribution
nesne:
b3 = tfd.Bernoulli(probs=[.3, .5, .7])
b3
<tfp.distributions.Bernoulli 'Bernoulli' batch_shape=[3] event_shape=[] dtype=int32>
Bunun ne anlama geldiği konusunda net olmak önemlidir. Yukarıdaki çağrı aynı Python içerdiği için ne üç bağımsız Bernoulli dağılımları, tanımlar Distribution
nesne. Üç dağıtım ayrı ayrı manipüle edilemez. Not nasıl batch_shape
olduğu (3,)
üç dağılımları bir toplu gösteren ve event_shape
olan ()
tek tek dağılımlar tek değişkenli etkinlik alanı vardır gösteren.
Dediğimiz Eğer sample
, hepimiz üçten örnek alın:
b3.sample()
<tf.Tensor: shape=(3,), dtype=int32, numpy=array([0, 1, 1], dtype=int32)>
b3.sample(6)
<tf.Tensor: shape=(6, 3), dtype=int32, numpy= array([[1, 0, 1], [0, 1, 1], [0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 1, 0]], dtype=int32)>
Diyoruz halinde prob
, (bu da aynı şekil semantik sahip log_prob
; Kullandığımız prob
, ancak açıklık için, bu küçük Bernoulli örneklerle log_prob
genellikle uygulamalarda tercih edilir) bir vektör olarak geçebilir ve bu değer elde edilmiştir, her para olasılığını değerlendirmek :
b3.prob([1, 1, 0])
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([0.29999998, 0.5 , 0.29999998], dtype=float32)>
API neden toplu şekil içeriyor? Semantik, tek dağılımları bir listesini oluşturarak ve onlara yineleme ile aynı hesaplamaları gerçekleştirebilir for
(bir ihtiyacım olacağını TF grafik modunda, istekli modunda en azından döngü tf.while
döngü). Bununla birlikte, (potansiyel olarak büyük) bir dizi özdeş parametreli dağılıma sahip olmak son derece yaygındır ve mümkün olduğunda vektörleştirilmiş hesaplamaların kullanılması, donanım hızlandırıcıları kullanarak hızlı hesaplamalar yapabilmek için önemli bir bileşendir.
Grupları Olaylarda Birleştirmek İçin Bağımsız Kullanma
Bir önceki bölümde, oluşturulan b3
, tek Distribution
üç sikke çevirir temsil nesnesi. Biz denilen Eğer b3.prob
bir vektör üzerine \(v\), \(i\)'inci girdi olasılığı idi \(i\)sikke inci değeri alır \(v[i]\).
Bunun yerine, aynı temel aileden bağımsız rastgele değişkenler üzerinde bir "ortak" dağılım belirtmek istediğimizi varsayalım. Bu durum, bu yeni dağıtım bölgesi, matematiksel olarak farklı bir amacı, prob
bir vektör üzerinde \(v\) paraların tüm resim vektörü ile eşleşen olasılığını temsil eden tek bir değer döndürür \(v\).
Bunu nasıl tamamlayacağız? Biz denilen bir "Üst düzey" dağıtım kullanmak Independent
bir dağılım alır ve olay şekle taşındı toplu şekli ile yeni bir dağıtım verir:
b3_joint = tfd.Independent(b3, reinterpreted_batch_ndims=1)
b3_joint
<tfp.distributions.Independent 'IndependentBernoulli' batch_shape=[] event_shape=[3] dtype=int32>
Orijinal o şekil karşılaştırın b3
:
b3
<tfp.distributions.Bernoulli 'Bernoulli' batch_shape=[3] event_shape=[] dtype=int32>
Söz olarak, bu görüyoruz Independent
: Olay şeklinde toplu şekil taşındı b3_joint
tek dağılımı (olup batch_shape = ()
, üç boyutlu bir etkinlik alanı (aşırı) event_shape = (3,)
).
Semantiği kontrol edelim:
b3_joint.prob([1, 1, 0])
<tf.Tensor: shape=(), dtype=float32, numpy=0.044999998>
Aynı sonucu elde etmek için alternatif bir yolu kullanarak hesaplama olasılıkları olacaktır b3
ve (toplayarak, günlük olasılıkları kullanılır daha olağan durumda ya) çarpılarak azalma elle yapın:
tf.reduce_prod(b3.prob([1, 1, 0]))
<tf.Tensor: shape=(), dtype=float32, numpy=0.044999994>
Indpendent
kullanıcı daha açık istenilen kavramını temsil edilmesini sağlar. Bunu kesinlikle gerekli olmasa da son derece yararlı buluyoruz.
Eğlenceli gerçekler:
-
b3.sample
veb3_joint.sample
farklı kavramsal uygulamaları, ama ayırt çıkışları vardır: bağımsız dağılımlarının bir toplu kullanılarak yığın oluşturuldu tek bir dağılım arasındaki farkIndependent
numune alırken, ihtimalleri işlem zaman değil gösterir kadar. -
MultivariateNormalDiag
trivially sayıl kullanılarak uygulanabilecekNormal
veIndependent
(aslında bu şekilde uygulanmadı, ancak bu olabilir) dağılımları.
Çok Değişkenli Dağılım Partileri
Üç tam kovaryanslı iki boyutlu çok değişkenli normalden oluşan bir toplu iş oluşturalım:
nd_batch = tfd.MultivariateNormalFullCovariance(
loc = [[0., 0.], [1., 1.], [2., 2.]],
covariance_matrix = [[[1., .1], [.1, 1.]],
[[1., .3], [.3, 1.]],
[[1., .5], [.5, 1.]]])
nd_batch
<tfp.distributions.MultivariateNormalFullCovariance 'MultivariateNormalFullCovariance' batch_shape=[3] event_shape=[2] dtype=float32>
Görüyoruz batch_shape = (3,)
ve, bu nedenle üç bağımsız değişkenli normalleri vardır event_shape = (2,)
normal her değişkenli böylece iki boyutludur. Bu örnekte, bireysel dağılımların bağımsız öğeleri yoktur.
Örnekleme çalışmaları:
nd_batch.sample(4)
<tf.Tensor: shape=(4, 3, 2), dtype=float32, numpy= array([[[ 0.7367498 , 2.730996 ], [-0.74080074, -0.36466932], [ 0.6516018 , 0.9391426 ]], [[ 1.038303 , 0.12231752], [-0.94788766, -1.204232 ], [ 4.059758 , 3.035752 ]], [[ 0.56903946, -0.06875849], [-0.35127294, 0.5311631 ], [ 3.4635801 , 4.565582 ]], [[-0.15989424, -0.25715637], [ 0.87479895, 0.97391707], [ 0.5211419 , 2.32108 ]]], dtype=float32)>
Yana batch_shape = (3,)
ve event_shape = (2,)
, şekli bir tensörünün geçmesi (3, 2)
için log_prob
:
nd_batch.log_prob([[0., 0.], [1., 1.], [2., 2.]])
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([-1.8328519, -1.7907217, -1.694036 ], dtype=float32)>
Yayıncılık, aka Bu Neden Bu Kadar Kafa karıştırıcı?
Şimdiye kadar ne yaptık dışarı Öz Çıkarma, her dağıtım bir toplu şekli vardır B
ve bir olay şekil E
. Izin BE
olay şekillerinin birleştirme be:
- Tek değişkenli skalar dağılımlar için
n
veb
,BE = ().
. - İki boyutlu değişkenli normaller için
nd
.BE = (2).
- Her ikisi için de
b3
veb3_joint
,BE = (3).
- Çok değişkenli normaller parti için
ndb
,BE = (3, 2).
Şimdiye kadar kullandığımız "değerlendirme kuralları" şunlardır:
- Herhangi bir bağımsız değişken ile örnek şekil ile tensörünün döner
BE
; bir sayısal n getirileri bir "n ile birlikte numuneBE
" tensörü. -
prob
velog_prob
şekildeki bir tensör almakBE
ve şekli bir sonuca dönmekB
.
Gerçek "değerlendirme kuralı" prob
ve log_prob
daha bir bakıma, karmaşık teklifler potansiyel güç ve hız değil, aynı zamanda karmaşıklığı ve zorluklara söyledi. Gerçek kural bağımsız değişken olduğu (aslında) olan log_prob
olmalıdır broadcastable karşı BE
; çıktıda herhangi bir "ekstra" boyut korunur.
Etkilerini inceleyelim. Tek değişkenli Normal için n
, BE = ()
, böylece log_prob
bir skalar bekler. Biz başarılı olursa log_prob
boş olmayan bir şekle sahip bir tensörünün bu çıkış parti boyutları olarak gösterilir:
n = tfd.Normal(loc=0., scale=1.)
n
<tfp.distributions.Normal 'Normal' batch_shape=[] event_shape=[] dtype=float32>
n.log_prob(0.)
<tf.Tensor: shape=(), dtype=float32, numpy=-0.9189385>
n.log_prob([0.])
<tf.Tensor: shape=(1,), dtype=float32, numpy=array([-0.9189385], dtype=float32)>
n.log_prob([[0., 1.], [-1., 2.]])
<tf.Tensor: shape=(2, 2), dtype=float32, numpy= array([[-0.9189385, -1.4189385], [-1.4189385, -2.9189386]], dtype=float32)>
İki boyutlu değişkenli normale edelim dönüş nd
(parametreler gösterim amaçlı değişti):
nd = tfd.MultivariateNormalDiag(loc=[0., 1.], scale_diag=[1., 1.])
nd
<tfp.distributions.MultivariateNormalDiag 'MultivariateNormalDiag' batch_shape=[] event_shape=[2] dtype=float32>
log_prob
"beklediğini" şeklinde bir argüman (2,)
, ancak herhangi bir argüman kabul edeceğini bu şekle karşı yayın:
nd.log_prob([0., 0.])
<tf.Tensor: shape=(), dtype=float32, numpy=-2.337877>
Ama biz "daha" örneklerde geçmesi ve tüm bunların değerlendirebilir log_prob
seferde s':
nd.log_prob([[0., 0.],
[1., 1.],
[2., 2.]])
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([-2.337877 , -2.337877 , -4.3378773], dtype=float32)>
Belki daha az çekici bir şekilde, olay boyutları üzerinden yayın yapabiliriz:
nd.log_prob([0.])
<tf.Tensor: shape=(), dtype=float32, numpy=-2.337877>
nd.log_prob([[0.], [1.], [2.]])
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([-2.337877 , -2.337877 , -4.3378773], dtype=float32)>
Bu şekilde yayın yapmak, "mümkün olduğunda yayına izin ver" tasarımımızın bir sonucudur; bu kullanım biraz tartışmalıdır ve TFP'nin gelecekteki bir sürümünde potansiyel olarak kaldırılabilir.
Şimdi üç jeton örneğine tekrar bakalım:
b3 = tfd.Bernoulli(probs=[.3, .5, .7])
Burada, her sikke kafalarını çıkageldi olasılığını temsil etmek yayın kullanarak oldukça sezgisel:
b3.prob([1])
<tf.Tensor: shape=(3,), dtype=float32, numpy=array([0.29999998, 0.5 , 0.7 ], dtype=float32)>
(Bu Karşılaştırması b3.prob([1., 1., 1.])
, biz kullanılan geri olurdu, b3
tanıtıldı.)
Şimdi bilmek istiyorum varsayalım, her sikke için, olasılık sikke başlarını gelir ve olasılık o kuyrukları çıkageldi. Şunları denemeyi hayal edebiliriz:
b3.log_prob([0, 1])
Ne yazık ki, bu, uzun ve çok okunamayan bir yığın izlemesi olan bir hata üretir. b3
sahiptir BE = (3)
biz geçmelidir böylece, b3.prob
karşı bir şey broadcastable (3,)
. [0, 1]
bir şekle sahiptir (2)
bu nedenle yayın etmez, ve hataya yol açabilir. Bunun yerine şunu söylemeliyiz:
b3.prob([[0], [1]])
<tf.Tensor: shape=(2, 3), dtype=float32, numpy= array([[0.7, 0.5, 0.3], [0.3, 0.5, 0.7]], dtype=float32)>
Niye ya? [[0], [1]]
şekle sahiptir (2, 1)
bu şekil karşı yayın böylece, (3)
bir yayın şekil yapmak için (2, 3)
.
Yayın oldukça güçlüdür: kullanılan bellek miktarında büyüklük sırasına göre azalmaya izin verdiği ve genellikle kullanıcı kodunu kısalttığı durumlar vardır. Bununla birlikte, programlamak zor olabilir. Eğer ararsanız log_prob
ve bir hata alıyorum, yayına bir başarısızlık neredeyse her zaman bir sorundur.
daha uzağa gitmek
Bu derste (umarız) basit bir giriş sağladık. Daha ileri gitmek için birkaç işaret:
-
event_shape
,batch_shape
vesample_shape
keyfi rütbe olabilir (bu eğitimde onlar da skaler veya rütbe 1 her zaman). Bu, gücü arttırır, ancak özellikle yayın söz konusu olduğunda yine programlama zorluklarına yol açabilir. Şekil manipülasyon içine ek bir derin dalış için bkz anlama TensorFlow Dağılımları Şekilleri . - TFP olarak bilinen güçlü soyutlama içerir
Bijectors
ile bağlantılı olarak,TransformedDistribution
, kolayca mevcut dağılımlarının tersinir dönüşümler yeni dağılımları oluşturmak için esnek, kompozisyon bir şekilde elde edilir. Bu yakında bir öğretici yazmaya çalışıyorum, ama bu arada, kontrol edeceğiz belgeleri