by Fedor Iskhakov, ANU
Description: Gaussian quadrature. Monte Carlo integration.
Most integrals can not be evaluated analytically
Goal: definite integral $ \int_a^b f(x) dx $
Idea: Approximate the function with low order polynomial, then integrate approximation
Preform Newton-Cotes on a grid separately on each interval
Note that the points are placed exogenously
General formula
$$ \int_a^b f(x) dx = \sum_{i=1}^n \omega_i f(x_i) $$Note that the points are placed endogenously
Suppose that $ \{\phi_k(x)\}_{k=1,2,\dots} $ is family of polynomials of degree $ k $ orthogonal with respect to the weighting function $ w(x) $
Then
Want to integrate $ f(x) $ on $ [a,b] $, no weighting function.
where $ y_i $ are Gauss-Chebyshev nodes over $ [-1,1] $
Much more complication, simple methods are subject to curse of dimensionality
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
plt.rcParams['figure.figsize'] = [12, 8]
def mc_int_cube(f,ndims=1,N=1000):
'''Computes the integral of function f on a hypercube of dimension ndims
using Monte Carlo integration with N uniformly distributed points
Assume function f uses axis=0 for inputs, and can be vectorized in other axis
Return: value and standard error
'''
# generate uniform numbers on the hypercube
x = np.random.random(ndims*N).reshape(ndims,N) # uniform random numbers in a matrix
y = f(x) # function value
Q = y.mean() # sample average
seQ = y.std()/np.sqrt(N) # standard error of sample average
return Q,seQ
# pi example from video 33 as two-dim integral
# Approximate pi using 2-d Monte Carlo integration
N=1000 # Number of Monte carlo Samples
g = lambda x: (x[0,:]**2 + x[1,:]**2)<1 # indicator function to inegrate
q,se = mc_int_cube(g,ndims=2,N=N)
pi_hat = 4*q
se_pi_hat = 4*se
print('Number of Monte Carlo samples : ', N);
print('Estimate (pi_hat) : ', pi_hat.round(10));
print('Standard error (pi_hat) : ', se_pi_hat.round(10));
print('Approximation error (pi_hat-pi) : ', (pi_hat-np.pi).round(10))
Number of Monte Carlo samples : 1000 Estimate (pi_hat) : 3.088 Standard error (pi_hat) : 0.0530684087 Approximation error (pi_hat-pi) : -0.0535926536
Consistency: Law of large numbers ensures that the sample average converge to the mean
$$ \lim _{{N\to \infty }}Q_f(N) =\lim _{{N\to \infty }}{\frac{1}{N}}\sum _{{i=1}}^{N}\frac{f(x_i)}{p(x_i)} =E\left[\frac{f(\tilde{x})}{p(\tilde{x})}\right] = \int_{\Omega} f(x)\,dx = I_f $$Assymptotic Normality: By the central limit theorem we have
$$ \sqrt{N}\left(Q_f(N)-I_f \right)\ \xrightarrow {d} \ N\left(0,\sigma ^{2}\right), \; \sigma^2= \operatorname{Var}\left[\frac{f(\tilde{x})}{p(\tilde{x})}\right] $$The standard error of $ Q_f(N) $ is then given by $ \sigma_{Q_f(N)}=\sigma \big/ \sqrt{N} $
Given our estimate $ Q_f(N) $ of $ I_f $, we can obtain an unbiased estimate of $ \sigma^2= \operatorname{Var}\left[\frac{f(\tilde{x})}{p(\tilde{x})}\right] $
$$ {\hat{\sigma}}^2_N=\frac{1}{N-1}\sum _{i=1}^N \left(\frac{f(x_i)}{p(x_i)}-Q_f(N)\right)^2 $$and the estimate of the standard error of $ Q_f(N) $
$$ {\hat{\sigma}}_{Q_f(N)}={\hat{\sigma}}_N \big/ \sqrt{N} $$The standard error of $ Q_f(N) $:
Decreases with the standard parametric rate $ \sqrt{N} $
# distribution of Monte Carlo integral
N=1000; # number of Monte Carlo samples used to simulate the integral
S=1000; # number of runs to generate the distribution of estimates
qs = np.empty(S,dtype=float)
ses = np.empty(S,dtype=float)
for i in range(S):
q,se = mc_int_cube(g,ndims=2,N=N)
qs[i] = 4*q
ses[i] = 4*se
plt.hist(qs,bins=50,range=(np.pi-.2, np.pi+.2))
plt.title('Distribution of %d Monte Carlo approximations of pi'%S)
print('True value (pi) :', np.round(np.pi,10))
print('Average estimate across all runs :', qs.mean().round(10))
print('Mean bias :', np.mean(qs-np.pi).round(10))
print('Average std err across all runs :', ses.mean().round(10))
print('Std dev of bias :', np.std(qs-np.pi).round(10))
True value (pi) : 3.1415926536 Average estimate across all runs : 3.13976 Mean bias : -0.0018326536 Average std err across all runs : 0.0519299844 Std dev of bias : 0.0533409261