def PlotCurvesConstrained(self, constrained): # plots sums of data curves up to each order we're interested in, subject to some # constraint if constrained: trunc_gp_sym = gm.TruncationGP(kernel = self.kernel, ref=1, ratio = self.ratio, \ disp = 0, df = np.inf, scale = 1, optimizer = None) # fits GP given constraints trunc_gp_sym.fit(self.X[::10], self.yn_constrained[::10], orders = self.orders_array, \ dX = np.array([[0], [1]]), dy = np.array([0, 0])) fig, axes = plt.subplots( math.ceil(self.n_orders / 2), 2, sharex = True, \ sharey = True, figsize = (5, 8) ) for i, n in enumerate(self.orders_array): # Again, only consider the truncation errors for this plot _, std_sym = trunc_gp_sym.predict(self.X, order = n, return_std = True, \ kind = 'trunc') for j in range(i, self.n_orders): ax = axes.ravel()[j] ax.plot(self.x, self.yn_constrained[:, i], zorder=i - 5, c=self.colors[i]) ax.fill_between(self.x, self.yn_constrained[:, i] + 2 * std_sym, \ self.yn_constrained[:, i] - 2 * std_sym, zorder = i-5, \ facecolor = self.light_colors[i], edgecolor = self.colors[i], \ lw = edgewidth) ax = axes.ravel()[i] ax.axhline(0, 0, 1, ls='--', lw=0.5, c=softblack, zorder=0) ax.set_xticks([]) ax.set_yticks([]) fig.tight_layout(h_pad=0.3, w_pad=0.3) else: return 0
def PlotPointwiseFit(self, mask, expensive=True, constrained=False): # plots sums of data curves up to each order we're interested in. If the system is # inexpensive, we plot the full sum for each x-value; if the system is expensive, we # plot the full sum of the curves when fit a subset of x-values # By setting disp=0 and df=inf, no updating of hyperparameters occurs # The priors become Dirac delta functions at mu=center and cbar=scale # But this assumption could be relaxed, if desired trunc_gp = gm.TruncationGP(kernel = self.kernel, ref = self.ref, ratio = self.ratio, \ disp = 0, df = np.inf, scale = 1, optimizer = None) # Still only fit on a subset of all data to update mu and cbar! # We must beware of numerical issues of using data that are "too close" trunc_gp.fit(self.X[mask], self.data[mask], orders=self.orders_array) fig, axes = plt.subplots(math.ceil(self.n_orders / 2), 2, sharex = True, sharey = True, \ figsize = (5, 8)) for i, n in enumerate(self.orders_array): if expensive: # Only get the uncertainty due to truncation (kind='trunc') pred_exp, std_trunc_exp = trunc_gp.predict(self.X, order = n, \ return_std = True) for j in range(i, self.n_orders): ax = axes.ravel()[j] ax.plot(self.x, pred_exp, zorder=i - 5, c=self.colors[i]) ax.plot(self.x[mask], self.data[mask, i], ls = '', c = self.colors[i], \ marker = 'o', zorder = i-5) ax.fill_between(self.x, pred_exp + 2 * std_trunc_exp, \ pred_exp - 2 * std_trunc_exp, zorder = i-5, \ facecolor = self.light_colors[i], edgecolor = self.colors[i], \ lw = edgewidth) ax = axes.ravel()[i] ax.set_xticks([]) ax.set_yticks([]) ax.set_ylim(-15, 37) else: # Only get the uncertainty due to truncation (kind='trunc') _, std_trunc = trunc_gp.predict(self.X, order=n, return_std=True, kind='trunc') for j in range(i, self.n_orders): ax = axes.ravel()[j] ax.plot(self.x, self.data[:, i], zorder=i - 5, c=self.colors[i]) ax.fill_between(self.x, self.data[:, i] + 2 * std_trunc, \ self.data[:, i] - 2 * std_trunc, zorder = i-5, \ facecolor = self.light_colors[i], edgecolor = self.colors[i], \ lw = edgewidth) ax = axes.ravel()[i] ax.set_xticks([]) ax.set_yticks([]) ax.set_ylim(-15, 37) fig.tight_layout(h_pad=0.3, w_pad=0.3)
def PlotCredibleIntervals(self): # plots credible intervals ("weather plot") for each order we're interested in try: # kernel for fit self.kernel_fit = RBF(length_scale = self.ls) + \ WhiteKernel(noise_level = self.nugget, noise_level_bounds = 'fixed') # truncation GP self.gp_trunc = gm.TruncationGP(kernel = self.kernel_fit, ref = self.ref, \ ratio = self.ratio, center = self.center, disp = self.disp, \ df = self.df, scale = self.scale) self.gp_trunc.fit(self.X[self.x_train_mask], y = self.data[self.x_train_mask], \ orders = self.orders_array) # extracts truncation error for each x-value self.norm_trunc_cov = self.gp_trunc.cov(self.X[self.x_valid_mask], start=0, end=0) self.norm_residuals = (self.data_true[self.x_valid_mask, None] - \ self.data[self.x_valid_mask]) / \ (self.ratio**(self.orders_array+1) / np.sqrt(1 - self.ratio**2)) self.gr_dgn_trunc = gm.GraphicalDiagnostic(self.norm_residuals, \ mean = np.zeros(self.x[self.x_valid_mask].shape[0]), \ cov = self.norm_trunc_cov, colors = self.colors, gray = gray, \ black = softblack) fig, ax = plt.subplots(figsize=(3.4, 3.2)) # plots the curves for i, n in enumerate(self.orders_array): norm_residuals_alt = self.data_true[self.x_valid_mask] - \ self.data[self.x_valid_mask][:,i] norm_trunc_cov_alt = self.gp_trunc.cov( self.X[self.x_valid_mask], start=n + 1) gr_dgn_trunc_alt = gm.GraphicalDiagnostic( norm_residuals_alt, mean = np.zeros(self.x[self.x_valid_mask].shape[0]), \ cov = norm_trunc_cov_alt, colors = [self.colors[i]], gray = gray, black = softblack) gr_dgn_trunc_alt.credible_interval( np.linspace(1e-5, 1, 100), band_perc=[0.68, 0.95], ax=ax, title=None, xlabel=r'Credible Interval ($100\alpha\%$)', ylabel=r'Empirical Coverage ($\%$)') ax.set_xticks([0, 0.2, 0.4, 0.6, 0.8, 1]) ax.set_xticklabels([0, 20, 40, 60, 80, 100]) ax.set_yticks([0, 0.2, 0.4, 0.6, 0.8, 1]) ax.set_yticklabels([0, 20, 40, 60, 80, 100]) fig.tight_layout() except: print( "The credible intervals could not be calculated at one or more orders." )
def PlotPosteriorPDF(self, posteriorgrid): # plots the posterior PDF for the ratio and correlation length of the fit GP try: # kernel for fit self.kernel_fit = RBF(length_scale = self.ls) + \ WhiteKernel(noise_level = self.nugget, noise_level_bounds = 'fixed') # fits the GP at the mask self.gp_trunc = gm.TruncationGP(kernel = self.kernel_fit, ref = self.ref, \ ratio = self.ratio, center = self.center, disp = self.disp, \ df = self.df, scale = self.scale) self.gp_trunc.fit(self.X[self.x_train_mask], y = self.data[self.x_train_mask], \ orders = self.orders_array) # reads the posterior grid points to the class self.posteriorgrid = posteriorgrid self.ls_vals = self.posteriorgrid.x_vals self.ratio_vals = self.posteriorgrid.y_vals # Compute the log likelihood for values on this grid. self.ls_ratio_loglike = np.array([[ self.gp_trunc.log_marginal_likelihood(theta = [ls_,], ratio = ratio_val) \ for ls_ in np.log(self.ls_vals)] for ratio_val in self.ratio_vals]) # Makes sure that the values don't get too big or too small self.ls_ratio_like = np.exp(self.ls_ratio_loglike - np.max(self.ls_ratio_loglike)) # Now compute the marginal distributions self.ratio_like = np.trapz(self.ls_ratio_like, x=self.ls_vals, axis=-1) self.ls_like = np.trapz(self.ls_ratio_like, x=self.ratio_vals, axis=0) # Normalize them self.ratio_like /= np.trapz(self.ratio_like, x=self.ratio_vals, axis=0) self.ls_like /= np.trapz(self.ls_like, x=self.ls_vals, axis=0) with plt.rc_context({ "text.usetex": True, "text.latex.preview": True }): # with plt.rc_context({"text.usetex": True}): cmap_name = 'Blues' cmap = mpl.cm.get_cmap(cmap_name) # Setup axes fig, ax_joint, ax_marg_x, ax_marg_y = joint_plot(ratio=5, height=3.4) # Plot contour ax_joint.contour(self.ls_vals, self.ratio_vals, self.ls_ratio_like, levels=[ np.exp(-0.5 * r**2) for r in np.arange(9, 0, -0.5) ] + [0.999], cmap=cmap_name, vmin=-0.05, vmax=0.8, zorder=1) # Now plot the marginal distributions ax_marg_y.plot(self.ratio_like, self.ratio_vals, c=cmap(0.8), lw=1) ax_marg_y.fill_betweenx(self.ratio_vals, np.zeros_like(self.ratio_like), self.ratio_like, facecolor=cmap(0.2), lw=1) ax_marg_x.plot(self.ls_vals, self.ls_like, c=cmap(0.8), lw=1) ax_marg_x.fill_between(self.ls_vals, np.zeros_like(self.ls_vals), self.ls_like, facecolor=cmap(0.2), lw=1) # Formatting ax_joint.set_xlabel(r'$\ell$') ax_joint.set_ylabel(r'$Q$') ax_joint.axvline(self.ls, 0, 1, c=gray, lw=1, zorder=0) ax_joint.axhline(self.ratio, 0, 1, c=gray, lw=1, zorder=0) ax_joint.margins(x=0, y=0.) ax_joint.set_xlim(0.05, 0.35) ax_joint.set_xticks([0.1, 0.2, 0.3]) ax_joint.set_xticks([0.15, 0.25], minor=True) ax_joint.set_yticks([0.4, 0.5, 0.6]) ax_joint.set_yticks([0.35, 0.45, 0.55, 0.65], minor=True) ax_marg_x.set_ylim(bottom=0) ax_marg_y.set_xlim(left=0) ax_joint.text(0.95, 0.95, r'pr$(\ell, Q \,|\, \vec{\mathbf{y}}_k)$', ha='right', \ va='top', transform = ax_joint.transAxes, bbox = text_bbox) plt.show() except: print( "The posterior probability distribution could not be calculated." )
def PlotTruncations(self): # plots the data summed to each order we're interested in try: # kernel for fit self.kernel_fit = RBF(length_scale = self.ls) + \ WhiteKernel(noise_level = self.nugget, noise_level_bounds = 'fixed') # fits truncation GP to data given a mask self.gp_trunc = gm.TruncationGP(kernel = self.kernel_fit, ref = self.ref, \ ratio = self.ratio, center = self.center, disp = self.disp, \ df = self.df, scale = self.scale) self.gp_trunc.fit(self.X[self.x_train_mask], y = self.data[self.x_train_mask], \ orders = self.orders_array) # extracts truncation error for each x-value self.norm_trunc_cov = self.gp_trunc.cov(self.X[self.x_valid_mask], start=0, end=0) self.norm_residuals = (self.data_true[self.x_valid_mask, None] - \ self.data[self.x_valid_mask]) / \ (self.ratio**(self.orders_array+1) / np.sqrt(1 - self.ratio**2)) self.gr_dgn_trunc = gm.GraphicalDiagnostic(self.norm_residuals, \ mean = np.zeros(self.x[self.x_valid_mask].shape[0]), \ cov = self.norm_trunc_cov, colors = self.colors, gray = gray, \ black = softblack) fig, axes = plt.subplots(math.ceil(self.n_orders / 2), 2, sharex = True, sharey = True, \ figsize = (3.9, 3.2)) # plots curves with error for i, n in enumerate(self.orders_array): _, std_trunc = self.gp_trunc.predict(self.X, order = n, return_std = True, \ kind = 'trunc') for j in range(i, self.n_orders): ax = axes.ravel()[j] ax.plot(self.x, self.data[:, i], zorder=i - 5, c=self.colors[i]) ax.fill_between(self.x, self.data[:, i] + 2 * std_trunc, \ self.data[:, i] - 2 * std_trunc, zorder = i-5, \ facecolor = self.light_colors[i], edgecolor = self.colors[i], \ lw = edgewidth) ax = axes.ravel()[i] ax.plot(self.x, self.data_true, color=softblack, lw=1, ls='--') ax.set_xticks([0.25, 0.5, 0.75]) ax.set_xticks(self.x[self.x_valid_mask], minor=True) ax.set_xticklabels([0.25, 0.5, 0.75]) ax.set_yticks([0, 10, 20]) ax.set_yticks([-10, 0, 10, 20, 30]) ax.set_ylim(-15, 37) axes[1, 0].set_xlabel(r'$x$') axes[1, 1].set_xlabel(r'$x$') fig.tight_layout(h_pad=0.3, w_pad=0.3) except: print( "The truncation error curves could not be calculated at one or more orders." )