Monte Carlo Quadrature

This tutorial describes how to use Monte Carlo sampling to compute the expectations of the output of a model f(z):RDR parameterized by a set of variables z=[z1,,zD] with joint density given by ρ(z):RdR. Specifically, our goal is to approximate the integral

Q=Γf(z)ρ(z)dz

using Monte Carlo quadrature applied to an approximation fα of the function f, e.g. a representing a finite element approximation to the solution of a set of governing equations, where α is contols the accuracy of the approximation.

Monte Carlo quadrature approximates the integral

Qα=Γfα(z)ρ(z)dzQ

by drawing N random samples ZN of z from ρ and evaluating the function at each of these samples to obtain the data pairs {(z(n),fα(n))}n=1N, where fα(n)=fα(z(n)) and computing

Qα(ZN)=N1n=1Nfα(n)

This estimate of the mean,is itself a random quantity, which we call an estimator, because its value depends on the ZN realizations of the inputs ZN used to compute Qα(ZN). Specifically, using two different sets ZN will produce to different values.

To demonstrate this phenomenon, we will estimate the mean of a simple algebraic function f0 which belongs to an ensemble of models

f0(z)=A0(z15cosθ0+z25sinθ0),f1(z)=A1(z13cosθ1+z23sinθ1)+s1,f2(z)=A2(z1cosθ2+z2sinθ2)+s2

where z1,z2U(1,1) and all A and θ coefficients are real. We choose to set A=11, A1=7 and A2=3 to obtain unitary variance for each model. The parameters s1,s2 control the bias between the models. Here we set s1=1/10,s2=1/5. Similarly we can change the correlation between the models in a systematic way (by varying θ1. We will levarage this later in the tutorial.

First setup the example

import numpy as np
import matplotlib.pyplot as plt

from pyapprox.benchmarks import setup_benchmark

np.random.seed(1)
shifts = [.1, .2]
benchmark = setup_benchmark(
    "tunable_model_ensemble", theta1=np.pi/2*.95, shifts=shifts)

Now define a function that computes MC estimates of the mean using different sample sets ZN and plots the distribution the MC estimator Qα(ZN), computed from 1000 different sets, and the exact value of the mean Qα

def plot_estimator_histrogram(nsamples, model_id, ax):
    ntrials = 1000
    np.random.seed(1)
    means = np.empty((ntrials))
    model = benchmark.funs[model_id]
    for ii in range(ntrials):
        samples = benchmark.variable.rvs(nsamples)
        values = model(samples)
        means[ii] = values.mean()
    im = ax.hist(means, bins=ntrials//100, density=True, alpha=0.3,
                 label=r'$Q_{%d}(\mathcal{Z}_{%d})$' % (model_id, nsamples))[2]
    ax.axvline(x=benchmark.fun.get_means()[model_id], alpha=1,
               label=r'$Q_{%d}$' % model_id, c=im[0].get_facecolor())

Now lets plot the historgram of the MC estimator Q0(ZN) using N=100 samples

nsamples = int(1e2)
model_id = 0
ax = plt.subplots(1, 1, figsize=(8, 6))[1]
plot_estimator_histrogram(nsamples, model_id, ax)
_ = ax.legend()
plot monte carlo

The variability of the MC estimator as we change ZN decreases as we increase N. To see this, plot the estimator historgram using N=1000 samples

model_id = 0
ax = plt.subplots(1, 1, figsize=(8, 6))[1]
nsamples = int(1e2)
plot_estimator_histrogram(nsamples, model_id, ax)
nsamples = int(1e3)
plot_estimator_histrogram(nsamples, model_id, ax)
_ = ax.legend()
plot monte carlo

Regardless of the value of N the estimator Q0(ZN) is an unbiased estimate of Q0, that is

E[Q0(ZN)]Q0=0

Unfortunately, if the computational cost of evaluating a model is high, then one may not be able to make N large using that model. Consequently, one will not be able to trust the MC estimate of the mean much because any one realization of the estimator, computed using a single sample set, may obtain a value that is very far from the truth. So often a cheaper less accurate model is used so that N can be increased to reduce the variability of the estimator. The following compares the histograms of Q0(Z100) and Q1(Z1000) which uses the model f1 which we assume is a cheap approximation of f0

model_id = 0
ax = plt.subplots(1, 1, figsize=(8, 6))[1]
nsamples = int(1e2)
plot_estimator_histrogram(nsamples, model_id, ax)
model_id = 1
nsamples = int(1e3)
plot_estimator_histrogram(nsamples, model_id, ax)
_ = ax.legend()
plot monte carlo

However, using an approximate model means that the MC estimator is no longer unbiased. The mean of the histogram of Q1(Z1000) is no longer the mean of Q0

Letting Q denote the true mean we want to estimate, e.g. Q=Q0 in the example we have used so far, the mean squared error (MSE) is typically used to quantify the quality of a MC estimator. The MSE can be expressed as

E[(Qα(ZN)Q)2]=E[(Qα(ZN)E[Qα(ZN)]+E[Qα(ZN)]Q)2]=E[(Qα(ZN)E[Qα(ZN)])2]+E[(E[Qα(ZN)]Q)2]+E[2(Qα(ZN)E[Qα(ZN)])(E[Qα(ZN)]Q)]=V[Qα(ZN)]+(E[Qα(ZN)]Q)2=V[Qα(ZN)]+(QαQ)2

where the expectation E and variance V are taken over different realization of the sample set ZN, we used that E[(Qα(ZN)E[Qα(ZN)])]=0 so the third term on the second line is zero, and we used E[Qα(ZN)]=Qα to get the final equality.

Now using the well known result that for random variable Xn

V[n=1NXn]=n=1NV[Xn]+npCov[Xn,Xp]

and the result for a scalar a

V[aXn]=a2V[Xn]

yields

V[Qα(ZN)]=V[N1n=1Nfα(n)]=N2n=1NV[fα(n)]=N1V[fα]

where Cov[f(n),f(p)]=0,np because the samples are drawn independently.

Finally, substituting V[Qα(ZN)] into the expression for MSE yields

E[(Qα(ZN)E[Q])2]=N1V[fα]I+(QαQ)2II

From this expression we can see that the MSE can be decomposed into two terms; a so called stochastic error (I) and a deterministic bias (II). The first term is the variance of the Monte Carlo estimator which comes from using a finite number of samples. The second term is due to using an approximation of f0. These two errors should be balanced, however in the vast majority of all MC analyses a single model fα is used and the choice of α, e.g. mesh resolution, is made a priori without much concern for the balancing bias and variance.

Video

Click on the image below to view a video tutorial on Monte Carlo quadrature

../../_images/mc.png

Total running time of the script: ( 0 minutes 0.332 seconds)

Gallery generated by Sphinx-Gallery