In [1]:
#%load /Users/gully/astroML/bombcat/DFM_GP_example.py
Scipy.optimize functionsOriginals available at: https://github.com/dfm/gp-tutorial & https://speakerdeck.com/dfm/an-astronomers-introduction-to-gaussian-processes
In [41]:
%pylab inline
# Auto imports np and plt
In [42]:
from matplotlib import rcParams
#rcParams["savefig.dpi"] = 150
import emcee # http://dan.iel.fm/emcee
import triangle # https://github.com/dfm/triangle.py
import numpy as np
import matplotlib.pyplot as plt
from astroML.plotting import hist
from astroML.stats.random import bivariate_normal
from matplotlib.patches import Ellipse
import timeit
#from IPython.display import display, Math, Latex
In [43]:
import seaborn as sns
sns.set_context("notebook", font_scale=1.5, rc={"lines.linewidth": 2.5})
cmap = sns.cubehelix_palette(light=1, as_cmap=True)
sns.palplot(sns.cubehelix_palette(light=1))
In [44]:
from etalon import *
np.random.seed(123456)
# Introduce the True data
x = np.arange(1200.0, 2501.0, 10.0)
N = len(x)
d_True = 4120.0
f_True = 0.045
T_DSP = T_gap_Si(x, 0.0)
y_True = T_gap_Si_withFF(x, d_True, f_True)/T_DSP
#Introduce some noise with both measurement uncertainties
# and non-trivial correlated errors.
yerr = 0.0001 + 0.0003*np.random.rand(N)
yerr_hom = 0.0002*np.ones(N)
hom_cov = np.diag(yerr_hom ** 2)
iid_cov = np.diag(yerr ** 2)
a_True = 0.002
s_True = 12.0
true_cov = a_True**2.0 * np.exp(-0.5 * (x[:, None]-x[None, :])**2 / s_True**2) + iid_cov
y = np.random.multivariate_normal(y_True, true_cov)
#y = np.random.multivariate_normal(y, iid_cov)
In [45]:
plt.errorbar(x, y, yerr=yerr, fmt=".k", capsize=0)
plt.plot(x, y_True, "-r", lw=2, alpha=0.3)
plt.xlabel('$\lambda$');
plt.ylabel('$T_{gap}$');
plt.title('Synthetic Si Transmission');
plt.ylim(0.9, 1.01);
In [45]:
The following example follows from the Enthought Training on Demand videos.
https://training.enthought.com/course/SCIPY/lecture/SCIPY_CURVE_FITTING_CALLABLES
In [15]:
n1 = sellmeier_Si(x)
In [21]:
# Arguments are parameters, y, x
def f_err(p, y, x, n):
res = y - T_gap_Si_withFF_fast(x, p[0], p[1], n)
return res
In [22]:
import scipy.optimize as optimize
In [27]:
guess = [d_True*0.995, f_True*1.01]
In [28]:
c, ret_val = optimize.leastsq(f_err, guess, args=(y, x, n1))
In [29]:
ret_val
Out[29]:
In [30]:
c
Out[30]:
In [68]:
p_est, err_est = optimize.curve_fit(T_gap_Si_withFF, x, y, p0=(4115.0, 0.048))
In [69]:
p_est
Out[69]:
Result is a failure
The off-diagonal terms are characterized by parameters $a$ and $s$.
The term $a$ controls the strength of the interaction. The term $s$ controls the range of correlation.
First we define a natural log likelihood function. You hand it a $d$, a $f$, an $a$, and an $s$ and it gives you the likelihood of the data: $\ln{p}=\ln{p(y|d,f,a,s)}$
Note: x is not passed to this function. The way Python works, x, y, and iid_cov are searched for in the local namespace, then global namespace.
In [46]:
n1 = sellmeier_Si(x)
In [47]:
def lnlike(d, f):
C = iid_cov
sgn, logdet = np.linalg.slogdet(C)
if sgn <= 0:
return -np.inf
r = y - T_gap_Si_withFF_fast(x, d, f, n1)/T_DSP
return -0.5 * (np.dot(r, np.linalg.solve(C, r)) + logdet)
In [48]:
# Apply a uniform prior over some range.
# Shape params are uniform in log space
def lnprior(d, f):
if not (3900 < d < 4300 and 0 < f < 1):
return -np.inf
return 0.0
In [49]:
def lnprob(p):
lp = lnprior(*p)
if not np.isfinite(lp):
return -np.inf
return lp + lnlike(*p)
In [50]:
ndim, nwalkers = 2, 32
p0 = np.array([d_True, f_True]) # Excellent guess
pos = [p0 + 1.0e-3*p0 * np.random.randn(ndim) for i in range(nwalkers)]
sampler = emcee.EnsembleSampler(nwalkers, ndim, lnprob)
In [57]:
# This is the burn-in
pos, lp, state = sampler.run_mcmc(pos, 300)
In [58]:
sampler.reset()
pos, lp, state = sampler.run_mcmc(pos, 1000)
chain = sampler.chain
In [59]:
fig, axes = plt.subplots(2, 1, figsize=(5, 6), sharex=True)
fig.subplots_adjust(left=0.1, bottom=0.1, right=0.96, top=0.98,
wspace=0.0, hspace=0.05)
[a.plot(np.arange(chain.shape[1]), chain[:, :, i].T, "k", alpha=0.5)
for i, a in enumerate(axes)]
[a.set_ylabel("${0}$".format(l)) for a, l in zip(axes, ["d", "f"])]
axes[-1].set_xlim(0, chain.shape[1])
axes[-1].set_xlabel("iteration");
In [60]:
samples = sampler.flatchain
samples_lin = copy(samples)
In [61]:
fig = triangle.corner(samples_lin,
labels=map("${0}$".format, ["d", "f"]),
truths=[d_True, f_True])
In [71]:
for d, f in samples[np.random.randint(len(samples), size=100)]:
plt.plot(x, T_gap_Si_withFF_fast(x, d, f, n1)/T_DSP, color="b", alpha=0.03)
plt.errorbar(x, y, yerr=yerr, fmt=".k", capsize=0)
plt.plot(x, y_True, "--r", lw=2, alpha=1.0)
plt.xlabel('$\lambda$');
plt.ylabel('$T_{gap}$');
plt.title('100 samples from posterior');
plt.ylim(0.9, 1.01);
In [64]:
d_mcmc, f_mcmc= map(lambda v: (v[1], v[2]-v[1], v[1]-v[0]),
zip(*np.percentile(samples_lin, [16, 50, 84],
axis=0)))
In [65]:
d_mcmc, f_mcmc
Out[65]:
In [67]:
for d, f in samples_lin[np.random.randint(len(samples), size=30)]:
#plt.plot(x, T_gap_Si_withFF_fast(x, d, f, n1)/T_DSP, color="b", alpha=0.03)
C = iid_cov
fit = T_gap_Si_withFF_fast(x, d, f, n1)/T_DSP
vec = np.random.multivariate_normal(fit, C)
plt.plot(x, vec, color="g", alpha=0.03)
plt.errorbar(x, y, fmt=".k")
plt.xlabel('$\lambda$');
plt.ylabel('$T_{gap}$');
plt.title('Synthetic Si Transmission');
plt.ylim(0.9, 1.01);
In [ ]: