[英]Passing tensorflow-probability distributions as bijector parameters
我想創建一個 TransformedDistribution ,其變換雙射器(雙射器鏈)的一些組件參數化為分布本身,目的是每次通過雙射器轉換一些張量時都有不同的結果(因為雙射器的參數將是每次也采樣)。
讓我們舉一個非常簡單的例子來說明我所說的(沒有鏈):
import tensorflow as tf
import tensorflow_probability as tfp
tfd = tfp.distributions
tfb = tfp.bijectors
base_distribution = tfd.Normal(loc=0, scale=1.5)
x = base_distribution.sample(10) # Sample 10 times, to get fixed values
# Define the distribution for the parameter of the bijector
scale_distribution = tfd.Uniform(low=2/3-0.5, high=2/3+0.5)
# This is how I wish it was, but fails
bijector = tfb.Scale(scale=scale_distribution)
# ValueError: TypeError: object of type 'Uniform' has no len()
詳細說明這個例子:
transformed_dist = tfd.TransformedDistribution(
base_distribution,
bijector)
transformed_dist.sample() # get one sample of the original distribution,
# scaled with some scale factor drawn from the
# uniform distribution.
我知道有一種方法可以使用 JointDistribution 構建分層分布模型,這讓我可以使用一個(或多個)分布作為另一個分布的參數,然后從聯合分布中采樣。
但我還沒有找到隨機參數化雙射器的等效方法。 一種“有效”但有點麻煩的方法是:
# Works, but the sample is generated and becomes fixed when defining the bijector
bijector = tfb.Scale(scale=tf.random.uniform(minval=2/3-0.5, maxval=2/3+0.5,))
transformed_dist = tfd.TransformedDistribution(
base_distribution,
bijector)
transformed_dist.sample() # Now the distribution will always sample from
# a Normal what is Scaled by a deterministic
# parameter, that was randomly generated at
# definition time.
正如我在代碼中解釋的那樣,每次我希望參數不同時,我都需要重新運行整個代碼塊。
我想這樣做的原因是我想以這樣一種方式自動生成樣本,即某個旋轉是隨機的,即每次采樣時得到不同的分布。
注意:我正在使用 tensorflow >2.1 和急切執行。
我仍然認為 JointDistribution 是 go 的方式,做類似的事情
joint = tfd.JointDistributionSequential([
tfd.Uniform(...),
lambda unif: tfb.MyBijector(param=unif)(tfd.Normal(0., 1.))
])
饋入雙射器參數。
但是,您也可以使用tfp.util.DeferredTensor
拼湊一些東西。 這是一個 object,可以在任何地方使用張量,但其值取自給定 function 的執行。 例如
rand_dt = tfp.util.DeferredTensor(
pretransformed_input=1., # value doesn't matter here
transform_fn=lambda _: tf.random.uniform(minval=1., maxval=2.)
)
td = tfb.Scale(scale=rand_dt)(tfd.Normal(0., 1.))
for i in range(5):
print(td.sample())
# will print a sample with a different random scale on each call
這是一個 colab,對上述示例進行了略微修改,以說明發生了什么: https://colab.research.google.com/drive/1akjX6a1W-RJoUjsy0hVOrrRAQiBIYjY-
!
更新:
經過進一步思考,我實際上應該對第二種模式非常謹慎。 不幸的是,很難保證 DeferredTensor 的單個張量化值將被一致地使用——即使在單個 Distribution 方法調用的上下文中——所以做任何有副作用的事情都可能是危險的。 例如:
rand_dt = tfp.util.DeferredTensor(
pretransformed_input=1., # value doesn't matter here
transform_fn=lambda _: tf.random.uniform(minval=1., maxval=2.)
)
td = tfb.Scale(scale=rand_dt)(tfd.Normal(0., 1.))
sample = td.sample() # sample from TD with some random scale
print(td.log_prob(sample)) # new scale; wrong log_prob!
一種解決方法是使用無狀態 TF 采樣 API,直接或通過將列表值或張量值種子傳遞給 TFP(請參閱 此處有關無狀態采樣語義的更多信息),並顯式管理種子。 不過,這可能會使上面的示例更加丑陋且難以使用(您可能需要有一個浮動的變量作為種子輸入並在每次需要新樣本時被assign
)
您最好的選擇可能是使用 JointDistribution 方法!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.