depths = 2e-5 + (2e-4 - 2e-5) * np.random.rand(N) durations = 0.3 + 0.2 * np.random.rand(N) datasets = [] for t0, depth, duration in zip(t0s, depths, durations): ds = deepcopy(dataset) model = np.ones_like(ds.time) model[(ds.time < t0+duration)*(ds.time > t0-duration)] *= 1.0 - depth ds.flux *= model datasets.append(ds) [pl.plot(ds.time, ds.flux, ".") for ds in datasets] pl.savefig("data.png") # Compute the Gaussian processes on the dataset. gp = GaussianProcess([1e-3, 3.0, 10.]) gp.compute(dataset.time, dataset.ferr) # Loop over true epochs. d = 0.2 correct = [] incorrect = [] for t0, depth, duration, data in zip(t0s, depths, durations, datasets): null = gp.lnlikelihood(data.flux - 1.0) # Compute the correct model. model = np.ones_like(data.time) model[(data.time < t0+duration)*(data.time > t0-duration)] *= 1.0 - 0.0001 correct.append(gp.lnlikelihood(data.flux - model) - null) for i, t in enumerate(data.time): if np.abs(t0 - t) < 2*d:
pl.savefig("data.png") t = data.time f = data.flux d = 0.2 x = np.linspace(-6, 0, 10) y = np.linspace(-1.0, 10, 12) s2n = np.zeros((len(x), len(y))) ll = np.zeros((len(x), len(y))) delta_ll = np.zeros((len(x), len(y))) for ix, a in enumerate(x): for iy, l in enumerate(y): gp = GaussianProcess([10 ** a, 10 ** l, 1e6]) gp.compute(data.time, data.ferr) null = gp.lnlikelihood(f - 1.0) results = [] for i, t0 in enumerate(t): if np.abs(t0 - truth[2]) < 2*d: continue model = np.ones_like(f) model[(t < t0+d) * (t > t0-d)] *= 1.0 - 0.0001 results.append((t0, gp.lnlikelihood(f - model))) results = np.array(results) model = np.ones_like(f) model[(t < truth[2]+d) * (t > truth[2]-d)] *= 1.0 - 0.0001 ll_true = gp.lnlikelihood(f - model) mu, std = np.mean(results[:, 1]), np.std(results[:, 1])
class GPLightCurve(LightCurve): """ An extension to :class:`LightCurve` with a Gaussian Process likelihood function. This does various nice things like masking NaNs and Infs and normalizing the fluxes by the median. :param time: The time series in days. :param flux: The flux measurements in arbitrary units. :param ferr: The error bars on ``flux``. :param hyperpars: The parameters for the ``GaussianProcess`` kernel. :param texp: (optional) The integration time (in seconds). (default: 1626.0… Kepler long-cadence) :param K: (optional) The number of bins to use in the approximate exposure time integral. (default: 3) """ def __init__(self, time, flux, ferr, hyperpars, jitter=0.0, **kwargs): if GaussianProcess is None: raise ImportError("You need to install george to use GPs") super(GPLightCurve, self).__init__(time, flux, ferr, **kwargs) self._hyperpars = hyperpars self._gp = None self._jitter = jitter def __getstate__(self): return dict([(k, v) for k, v in self.__dict__.items() if k != "_gp"]) def __setstate__(self, d): for k, v in d.items(): setattr(self, k, v) self._gp = None @property def gp(self): if self._gp is None: self._gp = GaussianProcess(ExpSquaredKernel(*self.hyperpars)) if not self._gp.computed: std = np.sqrt(self.ferr**2 + self.jitter**2) self._gp.compute(self.time, std) return self._gp @property def jitter(self): return self._jitter @jitter.setter def jitter(self, value): self._gp = None self._jitter = value @property def hyperpars(self): return self._hyperpars @hyperpars.setter def hyperpars(self, value): self._hyperpars = value self._gp = None # Helper functions for the individual hyperparameters. @property def alpha(self): return self._hyperpars[0] @alpha.setter def alpha(self, value): h = self._hyperpars h[0] = value self.hyperpars = h @property def scale(self): return self._hyperpars[1] @scale.setter def scale(self, value): h = self._hyperpars h[1] = value self.hyperpars = h def optimize_hyperpars(self, n=None, **kwargs): if n is None: n = len(self.time) gp = GaussianProcess(self.hyperpars) flag, hyperpars = gp.optimize(self.time[:n], self.ferr[:n], self.flux[:n]-1, **kwargs) self.hyperpars = hyperpars return flag, hyperpars def lnlike(self, lc): """ Get the likelihood of this dataset given a particular :class:`Model`. :param model: The predicted light curve model evaluated at ``eval_time``. """ return self.gp.lnlikelihood(self.flux - lc) def predict(self, lc, size=None, resample=None): """ Generate a sample from the light curve probability function for a particular :class:`Model`. :param model: The predicted light curve model evaluated at ``eval_time``. """ if resample is None: mu, cov = self.gp.predict(self.flux - lc, self.time) return mu + lc t = self.time[::resample] mu, cov = self.gp.predict(self.flux - lc, t) mu += lc[::resample] return np.interp(self.time, t, mu)
# Generate some fake data. period = 0.956 x = 10 * np.sort(np.random.rand(75)) yerr = 0.1 + 0.1 * np.random.rand(len(x)) y = gp.sample_prior(x) y += 0.8 * np.cos(2 * np.pi * x / period) y += yerr * np.random.randn(len(yerr)) # Set up a periodic kernel. pk = ExpSquaredKernel(np.sqrt(0.8), 1000.0) * CosineKernel(period) kernel2 = kernel + pk gp2 = GaussianProcess(kernel2) # Condition on this data. gp2.compute(x, yerr) # Compute the log-likelihood. print("Log likelihood = {0}".format(gp2.lnlikelihood(y))) # Compute the conditional predictive distribution. t = np.linspace(0, 10, 200) f = gp2.sample_conditional(y, t, size=500) mu = np.mean(f, axis=0) std = np.std(f, axis=0) pl.errorbar(x, y, yerr=yerr, fmt=".k") pl.plot(t, mu, "k", lw=2, alpha=0.5) pl.plot(t, mu+std, "k", alpha=0.5) pl.plot(t, mu-std, "k", alpha=0.5) pl.savefig("periodic.png")