TensorFlow.org पर देखें | Google Colab में चलाएं | GitHub पर स्रोत देखें | नोटबुक डाउनलोड करें |
विभिन्न अनुमान (VI) एक अनुकूलन समस्या के रूप में अनुमानित बायेसियन अनुमान लगाता है और एक 'सरोगेट' पश्च वितरण की तलाश करता है जो वास्तविक पश्च के साथ केएल विचलन को कम करता है। ग्रेडिएंट-आधारित VI अक्सर MCMC विधियों की तुलना में तेज़ होता है, मॉडल मापदंडों के अनुकूलन के साथ स्वाभाविक रूप से रचना करता है, और मॉडल साक्ष्य पर एक निचला बाउंड प्रदान करता है जिसका उपयोग सीधे मॉडल तुलना, अभिसरण निदान और कंपोज़ेबल अनुमान के लिए किया जा सकता है।
TensorFlow Probability तेज़, लचीले और स्केलेबल VI के लिए उपकरण प्रदान करती है जो स्वाभाविक रूप से TFP स्टैक में फिट होते हैं। ये उपकरण रैखिक परिवर्तनों या प्रवाह को सामान्य करने से प्रेरित सहसंयोजक संरचनाओं के साथ सरोगेट पोस्टीरियर के निर्माण को सक्षम करते हैं।
छठी बायेसियन अनुमान लगाने के लिए इस्तेमाल किया जा सकता विश्वसनीय अंतराल प्रतिगमन मॉडल के मापदंडों रुचि का एक परिणाम पर विभिन्न उपचार या मनाया सुविधाओं के प्रभाव का अनुमान लगाने के लिए। प्रेक्षित डेटा पर वातानुकूलित पैरामीटर के पश्च वितरण के अनुसार और पैरामीटर के पूर्व वितरण पर एक धारणा दी गई है, विश्वसनीय अंतराल एक निश्चित संभावना के साथ एक गैर-अवलोकन पैरामीटर के मूल्यों को बाध्य करता है।
इस Colab में, हम छठी उपयोग करने के लिए कैसे एक बायेसियन के घरों में मापा जाता रेडॉन के स्तर के लिए प्रतिगमन मॉडल रैखिक मापदंडों के लिए विश्वसनीय अंतराल प्राप्त करने के लिए प्रदर्शित (का उपयोग कर Gelman एट अल के (2007) रेडॉन डाटासेट। ; देखने के समान उदाहरण स्टेन में)। हम यह दिखाना कैसे TFP JointDistribution
रों के साथ गठबंधन bijectors
निर्माण करने के लिए और अर्थपूर्ण किराए की कूल्हे के दो प्रकार फिट:
- एक मानक सामान्य वितरण एक ब्लॉक मैट्रिक्स द्वारा परिवर्तित। मैट्रिक्स पश्च के कुछ घटकों के बीच स्वतंत्रता और दूसरों के बीच निर्भरता को प्रतिबिंबित कर सकता है, एक माध्य-क्षेत्र या पूर्ण-सहसंयोजक पश्च की धारणा को आराम देता है।
- एक अधिक जटिल, उच्च क्षमता autoregressive प्रवाह उलटा ।
सरोगेट पोस्टरियर को प्रशिक्षित किया जाता है और एक माध्य-क्षेत्र सरोगेट पोस्टीरियर बेसलाइन के परिणामों के साथ-साथ हैमिल्टनियन मोंटे कार्लो से जमीनी सच्चाई के नमूनों की तुलना की जाती है।
बायेसियन भिन्नात्मक अनुमान का अवलोकन
मान लीजिए कि हमें निम्नलिखित उत्पादक प्रक्रिया है, जहां है \(\theta\) यादृच्छिक मानकों का प्रतिनिधित्व करता है, \(\omega\) नियतात्मक मानकों का प्रतिनिधित्व करता है, और \(x_i\) विशेषताएं हैं और \(y_i\) लक्ष्य मूल्यों के लिए कर रहे हैं \(i=1,\ldots,n\) डेटा बिंदुओं मनाया: \ संरेखित शुरू { } &\थीटा \sim r(\Theta) && \text{(पूर्व)}\ &\text{के लिए } i = 1 \ldots n: \nonumber \ &\quad y_i \sim p(Y_i|x_i, \theta \ ओमेगा) && \ text {(संभावना)} \ अंत {align}
VI की विशेषता तब होती है: $\newcommand{\E}{\operatorname{\mathbb{E} } } \newcommand{\K}{\operatorname{\mathbb{K} } } \newcommand{\defeq}{\overset {\tiny\text{def} }{=} } \DeclareMathOperator*{\argmin}{arg\,min}$
\ लॉग पी ({y_i} सर्वव्यापी ^ n | {x_i} सर्वव्यापी ^ n, \ ओमेगा) - \ {align} शुरू और \ defeq - \ लॉग इन करें \ पूर्णांक \ textrm {घ} \ थीटा \ r (\ थीटा) \ prod_i^np(y_i|x_i,\theta, \omega) && \text{(रियली हार्ड इंटीग्रल)} \ &= -\log \int \textrm{d}\theta\, q(\theta) \frac{1 }{q(\theta)} r(\theta) \prod_i^np(y_i|x_i,\theta, \omega) && \text{(1 से गुणा करें)}\ &\le - \int \textrm{d} \ थीटा \, क्ष (\ थीटा) \ लॉग \ frac {आर (\ थीटा) \ prod_i ^ एनपी (y_i | x मैं, \ थीटा, \ ओमेगा)} {क्ष (\ थीटा)} && \ text {(जेन्सेन की असमानता )} \ और \ defeq \ ई {क्ष (\ थीटा)} [- \ लॉग पी (y_i | x_i, \ थीटा, \ ओमेगा)] \ कश्मीर [q (\ थीटा), आर (\ थीटा)] \ & \ defeq \text{expected negative log likelihood"} +
\ text {kl regularizer"} \ अंत {align}
(तकनीकी तौर पर हम यह सोचते हैं कर रहे हैं \(q\) है बिल्कुल निरंतर के संबंध में \(r\)। यह भी देखें, जेन्सेन की असमानता ।)
चूंकि बाउंड सभी q के लिए है, यह स्पष्ट रूप से इसके लिए सबसे कड़ा है:
\[q^*,w^* = \argmin_{q \in \mathcal{Q},\omega\in\mathbb{R}^d} \left\{ \sum_i^n\E_{q(\Theta)}\left[ -\log p(y_i|x_i,\Theta, \omega) \right] + \K[q(\Theta), r(\Theta)] \right\}\]
शब्दावली के संबंध में, हम कहते हैं
- \(q^*\) "सरोगेट पीछे," और,
- \(\mathcal{Q}\) "सरोगेट परिवार।"
\(\omega^*\) छठी नुकसान पर नियतात्मक मापदंडों का अधिकतम संभावना मूल्यों का प्रतिनिधित्व करता है। देखें इस सर्वेक्षण परिवर्तन संबंधी अनुमान बारे में अधिक जानकारी के लिए।
उदाहरण: रेडॉन माप पर बायेसियन पदानुक्रमित रैखिक प्रतिगमन
रेडॉन एक रेडियोधर्मी गैस है जो जमीन के संपर्क बिंदुओं के माध्यम से घरों में प्रवेश करती है। यह एक कार्सिनोजेन है जो धूम्रपान न करने वालों में फेफड़ों के कैंसर का प्राथमिक कारण है। रेडॉन का स्तर घर-घर में बहुत भिन्न होता है।
EPA ने 80,000 घरों में रेडॉन के स्तर का अध्ययन किया। दो महत्वपूर्ण भविष्यवक्ता हैं:
- जिस तल पर माप लिया गया था (तहखाने में रेडॉन अधिक)
- काउंटी यूरेनियम स्तर (रेडॉन स्तरों के साथ सकारात्मक सहसंबंध)
काउंटी के आधार पर वर्गीकृत घरों में रेडॉन के स्तर की भविष्यवाणी बायेसियन श्रेणीबद्ध मॉडलिंग में एक क्लासिक समस्या, द्वारा शुरू की है Gelman और हिल (2006) । हम घरों में रेडॉन माप की भविष्यवाणी करने के लिए एक पदानुक्रमित रैखिक मॉडल का निर्माण करेंगे, जिसमें पदानुक्रम काउंटी द्वारा घरों का समूह है। हम मिनेसोटा में घरों के रेडॉन स्तर पर स्थान (काउंटी) के प्रभाव के लिए विश्वसनीय अंतराल में रुचि रखते हैं। इस प्रभाव को अलग करने के लिए, मॉडल में फर्श और यूरेनियम स्तर के प्रभावों को भी शामिल किया गया है। इसके अतिरिक्त, हम उस माध्य तल के अनुरूप एक प्रासंगिक प्रभाव शामिल करेंगे जिस पर काउंटी द्वारा माप लिया गया था, ताकि यदि उस मंजिल की काउंटियों में भिन्नता हो, जिस पर माप लिया गया था, तो यह काउंटी प्रभाव के लिए जिम्मेदार नहीं है।
pip3 install -q tf-nightly tfp-nightly
import matplotlib.pyplot as plt
import numpy as np
import seaborn as sns
import tensorflow as tf
import tensorflow_datasets as tfds
import tensorflow_probability as tfp
import warnings
tfd = tfp.distributions
tfb = tfp.bijectors
plt.rcParams['figure.facecolor'] = '1.'
# Load the Radon dataset from `tensorflow_datasets` and filter to data from
# Minnesota.
dataset = tfds.as_numpy(
tfds.load('radon', split='train').filter(
lambda x: x['features']['state'] == 'MN').batch(10**9))
# Dependent variable: Radon measurements by house.
dataset = next(iter(dataset))
radon_measurement = dataset['activity'].astype(np.float32)
radon_measurement[radon_measurement <= 0.] = 0.1
log_radon = np.log(radon_measurement)
# Measured uranium concentrations in surrounding soil.
uranium_measurement = dataset['features']['Uppm'].astype(np.float32)
log_uranium = np.log(uranium_measurement)
# County indicator.
county_strings = dataset['features']['county'].astype('U13')
unique_counties, county = np.unique(county_strings, return_inverse=True)
county = county.astype(np.int32)
num_counties = unique_counties.size
# Floor on which the measurement was taken.
floor_of_house = dataset['features']['floor'].astype(np.int32)
# Average floor by county (contextual effect).
county_mean_floor = []
for i in range(num_counties):
county_mean_floor.append(floor_of_house[county == i].mean())
county_mean_floor = np.array(county_mean_floor, dtype=log_radon.dtype)
floor_by_county = county_mean_floor[county]
प्रतिगमन मॉडल निम्नानुसार निर्दिष्ट है:
\(\newcommand{\Normal}{\operatorname{\sf Normal} }\)शुरू \ {align} और \ text {uranium_weight} \ सिम \ सामान्य (0, 1) \ & \ text {county_floor_weight} \ सिम \ सामान्य (0, 1) \ & \ text {के लिए} j = 1 \ ldots \text{num_counties}:\ &\quad \text{county_effect}_j \sim \Normal (0, \sigma_c)\ &\text{for } i = 1\ldots n:\ &\quad \mu_i = ( \ और \ ट्रैक्टर \ ट्रैक्टर \ text {पूर्वाग्रह} \ और \ ट्रैक्टर \ ट्रैक्टर + \ text {काउंटी प्रभाव} {\ text {काउंटी} सर्वव्यापी} \ और \ ट्रैक्टर \ ट्रैक्टर + \ text {log_uranium} सर्वव्यापी \ बार \ text {uranium_weight } \ और \ ट्रैक्टर \ ट्रैक्टर + \ text {floor_of_house} सर्वव्यापी \ बार \ text {floor_weight} \ और \ ट्रैक्टर \ ट्रैक्टर + \ text {floor_by काउंटी} {\ text {काउंटी} सर्वव्यापी} \ बार \ text {county_floor_weight}) \ & \ ट्रैक्टर \ text {} log_radon सर्वव्यापी \ सिम \ सामान्य (\ mu_i, \ sigma_y) \ अंत {align} जिसमें \(i\) अनुक्रमित टिप्पणियों और \(\text{county}_i\) है काउंटी जिसमें \(i\)वें अवलोकन था लिया।
हम भौगोलिक विविधता को पकड़ने के लिए काउंटी-स्तरीय यादृच्छिक प्रभाव का उपयोग करते हैं। मापदंडों uranium_weight
और county_floor_weight
संभवतया मॉडलिंग कर रहे हैं, और floor_weight
और निरंतर bias
नियतात्मक हैं। ये मॉडलिंग विकल्प काफी हद तक मनमाने हैं, और उचित जटिलता के संभाव्य मॉडल पर VI को प्रदर्शित करने के उद्देश्य से बनाए गए हैं। TFP में ठीक किया गया और यादृच्छिक प्रभाव, राडोण डाटासेट उपयोग करने के साथ बहुस्तरीय मॉडलिंग का एक और अधिक गहन विचार विमर्श के लिए, देखें बहुस्तरीय मॉडलिंग प्राइमर और परिवर्तन संबंधी निष्कर्ष का उपयोग फिटिंग सामान्यीकृत रैखिक मिश्रित प्रभाव मॉडल ।
# Create variables for fixed effects.
floor_weight = tf.Variable(0.)
bias = tf.Variable(0.)
# Variables for scale parameters.
log_radon_scale = tfp.util.TransformedVariable(1., tfb.Exp())
county_effect_scale = tfp.util.TransformedVariable(1., tfb.Exp())
# Define the probabilistic graphical model as a JointDistribution.
@tfd.JointDistributionCoroutineAutoBatched
def model():
uranium_weight = yield tfd.Normal(0., scale=1., name='uranium_weight')
county_floor_weight = yield tfd.Normal(
0., scale=1., name='county_floor_weight')
county_effect = yield tfd.Sample(
tfd.Normal(0., scale=county_effect_scale),
sample_shape=[num_counties], name='county_effect')
yield tfd.Normal(
loc=(log_uranium * uranium_weight + floor_of_house* floor_weight
+ floor_by_county * county_floor_weight
+ tf.gather(county_effect, county, axis=-1)
+ bias),
scale=log_radon_scale[..., tf.newaxis],
name='log_radon')
# Pin the observed `log_radon` values to model the un-normalized posterior.
target_model = model.experimental_pin(log_radon=log_radon)
अभिव्यंजक सरोगेट पोस्टीरियर
आगे हम दो अलग-अलग प्रकार के सरोगेट पोस्टरियर के साथ VI का उपयोग करके यादृच्छिक प्रभावों के पश्च वितरण का अनुमान लगाते हैं:
- एक अवरुद्ध बहुभिन्नरूपी सामान्य वितरण, एक ब्लॉकवाइज मैट्रिक्स परिवर्तन द्वारा प्रेरित सहप्रसरण संरचना के साथ।
- एक मल्टीवेरिएट मानक सामान्य बंटन एक से बदल उलटा autoregressive प्रवाह है, जो तब विभाजित है और पीछे के समर्थन से मिलान करने के पुनर्गठन किया गया है।
बहुभिन्नरूपी सामान्य सरोगेट पोस्टीरियर
इस सरोगेट पोस्टीरियर को बनाने के लिए, एक प्रशिक्षित लीनियर ऑपरेटर का उपयोग पोस्टीरियर के घटकों के बीच सहसंबंध को प्रेरित करने के लिए किया जाता है।
# Determine the `event_shape` of the posterior, and calculate the size of each
# `event_shape` component. These determine the sizes of the components of the
# underlying standard Normal distribution, and the dimensions of the blocks in
# the blockwise matrix transformation.
event_shape = target_model.event_shape_tensor()
flat_event_shape = tf.nest.flatten(event_shape)
flat_event_size = tf.nest.map_structure(tf.reduce_prod, flat_event_shape)
# The `event_space_bijector` maps unconstrained values (in R^n) to the support
# of the prior -- we'll need this at the end to constrain Multivariate Normal
# samples to the prior's support.
event_space_bijector = target_model.experimental_default_event_space_bijector()
एक का निर्माण JointDistribution
वेक्टर-मान मानक सामान्य घटकों के साथ, इसी से पहले घटकों द्वारा निर्धारित आकारों के साथ। घटकों को वेक्टर-मूल्यवान होना चाहिए ताकि उन्हें रैखिक ऑपरेटर द्वारा परिवर्तित किया जा सके।
base_standard_dist = tfd.JointDistributionSequential(
[tfd.Sample(tfd.Normal(0., 1.), s) for s in flat_event_size])
एक प्रशिक्षित ब्लॉकवाइज निचले-त्रिकोणीय रैखिक ऑपरेटर का निर्माण करें। हम इसे (प्रशिक्षित) ब्लॉकवाइज मैट्रिक्स परिवर्तन को लागू करने और पश्च के सहसंबंध संरचना को प्रेरित करने के लिए मानक सामान्य वितरण पर लागू करेंगे।
Blockwise रैखिक ऑपरेटर के भीतर, एक trainable पूर्ण मैट्रिक्स ब्लॉक, पीछे के दो घटकों के बीच पूर्ण सहप्रसरण का प्रतिनिधित्व करता है, जबकि शून्य (या के एक ब्लॉक None
) स्वतंत्रता व्यक्त करता है। विकर्ण पर ब्लॉक या तो निचले-त्रिकोणीय या विकर्ण मैट्रिक्स होते हैं, जिससे कि संपूर्ण ब्लॉक संरचना निचले-त्रिकोणीय मैट्रिक्स का प्रतिनिधित्व करती है।
इस द्विभाजक को आधार वितरण पर लागू करने से माध्य 0 और (चॉल्स्की-फैक्टेड) सहप्रसरण के साथ एक बहुभिन्नरूपी सामान्य वितरण होता है जो निचले-त्रिकोणीय ब्लॉक मैट्रिक्स के बराबर होता है।
operators = (
(tf.linalg.LinearOperatorDiag,), # Variance of uranium weight (scalar).
(tf.linalg.LinearOperatorFullMatrix, # Covariance between uranium and floor-by-county weights.
tf.linalg.LinearOperatorDiag), # Variance of floor-by-county weight (scalar).
(None, # Independence between uranium weight and county effects.
None, # Independence between floor-by-county and county effects.
tf.linalg.LinearOperatorDiag) # Independence among the 85 county effects.
)
block_tril_linop = (
tfp.experimental.vi.util.build_trainable_linear_operator_block(
operators, flat_event_size))
scale_bijector = tfb.ScaleMatvecLinearOperatorBlock(block_tril_linop)
मानक सामान्य वितरण के लिए रेखीय ऑपरेटर लागू करने के बाद, एक बहुखण्डीय लागू Shift
मतलब अशून्य मान लेने के लिए अनुमति देने के लिए bijector।
loc_bijector = tfb.JointMap(
tf.nest.map_structure(
lambda s: tfb.Shift(
tf.Variable(tf.random.uniform(
(s,), minval=-2., maxval=2., dtype=tf.float32))),
flat_event_size))
परिणामी बहुभिन्नरूपी सामान्य वितरण, पैमाने और स्थान द्विभाजक के साथ मानक सामान्य वितरण को बदलकर प्राप्त किया जाता है, इसे पूर्व से मेल खाने के लिए फिर से आकार और पुनर्गठित किया जाना चाहिए, और अंत में पूर्व के समर्थन के लिए विवश होना चाहिए।
# Reshape each component to match the prior, using a nested structure of
# `Reshape` bijectors wrapped in `JointMap` to form a multipart bijector.
reshape_bijector = tfb.JointMap(
tf.nest.map_structure(tfb.Reshape, flat_event_shape))
# Restructure the flat list of components to match the prior's structure
unflatten_bijector = tfb.Restructure(
tf.nest.pack_sequence_as(
event_shape, range(len(flat_event_shape))))
अब, यह सब एक साथ रखें - प्रशिक्षित बायजेक्टरों को एक साथ श्रृंखलाबद्ध करें और उन्हें सरोगेट पोस्टीरियर के निर्माण के लिए आधार मानक सामान्य वितरण पर लागू करें।
surrogate_posterior = tfd.TransformedDistribution(
base_standard_dist,
bijector = tfb.Chain( # Note that the chained bijectors are applied in reverse order
[
event_space_bijector, # constrain the surrogate to the support of the prior
unflatten_bijector, # pack the reshaped components into the `event_shape` structure of the posterior
reshape_bijector, # reshape the vector-valued components to match the shapes of the posterior components
loc_bijector, # allow for nonzero mean
scale_bijector # apply the block matrix transformation to the standard Normal distribution
]))
बहुभिन्नरूपी सामान्य सरोगेट पोस्टीरियर को प्रशिक्षित करें।
optimizer = tf.optimizers.Adam(learning_rate=1e-2)
mvn_loss = tfp.vi.fit_surrogate_posterior(
target_model.unnormalized_log_prob,
surrogate_posterior,
optimizer=optimizer,
num_steps=10**4,
sample_size=16,
jit_compile=True)
mvn_samples = surrogate_posterior.sample(1000)
mvn_final_elbo = tf.reduce_mean(
target_model.unnormalized_log_prob(*mvn_samples)
- surrogate_posterior.log_prob(mvn_samples))
print('Multivariate Normal surrogate posterior ELBO: {}'.format(mvn_final_elbo))
plt.plot(mvn_loss)
plt.xlabel('Training step')
_ = plt.ylabel('Loss value')
Multivariate Normal surrogate posterior ELBO: -1065.705322265625
चूंकि प्रशिक्षित सरोगेट पोस्टीरियर एक TFP वितरण है, इसलिए हम इससे नमूने ले सकते हैं और मापदंडों के लिए पश्च विश्वसनीय अंतराल उत्पन्न करने के लिए उन्हें संसाधित कर सकते हैं।
बॉक्स और मूंछ भूखंडों नीचे 50% और 95% दिखाने विश्वसनीय अंतराल काउंटी काउंटी द्वारा मिट्टी यूरेनियम माप पर दो सबसे बड़े काउंटियों और प्रतिगमन वजन के प्रभाव और मतलब मंजिल के लिए। काउंटी प्रभावों के लिए पश्च विश्वसनीय अंतराल इंगित करते हैं कि सेंट लुइस काउंटी में स्थान अन्य चर के लिए लेखांकन के बाद निचले रेडॉन स्तरों से जुड़ा हुआ है, और यह कि हेनेपिन काउंटी में स्थान का प्रभाव तटस्थ के करीब है।
प्रतिगमन भार पर पश्च विश्वसनीय अंतराल दर्शाते हैं कि मृदा यूरेनियम का उच्च स्तर उच्च रेडॉन स्तरों से जुड़ा हुआ है, और काउंटियों जहां उच्च मंजिलों पर माप लिया गया था (संभवतः क्योंकि घर में एक तहखाना नहीं था) में रेडॉन का उच्च स्तर होता है, जो मिट्टी के गुणों और निर्मित संरचनाओं के प्रकार पर उनके प्रभाव से संबंधित हो सकते हैं।
मंजिल का (नियतात्मक) गुणांक ऋणात्मक है, यह दर्शाता है कि निचली मंजिलों में अपेक्षा के अनुरूप उच्च रेडॉन स्तर हैं।
st_louis_co = 69 # Index of St. Louis, the county with the most observations.
hennepin_co = 25 # Index of Hennepin, with the second-most observations.
def pack_samples(samples):
return {'County effect (St. Louis)': samples.county_effect[..., st_louis_co],
'County effect (Hennepin)': samples.county_effect[..., hennepin_co],
'Uranium weight': samples.uranium_weight,
'Floor-by-county weight': samples.county_floor_weight}
def plot_boxplot(posterior_samples):
fig, axes = plt.subplots(1, 4, figsize=(16, 4))
# Invert the results dict for easier plotting.
k = list(posterior_samples.values())[0].keys()
plot_results = {
v: {p: posterior_samples[p][v] for p in posterior_samples} for v in k}
for i, (var, var_results) in enumerate(plot_results.items()):
sns.boxplot(data=list(var_results.values()), ax=axes[i],
width=0.18*len(var_results), whis=(2.5, 97.5))
# axes[i].boxplot(list(var_results.values()), whis=(2.5, 97.5))
axes[i].title.set_text(var)
fs = 10 if len(var_results) < 4 else 8
axes[i].set_xticklabels(list(var_results.keys()), fontsize=fs)
results = {'Multivariate Normal': pack_samples(mvn_samples)}
print('Bias is: {:.2f}'.format(bias.numpy()))
print('Floor fixed effect is: {:.2f}'.format(floor_weight.numpy()))
plot_boxplot(results)
Bias is: 1.40 Floor fixed effect is: -0.72
उलटा ऑटोरेग्रेसिव फ्लो सरोगेट पोस्टीरियर
उलटा ऑटोरेग्रेसिव फ्लो (आईएएफ) प्रवाह को सामान्य कर रहे हैं जो वितरण के घटकों के बीच जटिल, गैर-रेखीय निर्भरता को पकड़ने के लिए तंत्रिका नेटवर्क का उपयोग करते हैं। आगे हम यह देखने के लिए एक IAF सरोगेट पोस्टीरियर का निर्माण करते हैं कि क्या यह उच्च क्षमता वाला, अधिक लचीला मॉडल विवश बहुभिन्नरूपी सामान्य से बेहतर प्रदर्शन करता है।
# Build a standard Normal with a vector `event_shape`, with length equal to the
# total number of degrees of freedom in the posterior.
base_distribution = tfd.Sample(
tfd.Normal(0., 1.), sample_shape=[tf.reduce_sum(flat_event_size)])
# Apply an IAF to the base distribution.
num_iafs = 2
iaf_bijectors = [
tfb.Invert(tfb.MaskedAutoregressiveFlow(
shift_and_log_scale_fn=tfb.AutoregressiveNetwork(
params=2, hidden_units=[256, 256], activation='relu')))
for _ in range(num_iafs)
]
# Split the base distribution's `event_shape` into components that are equal
# in size to the prior's components.
split = tfb.Split(flat_event_size)
# Chain these bijectors and apply them to the standard Normal base distribution
# to build the surrogate posterior. `event_space_bijector`,
# `unflatten_bijector`, and `reshape_bijector` are the same as in the
# multivariate Normal surrogate posterior.
iaf_surrogate_posterior = tfd.TransformedDistribution(
base_distribution,
bijector=tfb.Chain([
event_space_bijector, # constrain the surrogate to the support of the prior
unflatten_bijector, # pack the reshaped components into the `event_shape` structure of the prior
reshape_bijector, # reshape the vector-valued components to match the shapes of the prior components
split] + # Split the samples into components of the same size as the prior components
iaf_bijectors # Apply a flow model to the Tensor-valued standard Normal distribution
))
IAF सरोगेट पोस्टीरियर को प्रशिक्षित करें।
optimizer=tf.optimizers.Adam(learning_rate=1e-2)
iaf_loss = tfp.vi.fit_surrogate_posterior(
target_model.unnormalized_log_prob,
iaf_surrogate_posterior,
optimizer=optimizer,
num_steps=10**4,
sample_size=4,
jit_compile=True)
iaf_samples = iaf_surrogate_posterior.sample(1000)
iaf_final_elbo = tf.reduce_mean(
target_model.unnormalized_log_prob(*iaf_samples)
- iaf_surrogate_posterior.log_prob(iaf_samples))
print('IAF surrogate posterior ELBO: {}'.format(iaf_final_elbo))
plt.plot(iaf_loss)
plt.xlabel('Training step')
_ = plt.ylabel('Loss value')
IAF surrogate posterior ELBO: -1065.3663330078125
IAF सरोगेट पोस्टीरियर के लिए विश्वसनीय अंतराल विवश बहुभिन्नरूपी सामान्य के समान दिखाई देते हैं।
results['IAF'] = pack_samples(iaf_samples)
plot_boxplot(results)
बेसलाइन: मीन-फील्ड सरोगेट पोस्टीरियर
VI सरोगेट पोस्टरियर को अक्सर माध्य-क्षेत्र (स्वतंत्र) सामान्य वितरण माना जाता है, प्रशिक्षण योग्य साधनों और भिन्नताओं के साथ, जो कि एक विशेषण परिवर्तन के साथ पूर्व के समर्थन के लिए विवश हैं। हम बहुभिन्नरूपी सामान्य सरोगेट पोस्टीरियर के समान सामान्य सूत्र का उपयोग करते हुए, दो और अभिव्यंजक सरोगेट पोस्टीरियर के अलावा एक माध्य-क्षेत्र सरोगेट पोस्टीरियर को परिभाषित करते हैं।
# A block-diagonal linear operator, in which each block is a diagonal operator,
# transforms the standard Normal base distribution to produce a mean-field
# surrogate posterior.
operators = (tf.linalg.LinearOperatorDiag,
tf.linalg.LinearOperatorDiag,
tf.linalg.LinearOperatorDiag)
block_diag_linop = (
tfp.experimental.vi.util.build_trainable_linear_operator_block(
operators, flat_event_size))
mean_field_scale = tfb.ScaleMatvecLinearOperatorBlock(block_diag_linop)
mean_field_loc = tfb.JointMap(
tf.nest.map_structure(
lambda s: tfb.Shift(
tf.Variable(tf.random.uniform(
(s,), minval=-2., maxval=2., dtype=tf.float32))),
flat_event_size))
mean_field_surrogate_posterior = tfd.TransformedDistribution(
base_standard_dist,
bijector = tfb.Chain( # Note that the chained bijectors are applied in reverse order
[
event_space_bijector, # constrain the surrogate to the support of the prior
unflatten_bijector, # pack the reshaped components into the `event_shape` structure of the posterior
reshape_bijector, # reshape the vector-valued components to match the shapes of the posterior components
mean_field_loc, # allow for nonzero mean
mean_field_scale # apply the block matrix transformation to the standard Normal distribution
]))
optimizer=tf.optimizers.Adam(learning_rate=1e-2)
mean_field_loss = tfp.vi.fit_surrogate_posterior(
target_model.unnormalized_log_prob,
mean_field_surrogate_posterior,
optimizer=optimizer,
num_steps=10**4,
sample_size=16,
jit_compile=True)
mean_field_samples = mean_field_surrogate_posterior.sample(1000)
mean_field_final_elbo = tf.reduce_mean(
target_model.unnormalized_log_prob(*mean_field_samples)
- mean_field_surrogate_posterior.log_prob(mean_field_samples))
print('Mean-field surrogate posterior ELBO: {}'.format(mean_field_final_elbo))
plt.plot(mean_field_loss)
plt.xlabel('Training step')
_ = plt.ylabel('Loss value')
Mean-field surrogate posterior ELBO: -1065.7652587890625
इस मामले में, माध्य क्षेत्र सरोगेट पोस्टीरियर अधिक अभिव्यंजक सरोगेट पोस्टीरियर के समान परिणाम देता है, यह दर्शाता है कि यह सरल मॉडल अनुमान कार्य के लिए पर्याप्त हो सकता है।
results['Mean Field'] = pack_samples(mean_field_samples)
plot_boxplot(results)
जमीनी सच्चाई: हैमिल्टनियन मोंटे कार्लो (HMC)
सरोगेट पोस्टीरियर के परिणामों की तुलना के लिए, हम वास्तविक पोस्टीरियर से "जमीनी सच्चाई" नमूने उत्पन्न करने के लिए एचएमसी का उपयोग करते हैं।
num_chains = 8
num_leapfrog_steps = 3
step_size = 0.4
num_steps=20000
flat_event_shape = tf.nest.flatten(target_model.event_shape)
enum_components = list(range(len(flat_event_shape)))
bijector = tfb.Restructure(
enum_components,
tf.nest.pack_sequence_as(target_model.event_shape, enum_components))(
target_model.experimental_default_event_space_bijector())
current_state = bijector(
tf.nest.map_structure(
lambda e: tf.zeros([num_chains] + list(e), dtype=tf.float32),
target_model.event_shape))
hmc = tfp.mcmc.HamiltonianMonteCarlo(
target_log_prob_fn=target_model.unnormalized_log_prob,
num_leapfrog_steps=num_leapfrog_steps,
step_size=[tf.fill(s.shape, step_size) for s in current_state])
hmc = tfp.mcmc.TransformedTransitionKernel(
hmc, bijector)
hmc = tfp.mcmc.DualAveragingStepSizeAdaptation(
hmc,
num_adaptation_steps=int(num_steps // 2 * 0.8),
target_accept_prob=0.9)
chain, is_accepted = tf.function(
lambda current_state: tfp.mcmc.sample_chain(
current_state=current_state,
kernel=hmc,
num_results=num_steps // 2,
num_burnin_steps=num_steps // 2,
trace_fn=lambda _, pkr:
(pkr.inner_results.inner_results.is_accepted),
),
autograph=False,
jit_compile=True)(current_state)
accept_rate = tf.reduce_mean(tf.cast(is_accepted, tf.float32))
ess = tf.nest.map_structure(
lambda c: tfp.mcmc.effective_sample_size(
c,
cross_chain_dims=1,
filter_beyond_positive_pairs=True),
chain)
r_hat = tf.nest.map_structure(tfp.mcmc.potential_scale_reduction, chain)
hmc_samples = pack_samples(
tf.nest.pack_sequence_as(target_model.event_shape, chain))
print('Acceptance rate is {}'.format(accept_rate))
Acceptance rate is 0.9008625149726868
एचएमसी परिणामों की विवेक-जांच के लिए प्लॉट नमूना निशान।
def plot_traces(var_name, samples):
fig, axes = plt.subplots(1, 2, figsize=(14, 1.5), sharex='col', sharey='col')
for chain in range(num_chains):
s = samples.numpy()[:, chain]
axes[0].plot(s, alpha=0.7)
sns.kdeplot(s, ax=axes[1], shade=False)
axes[0].title.set_text("'{}' trace".format(var_name))
axes[1].title.set_text("'{}' distribution".format(var_name))
axes[0].set_xlabel('Iteration')
warnings.filterwarnings('ignore')
for var, var_samples in hmc_samples.items():
plot_traces(var, var_samples)
सभी तीन सरोगेट पोस्टरियर ने विश्वसनीय अंतराल का उत्पादन किया जो नेत्रहीन एचएमसी नमूनों के समान हैं, हालांकि कभी-कभी ईएलबीओ नुकसान के प्रभाव के कारण कम-छितरी हुई है, जैसा कि VI में आम है।
results['HMC'] = hmc_samples
plot_boxplot(results)
अतिरिक्त परिणाम
प्लॉटिंग कार्य
plt.rcParams.update({'axes.titlesize': 'medium', 'xtick.labelsize': 'medium'})
def plot_loss_and_elbo():
fig, axes = plt.subplots(1, 2, figsize=(12, 4))
axes[0].scatter([0, 1, 2],
[mvn_final_elbo.numpy(),
iaf_final_elbo.numpy(),
mean_field_final_elbo.numpy()])
axes[0].set_xticks(ticks=[0, 1, 2])
axes[0].set_xticklabels(labels=[
'Multivariate Normal', 'IAF', 'Mean Field'])
axes[0].title.set_text('Evidence Lower Bound (ELBO)')
axes[1].plot(mvn_loss, label='Multivariate Normal')
axes[1].plot(iaf_loss, label='IAF')
axes[1].plot(mean_field_loss, label='Mean Field')
axes[1].set_ylim([1000, 4000])
axes[1].set_xlabel('Training step')
axes[1].set_ylabel('Loss (negative ELBO)')
axes[1].title.set_text('Loss')
plt.legend()
plt.show()
plt.rcParams.update({'axes.titlesize': 'medium', 'xtick.labelsize': 'small'})
def plot_kdes(num_chains=8):
fig, axes = plt.subplots(2, 2, figsize=(12, 8))
k = list(results.values())[0].keys()
plot_results = {
v: {p: results[p][v] for p in results} for v in k}
for i, (var, var_results) in enumerate(plot_results.items()):
ax = axes[i % 2, i // 2]
for posterior, posterior_results in var_results.items():
if posterior == 'HMC':
label = posterior
for chain in range(num_chains):
sns.kdeplot(
posterior_results[:, chain],
ax=ax, shade=False, color='k', linestyle=':', label=label)
label=None
else:
sns.kdeplot(
posterior_results, ax=ax, shade=False, label=posterior)
ax.title.set_text('{}'.format(var))
ax.legend()
एविडेंस लोअर बाउंड (ELBO)
IAF, अब तक का सबसे बड़ा और सबसे लचीला सरोगेट पोस्टीरियर, उच्चतम एविडेंस लोअर बाउंड (ELBO) में परिवर्तित हो जाता है।
plot_loss_and_elbo()
पश्च नमूने
एचएमसी जमीनी सच्चाई के नमूनों (बॉक्स भूखंडों में दिखाए गए नमूनों का एक अलग दृश्य) की तुलना में प्रत्येक सरोगेट पोस्टीरियर के नमूने।
plot_kdes()
निष्कर्ष
इस Colab में, हमने संयुक्त वितरण और मल्टीपार्ट बायजेक्टर का उपयोग करके VI सरोगेट पोस्टीरियर का निर्माण किया, और रेडॉन डेटासेट पर एक रिग्रेशन मॉडल में वज़न के लिए विश्वसनीय अंतराल का अनुमान लगाने के लिए उन्हें फिट किया। इस सरल मॉडल के लिए, अधिक अभिव्यंजक सरोगेट पोस्टीरियर ने माध्य-क्षेत्र सरोगेट पोस्टीरियर के समान प्रदर्शन किया। हालाँकि, हमने जिन उपकरणों का प्रदर्शन किया, उनका उपयोग अधिक जटिल मॉडल के लिए उपयुक्त लचीले सरोगेट पोस्टरियर की एक विस्तृत श्रृंखला के निर्माण के लिए किया जा सकता है।