From 12dba962f123f01795dec10bbd29a2e07940a944 Mon Sep 17 00:00:00 2001 From: mzwiessele Date: Mon, 12 Oct 2015 13:12:03 +0100 Subject: [PATCH] [kernel] plotting ard for prod and covariance plots added --- GPy/kern/src/add.py | 5 +- GPy/kern/src/kern.py | 15 ++- GPy/kern/src/prod.py | 9 +- GPy/plotting/gpy_plot/gp_plots.py | 37 +++--- GPy/plotting/gpy_plot/kernel_plots.py | 124 +++++++----------- GPy/plotting/gpy_plot/latent_plots.py | 9 +- GPy/plotting/gpy_plot/plot_util.py | 29 ++-- GPy/testing/plotting_tests.py | 11 +- .../plotting_tests/baseline/kern_cov_1d.png | Bin 0 -> 6916 bytes .../plotting_tests/baseline/kern_cov_2d.png | Bin 0 -> 27886 bytes .../plotting_tests/baseline/kern_cov_3d.png | Bin 0 -> 23854 bytes doc/source/conf.py | 5 +- setup.py | 2 +- 13 files changed, 130 insertions(+), 116 deletions(-) create mode 100644 GPy/testing/plotting_tests/baseline/kern_cov_1d.png create mode 100644 GPy/testing/plotting_tests/baseline/kern_cov_2d.png create mode 100644 GPy/testing/plotting_tests/baseline/kern_cov_3d.png diff --git a/GPy/kern/src/add.py b/GPy/kern/src/add.py index 41b4febb..9f80ac9d 100644 --- a/GPy/kern/src/add.py +++ b/GPy/kern/src/add.py @@ -254,7 +254,4 @@ class Add(CombinationKernel): i_s[k._all_dims_active] += k.input_sensitivity(summarize) return i_s else: - i_s = np.zeros((len(self.parts), self.input_dim)) - from operator import setitem - [setitem(i_s, (i, k._all_dims_active), k.input_sensitivity(summarize)) for i, k in enumerate(self.parts)] - return i_s + return super(Add, self).input_sensitivity(summarize) diff --git a/GPy/kern/src/kern.py b/GPy/kern/src/kern.py index 19e98b89..c3d98a9b 100644 --- a/GPy/kern/src/kern.py +++ b/GPy/kern/src/kern.py @@ -341,7 +341,20 @@ class CombinationKernel(Kern): otherwise put everything into an array with shape (#kernels, input_dim) in the order of appearance of the kernels in the parameterized object. """ - raise NotImplementedError("Choose the kernel you want to get the sensitivity for. You need to override the default behaviour for getting the input sensitivity to be able to get the input sensitivity. For sum kernel it is the sum of all sensitivities, TODO: product kernel? Other kernels?, also TODO: shall we return all the sensitivities here in the combination kernel? So we can combine them however we want? This could lead to just plot all the sensitivities here...") + if not summarize: + num_params = [0] + parts = [] + def sum_params(x): + if (not isinstance(x, CombinationKernel)) and isinstance(x, Kern): + num_params[0] += 1 + parts.append(x) + self.traverse(sum_params) + i_s = np.zeros((num_params[0], self.input_dim)) + from operator import setitem + [setitem(i_s, (i, k._all_dims_active), k.input_sensitivity(summarize)) for i, k in enumerate(parts)] + return i_s + else: + raise NotImplementedError("Choose the kernel you want to get the sensitivity for. You need to override the default behaviour for getting the input sensitivity to be able to get the input sensitivity. For sum kernel it is the sum of all sensitivities, TODO: product kernel? Other kernels?, also TODO: shall we return all the sensitivities here in the combination kernel? So we can combine them however we want? This could lead to just plot all the sensitivities here...") def _check_active_dims(self, X): return diff --git a/GPy/kern/src/prod.py b/GPy/kern/src/prod.py index b47e663d..68883af4 100644 --- a/GPy/kern/src/prod.py +++ b/GPy/kern/src/prod.py @@ -97,4 +97,11 @@ class Prod(CombinationKernel): target += p.gradients_X_diag(k/p.Kdiag(X),X) return target - + def input_sensitivity(self, summarize=True): + if summarize: + i_s = np.zeros((self.input_dim)) + for k in self.parts: + i_s[k._all_dims_active] *= k.input_sensitivity(summarize) + return i_s + else: + return super(Prod, self).input_sensitivity(summarize) diff --git a/GPy/plotting/gpy_plot/gp_plots.py b/GPy/plotting/gpy_plot/gp_plots.py index 2b00dfa8..da92748d 100644 --- a/GPy/plotting/gpy_plot/gp_plots.py +++ b/GPy/plotting/gpy_plot/gp_plots.py @@ -32,7 +32,7 @@ import numpy as np from . import plotting_library as pl from .plot_util import helper_for_plot_data, update_not_existing_kwargs, \ - helper_predict_with_model, get_which_data_ycols + helper_predict_with_model, get_which_data_ycols, get_x_y_var from .data_plots import _plot_data, _plot_inducing, _plot_data_error def plot_mean(self, plot_limits=None, fixed_inputs=None, @@ -66,8 +66,9 @@ def plot_mean(self, plot_limits=None, fixed_inputs=None, :param dict predict_kw: the keyword arguments for the prediction. If you want to plot a specific kernel give dict(kern=) in here """ canvas, kwargs = pl().new_canvas(projection=projection, **kwargs) - helper_data = helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resolution) - helper_prediction = helper_predict_with_model(self, helper_data[5], plot_raw, + X = get_x_y_var(self)[0] + helper_data = helper_for_plot_data(self, X, plot_limits, visible_dims, fixed_inputs, resolution) + helper_prediction = helper_predict_with_model(self, helper_data[2], plot_raw, apply_link, None, get_which_data_ycols(self, which_data_ycols), predict_kw) @@ -79,7 +80,7 @@ def _plot_mean(self, canvas, helper_data, helper_prediction, levels=20, projection='2d', label=None, **kwargs): - _, _, _, _, free_dims, Xgrid, x, y, _, _, resolution = helper_data + _, free_dims, Xgrid, x, y, _, _, resolution = helper_data if len(free_dims)<=2: mu, _, _ = helper_prediction if len(free_dims)==1: @@ -135,15 +136,16 @@ def plot_confidence(self, lower=2.5, upper=97.5, plot_limits=None, fixed_inputs= """ canvas, kwargs = pl().new_canvas(**kwargs) ycols = get_which_data_ycols(self, which_data_ycols) - helper_data = helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resolution) - helper_prediction = helper_predict_with_model(self, helper_data[5], plot_raw, apply_link, + X = get_x_y_var(self)[0] + helper_data = helper_for_plot_data(self, X, plot_limits, visible_dims, fixed_inputs, resolution) + helper_prediction = helper_predict_with_model(self, helper_data[2], plot_raw, apply_link, (lower, upper), ycols, predict_kw) plots = _plot_confidence(self, canvas, helper_data, helper_prediction, label, **kwargs) return pl().add_to_canvas(canvas, plots, legend=label is not None) def _plot_confidence(self, canvas, helper_data, helper_prediction, label, **kwargs): - _, _, _, _, free_dims, Xgrid, _, _, _, _, _ = helper_data + _, free_dims, Xgrid, _, _, _, _, _ = helper_data update_not_existing_kwargs(kwargs, pl().defaults.confidence_interval) # @UndefinedVariable if len(free_dims)<=1: if len(free_dims)==1: @@ -188,8 +190,9 @@ def plot_samples(self, plot_limits=None, fixed_inputs=None, """ canvas, kwargs = pl().new_canvas(projection=projection, **kwargs) ycols = get_which_data_ycols(self, which_data_ycols) - helper_data = helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resolution) - helper_prediction = helper_predict_with_model(self, helper_data[5], plot_raw, apply_link, + X = get_x_y_var(self)[0] + helper_data = helper_for_plot_data(self, X, plot_limits, visible_dims, fixed_inputs, resolution) + helper_prediction = helper_predict_with_model(self, helper_data[2], plot_raw, apply_link, None, ycols, predict_kw, samples) plots = _plot_samples(self, canvas, helper_data, helper_prediction, @@ -198,7 +201,7 @@ def plot_samples(self, plot_limits=None, fixed_inputs=None, def _plot_samples(self, canvas, helper_data, helper_prediction, projection, label, **kwargs): - _, _, _, _, free_dims, Xgrid, x, y, _, _, resolution = helper_data + _, free_dims, Xgrid, x, y, _, _, resolution = helper_data samples = helper_prediction[2] if len(free_dims)<=2: @@ -247,8 +250,9 @@ def plot_density(self, plot_limits=None, fixed_inputs=None, :param dict predict_kw: the keyword arguments for the prediction. If you want to plot a specific kernel give dict(kern=) in here """ canvas, kwargs = pl().new_canvas(**kwargs) - helper_data = helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resolution) - helper_prediction = helper_predict_with_model(self, helper_data[5], plot_raw, + X = get_x_y_var(self)[0] + helper_data = helper_for_plot_data(self, X, plot_limits, visible_dims, fixed_inputs, resolution) + helper_prediction = helper_predict_with_model(self, helper_data[2], plot_raw, apply_link, np.linspace(2.5, 97.5, levels*2), get_which_data_ycols(self, which_data_ycols), predict_kw) @@ -256,7 +260,7 @@ def plot_density(self, plot_limits=None, fixed_inputs=None, return pl().add_to_canvas(canvas, plots) def _plot_density(self, canvas, helper_data, helper_prediction, label, **kwargs): - _, _, _, _, free_dims, Xgrid, _, _, _, _, _ = helper_data + _, free_dims, Xgrid, _, _, _, _, _ = helper_data mu, percs, _ = helper_prediction update_not_existing_kwargs(kwargs, pl().defaults.density) # @UndefinedVariable @@ -316,8 +320,9 @@ def plot(self, plot_limits=None, fixed_inputs=None, :param bool legend: convenience, whether to put a legend on the plot or not. """ canvas, _ = pl().new_canvas(projection=projection, **kwargs) - helper_data = helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resolution) - helper_prediction = helper_predict_with_model(self, helper_data[5], plot_raw, + X = get_x_y_var(self)[0] + helper_data = helper_for_plot_data(self, X, plot_limits, visible_dims, fixed_inputs, resolution) + helper_prediction = helper_predict_with_model(self, helper_data[2], plot_raw, apply_link, np.linspace(2.5, 97.5, levels*2) if plot_density else (lower,upper), get_which_data_ycols(self, which_data_ycols), predict_kw, samples) @@ -330,7 +335,7 @@ def plot(self, plot_limits=None, fixed_inputs=None, plots.update(_plot_data_error(self, canvas, which_data_rows, which_data_ycols, visible_dims, projection, "Data Error")) plots.update(_plot(self, canvas, plots, helper_data, helper_prediction, levels, plot_inducing, plot_density, projection)) if plot_raw and (samples_likelihood > 0): - helper_prediction = helper_predict_with_model(self, helper_data[5], False, + helper_prediction = helper_predict_with_model(self, helper_data[2], False, apply_link, None, get_which_data_ycols(self, which_data_ycols), predict_kw, samples_likelihood) diff --git a/GPy/plotting/gpy_plot/kernel_plots.py b/GPy/plotting/gpy_plot/kernel_plots.py index 2194fdfc..daae15b8 100644 --- a/GPy/plotting/gpy_plot/kernel_plots.py +++ b/GPy/plotting/gpy_plot/kernel_plots.py @@ -30,10 +30,8 @@ import numpy as np from . import plotting_library as pl from .. import Tango -from .plot_util import get_x_y_var,\ - update_not_existing_kwargs, \ - helper_for_plot_data, scatter_label_generator, subsample_X,\ - find_best_layout_for_subplots +from .plot_util import update_not_existing_kwargs, helper_for_plot_data +from ...kern.src.kern import Kern, CombinationKernel def plot_ARD(kernel, filtering=None, legend=False, **kwargs): """ @@ -53,110 +51,90 @@ def plot_ARD(kernel, filtering=None, legend=False, **kwargs): x = np.arange(kernel.input_dim) + parts = [] + def visit(x): + if (not isinstance(x, CombinationKernel)) and isinstance(x, Kern): + parts.append(x) + kernel.traverse(visit) + if filtering is None: - filtering = kernel.parameter_names(recursive=False) + filtering = [k.name for k in parts] bars = [] kwargs = update_not_existing_kwargs(kwargs, pl().defaults.ard) - canvas, kwargs = pl().new_canvas(xlim=(-.5, kernel.input_dim-.5), **kwargs) + canvas, kwargs = pl().new_canvas(xlim=(-.5, kernel.input_dim-.5), xlabel='input dimension', ylabel='sensitivity', **kwargs) for i in range(ard_params.shape[0]): - if kernel.parameters[i].name in filtering: + if parts[i].name in filtering: c = Tango.nextMedium() bars.append(pl().barplot(canvas, x, ard_params[i,:], color=c, - label=kernel.parameters[i].name, + label=parts[i].name, bottom=bottom, **kwargs)) last_bottom = ard_params[i,:] bottom += last_bottom else: - print("filtering out {}".format(kernel.parameters[i].name)) + print("filtering out {}".format(parts[i].name)) #add_bar_labels(fig, ax, [bars[-1]], bottom=bottom-last_bottom) return pl().add_to_canvas(canvas, bars, legend=legend) -def plot_covariance(kernel, x=None, label=None, plot_limits=None, visible_dims=None, resolution=None, projection=None, levels=20, **mpl_kwargs): +def plot_covariance(kernel, x=None, label=None, + plot_limits=None, visible_dims=None, resolution=None, + projection='2d', levels=20, **kwargs): """ - plot a kernel. - :param x: the value to use for the other kernel argument (kernels are a function of two variables!) - :param fignum: figure number of the plot - :param ax: matplotlib axis to plot on - :param title: the matplotlib title + Plot a kernel covariance w.r.t. another x. + + :param array-like x: the value to use for the other kernel argument (kernels are a function of two variables!) :param plot_limits: the range over which to plot the kernel - :resolution: the resolution of the lines used in plotting - :mpl_kwargs avalid keyword arguments to pass through to matplotlib (e.g. lw=7) + :type plot_limits: Either (xmin, xmax) for 1D or (xmin, xmax, ymin, ymax) / ((xmin, xmax), (ymin, ymax)) for 2D + :param array-like visible_dims: input dimensions (!) to use for x. Make sure to select 2 or less dimensions to plot. + :resolution: the resolution of the lines used in plotting. for 2D this defines the grid for kernel evaluation. + :param {2d|3d} projection: What projection shall we use to plot the kernel? + :param int levels: for 2D projection, how many levels for the contour plot to use? + :param kwargs: valid kwargs for your specific plotting library """ - canvas, error_kwargs = pl().new_canvas(projection=projection, **error_kwargs) - _, _, _, _, free_dims, Xgrid, x, y, _, _, resolution = helper_for_plot_data(kernel, plot_limits, visible_dims, None, resolution) + X = np.ones((2, kernel.input_dim)) * [[-3], [3]] + _, free_dims, Xgrid, xx, yy, _, _, resolution = helper_for_plot_data(kernel, X, plot_limits, visible_dims, None, resolution) + + from numbers import Number + if x is None: + from ...kern.src.stationary import Stationary + x = np.ones((1, kernel.input_dim)) * (not isinstance(kernel, Stationary)) + elif isinstance(x, Number): + x = np.ones((1, kernel.input_dim))*x + K = kernel.K(Xgrid, x) + + if projection == '3d': + xlabel = 'X[:,0]' + ylabel = 'X[:,1]' + zlabel = "k(X, {!s})".format(np.asanyarray(x).tolist()) + else: + xlabel = 'X' + ylabel = "k(X, {!s})".format(np.asanyarray(x).tolist()) + zlabel = None + + canvas, kwargs = pl().new_canvas(projection=projection, xlabel=xlabel, ylabel=ylabel, zlabel=zlabel, **kwargs) if len(free_dims)<=2: if len(free_dims)==1: - if x is None: x = np.zeros((1, 1)) - else: - x = np.asarray(x) - assert x.size == 1, "The size of the fixed variable x is not 1" - x = x.reshape((1, 1)) # 1D plotting: update_not_existing_kwargs(kwargs, pl().defaults.meanplot_1d) # @UndefinedVariable - plots = dict(covariance=[pl().plot(canvas, Xgrid[:, free_dims], mu, label=label, **kwargs)]) + plots = dict(covariance=[pl().plot(canvas, Xgrid[:, free_dims], K, label=label, **kwargs)]) else: if projection == '2d': update_not_existing_kwargs(kwargs, pl().defaults.meanplot_2d) # @UndefinedVariable - plots = dict(covariance=[pl().contour(canvas, x, y, - mu.reshape(resolution, resolution).T, + plots = dict(covariance=[pl().contour(canvas, xx[:, 0], yy[0, :], + K.reshape(resolution, resolution), levels=levels, label=label, **kwargs)]) elif projection == '3d': update_not_existing_kwargs(kwargs, pl().defaults.meanplot_3d) # @UndefinedVariable - plots = dict(covariance=[pl().surface(canvas, x, y, - mu.reshape(resolution, resolution).T, + plots = dict(covariance=[pl().surface(canvas, xx, yy, + K.reshape(resolution, resolution), label=label, **kwargs)]) - return pl().add_to_canvas(canvas, plots) - if kernel.input_dim == 1: - - if plot_limits == None: - xmin, xmax = (x - 5).flatten(), (x + 5).flatten() - elif len(plot_limits) == 2: - xmin, xmax = plot_limits - else: - raise ValueError("Bad limits for plotting") - - Xnew = np.linspace(xmin, xmax, resolution or 201)[:, None] - Kx = kernel.K(Xnew, x) - ax.plot(Xnew, Kx, **mpl_kwargs) - ax.set_xlim(xmin, xmax) - ax.set_xlabel("x") - ax.set_ylabel("k(x,%0.1f)" % x) - - elif kernel.input_dim == 2: - if x is None: - x = np.zeros((1, 2)) - else: - x = np.asarray(x) - assert x.size == 2, "The size of the fixed variable x is not 2" - x = x.reshape((1, 2)) - - if plot_limits is None: - xmin, xmax = (x - 5).flatten(), (x + 5).flatten() - elif len(plot_limits) == 2: - xmin, xmax = plot_limits - else: - raise ValueError("Bad limits for plotting") - - - resolution = resolution or 51 - xx, yy = np.mgrid[xmin[0]:xmax[0]:1j * resolution, xmin[1]:xmax[1]:1j * resolution] - Xnew = np.vstack((xx.flatten(), yy.flatten())).T - Kx = kernel.K(Xnew, x) - Kx = Kx.reshape(resolution, resolution).T - ax.contour(xx, yy, Kx, vmin=Kx.min(), vmax=Kx.max(), cmap=pb.cm.jet, **mpl_kwargs) # @UndefinedVariable - ax.set_xlim(xmin[0], xmax[0]) - ax.set_ylim(xmin[1], xmax[1]) - ax.set_xlabel("x1") - ax.set_ylabel("x2") - ax.set_title("k(x1,x2 ; %0.1f,%0.1f)" % (x[0, 0], x[0, 1])) else: raise NotImplementedError("Cannot plot a kernel with more than two input dimensions") diff --git a/GPy/plotting/gpy_plot/latent_plots.py b/GPy/plotting/gpy_plot/latent_plots.py index 52c5fd17..2e5c7148 100644 --- a/GPy/plotting/gpy_plot/latent_plots.py +++ b/GPy/plotting/gpy_plot/latent_plots.py @@ -185,7 +185,8 @@ def plot_magnification(self, labels=None, which_indices=None, :param kwargs: the kwargs for the scatter plots """ input_1, input_2 = which_indices = self.get_most_significant_input_dimensions(which_indices)[:2] - X, _, _, _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, plot_limits, which_indices, None, resolution) + X = get_x_y_var(self)[0] + _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, X, plot_limits, which_indices, None, resolution) canvas, imshow_kwargs = pl().new_canvas(xlim=(xmin[0], xmax[0]), ylim=(xmin[1], xmax[1]), xlabel='latent dimension %i' % input_1, ylabel='latent dimension %i' % input_2, **imshow_kwargs) if (labels is not None): @@ -248,7 +249,8 @@ def plot_latent(self, labels=None, which_indices=None, :param scatter_kwargs: the kwargs for the scatter plots """ input_1, input_2 = which_indices = self.get_most_significant_input_dimensions(which_indices)[:2] - X, _, _, _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, plot_limits, which_indices, None, resolution) + X = get_x_y_var(self)[0] + _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, X, plot_limits, which_indices, None, resolution) canvas, imshow_kwargs = pl().new_canvas(xlim=(xmin[0], xmax[0]), ylim=(xmin[1], xmax[1]), xlabel='latent dimension %i' % input_1, ylabel='latent dimension %i' % input_2, **imshow_kwargs) if (labels is not None): @@ -313,7 +315,8 @@ def plot_steepest_gradient_map(self, output_labels=None, data_labels=None, which :param scatter_kwargs: the kwargs for the scatter plots """ input_1, input_2 = which_indices = self.get_most_significant_input_dimensions(which_indices)[:2] - X, _, _, _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, plot_limits, which_indices, None, resolution) + X = get_x_y_var(self)[0] + _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, X, plot_limits, which_indices, None, resolution) canvas, imshow_kwargs = pl().new_canvas(xlim=(xmin[0], xmax[0]), ylim=(xmin[1], xmax[1]), xlabel='latent dimension %i' % input_1, ylabel='latent dimension %i' % input_2, **imshow_kwargs) if (data_labels is not None): diff --git a/GPy/plotting/gpy_plot/plot_util.py b/GPy/plotting/gpy_plot/plot_util.py index 6aa1b8da..a60de819 100644 --- a/GPy/plotting/gpy_plot/plot_util.py +++ b/GPy/plotting/gpy_plot/plot_util.py @@ -102,19 +102,17 @@ def helper_predict_with_model(self, Xgrid, plot_raw, apply_link, percentiles, wh fsamples[:, s] = self.likelihood.gp_link.transf(fsamples[:, s]) return retmu, percs, fsamples -def helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resolution): +def helper_for_plot_data(self, X, plot_limits, visible_dims, fixed_inputs, resolution): """ Figure out the data, free_dims and create an Xgrid for the prediction. This is only implemented for two dimensions for now! """ - X, Xvar, Y = get_x_y_var(self) - #work out what the inputs are for plotting (1D or 2D) if fixed_inputs is None: fixed_inputs = [] - fixed_dims = get_fixed_dims(self, fixed_inputs) + fixed_dims = get_fixed_dims(fixed_inputs) free_dims = get_free_dims(self, visible_dims, fixed_dims) if len(free_dims) == 1: @@ -129,7 +127,7 @@ def helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resoluti y = None elif len(free_dims) == 2: #define the frame for plotting on - resolution = resolution or 50 + resolution = resolution or 35 Xnew, x, y, xmin, xmax = x_frame2D(X[:,free_dims], plot_limits, resolution) Xgrid = np.zeros((Xnew.shape[0], self.input_dim)) Xgrid[:,free_dims] = Xnew @@ -137,7 +135,7 @@ def helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resoluti Xgrid[:,i] = v else: raise TypeError("calculated free_dims {} from visible_dims {} and fixed_dims {} is neither 1D nor 2D".format(free_dims, visible_dims, fixed_dims)) - return X, Xvar, Y, fixed_dims, free_dims, Xgrid, x, y, xmin, xmax, resolution + return fixed_dims, free_dims, Xgrid, x, y, xmin, xmax, resolution def scatter_label_generator(labels, X, visible_dims, marker=None): ulabels = [] @@ -271,13 +269,16 @@ def update_not_existing_kwargs(to_update, update_from): def get_x_y_var(model): """ - The the data from a model as + Either the the data from a model as X the inputs, X_variance the variance of the inputs ([default: None]) and Y the outputs + If (X, X_variance, Y) is given, this just returns. + :returns: (X, X_variance, Y) """ + # model given if hasattr(model, 'has_uncertain_inputs') and model.has_uncertain_inputs(): X = model.X.mean.values X_variance = model.X.variance.values @@ -305,7 +306,7 @@ def get_free_dims(model, visible_dims, fixed_dims): return np.asanyarray([dim for dim in dims if dim is not None]) -def get_fixed_dims(model, fixed_inputs): +def get_fixed_dims(fixed_inputs): """ Work out the fixed dimensions from the fixed_inputs list of tuples. """ @@ -339,7 +340,7 @@ def x_frame1D(X,plot_limits=None,resolution=None): else: xmin,xmax = X.min(0),X.max(0) xmin, xmax = xmin-0.25*(xmax-xmin), xmax+0.25*(xmax-xmin) - elif len(plot_limits)==2: + elif len(plot_limits) == 2: xmin, xmax = plot_limits else: raise ValueError("Bad limits for plotting") @@ -355,9 +356,15 @@ def x_frame2D(X,plot_limits=None,resolution=None): if plot_limits is None: xmin, xmax = X.min(0),X.max(0) xmin, xmax = xmin-0.075*(xmax-xmin), xmax+0.075*(xmax-xmin) - elif len(plot_limits)==2: + elif len(plot_limits) == 2: xmin, xmax = plot_limits - elif len(plot_limits)==4: + try: + xmin = xmin[0], xmin[1] + except: + # only one limit given, copy over to other lim + xmin = [plot_limits[0], plot_limits[0]] + xmax = [plot_limits[1], plot_limits[1]] + elif len(plot_limits) == 4: xmin, xmax = (plot_limits[0], plot_limits[2]), (plot_limits[1], plot_limits[3]) else: raise ValueError("Bad limits for plotting") diff --git a/GPy/testing/plotting_tests.py b/GPy/testing/plotting_tests.py index 0c1e21f9..19064094 100644 --- a/GPy/testing/plotting_tests.py +++ b/GPy/testing/plotting_tests.py @@ -143,13 +143,16 @@ def test_kernel(): matplotlib.rcParams.update(matplotlib.rcParamsDefault) matplotlib.rcParams[u'figure.figsize'] = (4,3) matplotlib.rcParams[u'text.usetex'] = False - k = GPy.kern.RBF(5, ARD=True) + GPy.kern.Linear(3, active_dims=[0,2,4], ARD=True) + GPy.kern.Bias(2) + k = GPy.kern.RBF(5, ARD=True) * GPy.kern.Linear(3, active_dims=[0,2,4], ARD=True) + GPy.kern.Bias(2) k.randomize() - k2 = GPy.kern.RBF(5, ARD=True) + GPy.kern.Linear(3, active_dims=[0,2,4], ARD=True) + GPy.kern.Bias(2) + GPy.kern.White(4) + k2 = GPy.kern.RBF(5, ARD=True) * GPy.kern.Linear(3, active_dims=[0,2,4], ARD=True) + GPy.kern.Bias(2) + GPy.kern.White(4) k2[:-1] = k[:] - k2.plot_ARD([_.name for _ in k.parts], legend=True) + k2.plot_ARD(['rbf', 'linear', 'bias'], legend=True) + k2.plot_covariance(visible_dims=[0, 3], plot_limits=(-1,3)) + k2.plot_covariance(visible_dims=[2], plot_limits=(-1, 3)) + k2.plot_covariance(visible_dims=[2, 4], plot_limits=((-1, 0), (5, 3)), projection='3d') for do_test in _image_comparison( - baseline_images=['kern_{}'.format(sub) for sub in ["ARD",]], + baseline_images=['kern_{}'.format(sub) for sub in ["ARD", 'cov_2d', 'cov_1d', 'cov_3d']], extensions=extensions): yield (do_test, ) diff --git a/GPy/testing/plotting_tests/baseline/kern_cov_1d.png b/GPy/testing/plotting_tests/baseline/kern_cov_1d.png new file mode 100644 index 0000000000000000000000000000000000000000..449a686d339be295f88e5e90e81a920406e7e810 GIT binary patch literal 6916 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 literal 0 HcmV?d00001 diff --git a/GPy/testing/plotting_tests/baseline/kern_cov_2d.png b/GPy/testing/plotting_tests/baseline/kern_cov_2d.png new file mode 100644 index 0000000000000000000000000000000000000000..db76f5b6e5efc1298051f5b47ab121dd0d58790f GIT binary patch literal 27886 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 HeE5F=@*Ryn literal 0 HcmV?d00001 diff --git a/GPy/testing/plotting_tests/baseline/kern_cov_3d.png b/GPy/testing/plotting_tests/baseline/kern_cov_3d.png new file mode 100644 index 0000000000000000000000000000000000000000..31b32b5e7179a1ac583a2098ec0cadbeaefc3147 GIT binary patch literal 23854 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 NOa0lC3e^`O{{!&DO~?QM literal 0 HcmV?d00001 diff --git a/doc/source/conf.py b/doc/source/conf.py index 91187571..68d0c2a8 100644 --- a/doc/source/conf.py +++ b/doc/source/conf.py @@ -85,8 +85,9 @@ master_doc = 'index' # General information about the project. project = u'GPy' -copyright = u'2015, GPy Authors' -author = u'GPy Authors' +#author = u'`Humans `_' +author = 'GPy Authors, see https://github.com/SheffieldML/GPy/graphs/contributors' +copyright = u'2015, '+author # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the diff --git a/setup.py b/setup.py index 014c7f36..fdccea7d 100644 --- a/setup.py +++ b/setup.py @@ -49,7 +49,7 @@ def read_to_rst(fname): try: import pypandoc rstname = "{}.{}".format(os.path.splitext(fname)[0], 'rst') - pypandoc.convert(read(fname), 'rst', rstname) + pypandoc.convert(read(fname), 'rst', outputfile=rstname) return read(rstname) except ImportError: return read(fname)