diff --git a/GPy/kern/_src/kern.py b/GPy/kern/_src/kern.py index 453f5c2e..8bc053a4 100644 --- a/GPy/kern/_src/kern.py +++ b/GPy/kern/_src/kern.py @@ -224,26 +224,13 @@ class Kern(Parameterized): (0, None, None). :param which_indices: force the indices to be the given indices. - :type which_indices: int or tuple(int,int) + :type which_indices: int or tuple(int,int) or tuple(int,int,int) """ if which_indices is None: - if self.input_dim == 1: - input_1 = 0 - input_2 = None - input_3 = None - if self.input_dim == 2: - input_1, input_2 = 0, 1 - input_3 = None - if self.input_dim == 3: - input_1, input_2, input_3 = 0, 1, 2 - else: - try: - which_indices = np.argsort(self.input_sensitivity())[::-1][:3] - except: - raise ValueError("cannot automatically determine which dimensions to plot, please pass 'which_indices'") + which_indices = np.argsort(self.input_sensitivity())[::-1][:3] try: input_1, input_2, input_3 = which_indices - except TypeError: + except ValueError: # which indices is tuple or int try: input_3 = None @@ -253,8 +240,7 @@ class Kern(Parameterized): input_1, input_2 = which_indices, None except ValueError: # which_indices was a list or array like with only one int - input_1, input_2 = which_indices[0], None - + input_1, input_2 = which_indices[0], None return input_1, input_2, input_3 diff --git a/GPy/plotting/__init__.py b/GPy/plotting/__init__.py index 7de05473..b898f9b0 100644 --- a/GPy/plotting/__init__.py +++ b/GPy/plotting/__init__.py @@ -42,17 +42,21 @@ if config.get('plotting', 'library') is not 'none': SparseGP.plot_inducing = gpy_plot.data_plots.plot_inducing from ..models import GPLVM, BayesianGPLVM, bayesian_gplvm_minibatch, SSGPLVM, SSMRD - GPLVM.plot_prediction_fit = gpy_plot.latent_plots.plot_prediction_fit GPLVM.plot_latent = gpy_plot.latent_plots.plot_latent + GPLVM.plot_latent_scatter = gpy_plot.latent_plots.plot_latent_scatter + GPLVM.plot_latent_inducing = gpy_plot.latent_plots.plot_latent_inducing GPLVM.plot_steepest_gradient_map = gpy_plot.latent_plots.plot_steepest_gradient_map BayesianGPLVM.plot_latent = gpy_plot.latent_plots.plot_latent - BayesianGPLVM.plot_prediction_fit = gpy_plot.latent_plots.plot_prediction_fit + BayesianGPLVM.plot_latent_scatter = gpy_plot.latent_plots.plot_latent_scatter + BayesianGPLVM.plot_latent_inducing = gpy_plot.latent_plots.plot_latent_inducing BayesianGPLVM.plot_steepest_gradient_map = gpy_plot.latent_plots.plot_steepest_gradient_map bayesian_gplvm_minibatch.BayesianGPLVMMiniBatch.plot_latent = gpy_plot.latent_plots.plot_latent - bayesian_gplvm_minibatch.BayesianGPLVMMiniBatch.plot_prediction_fit = gpy_plot.latent_plots.plot_prediction_fit + bayesian_gplvm_minibatch.BayesianGPLVMMiniBatch.plot_latent_scatter = gpy_plot.latent_plots.plot_latent_scatter + bayesian_gplvm_minibatch.BayesianGPLVMMiniBatch.plot_latent_inducing = gpy_plot.latent_plots.plot_latent_inducing bayesian_gplvm_minibatch.BayesianGPLVMMiniBatch.plot_steepest_gradient_map = gpy_plot.latent_plots.plot_steepest_gradient_map SSGPLVM.plot_latent = gpy_plot.latent_plots.plot_latent - SSGPLVM.plot_prediction_fit = gpy_plot.latent_plots.plot_prediction_fit + SSGPLVM.plot_latent_scatter = gpy_plot.latent_plots.plot_latent_scatter + SSGPLVM.plot_latent_inducing = gpy_plot.latent_plots.plot_latent_inducing SSGPLVM.plot_steepest_gradient_map = gpy_plot.latent_plots.plot_steepest_gradient_map from ..kern import Kern diff --git a/GPy/plotting/abstract_plotting_library.py b/GPy/plotting/abstract_plotting_library.py index dd59ef2e..2bbb8dc4 100644 --- a/GPy/plotting/abstract_plotting_library.py +++ b/GPy/plotting/abstract_plotting_library.py @@ -174,30 +174,45 @@ class AbstractPlottingLibrary(object): """ raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library") - def imshow(self, canvas, X, extent=None, label=None, plot_function=None, vmin=None, vmax=None, **kwargs): + def imshow(self, canvas, X, extent=None, label=None, vmin=None, vmax=None, **kwargs): """ Show the image stored in X on the canvas. - if X is a function, create an imshow controller to stream - the image. There is an imshow controller written for - mmatplotlib, which updates the imshow on changes in axis. - - Just ignore the plot_function, if you do not have the option - to have interactive changes. - The origin of the image show is (0,0), such that X[0,0] gets plotted at [0,0] of the image! the kwargs are plotting library specific kwargs! """ raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library") - def annotation_heatmap(self, canvas, X, annotation, extent, label=None, plot_function=None, resolution=15, **kwargs): + def imshow_interact(self, canvas, plot_function, extent=None, label=None, vmin=None, vmax=None, **kwargs): + """ + This function is optional! + + Create an imshow controller to stream + the image returned by the plot_function. There is an imshow controller written for + mmatplotlib, which updates the imshow on changes in axis. + + The origin of the image show is (0,0), such that X[0,0] gets plotted at [0,0] of the image! + + the kwargs are plotting library specific kwargs! + """ + raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library") + + def annotation_heatmap(self, canvas, X, annotation, extent, label=None, **kwargs): """ Plot an annotation heatmap. That is like an imshow, but - put the text of the labels inside the cells of the heatmap (centered). - - if the labels are not given, just plot the heatmap. + put the text of the annotation inside the cells of the heatmap (centered). + :param canvas: the canvas to plot on + :param array-like annotation: the annotation labels for the heatmap + :param [horizontal_min,horizontal_max,vertical_min,vertical_max] extent: the extent of where to place the heatmap + :param str label: the label for the heatmap + :return: a list of both the heatmap and annotation plots [heatmap, annotation], or the interactive update object (alone) + """ + raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library") + + def annotation_heatmap_interact(self, canvas, plot_function, extent, label=None, resolution=15, **kwargs): + """ if plot_function is not None, return an interactive updated heatmap, which updates on axis events, so that one can zoom in and out and the heatmap gets updated. See the matplotlib implementation @@ -206,14 +221,14 @@ class AbstractPlottingLibrary(object): the plot_function returns a pair (X, annotation) to plot, when called with a new input X (which would be the grid, which is visible on the plot right now) - + :param canvas: the canvas to plot on :param array-like annotation: the annotation labels for the heatmap :param [horizontal_min,horizontal_max,vertical_min,vertical_max] extent: the extent of where to place the heatmap :param str label: the label for the heatmap + :return: a list of both the heatmap and annotation plots [heatmap, annotation], or the interactive update object (alone) :param plot_function: the function, which generates new data for given input locations X :param int resolution: the resolution of the interactive plot redraw - this is only needed when giving a plot_function - :return: a list of both the heatmap and annotation plots [heatmap, annotation] """ raise NotImplementedError("Implement all plot functions in AbstractPlottingLibrary in order to use your own plotting library") diff --git a/GPy/plotting/gpy_plot/latent_plots.py b/GPy/plotting/gpy_plot/latent_plots.py index fd2bba20..88aeda9a 100644 --- a/GPy/plotting/gpy_plot/latent_plots.py +++ b/GPy/plotting/gpy_plot/latent_plots.py @@ -47,85 +47,19 @@ def _wait_for_updates(view, updates): pass -def plot_prediction_fit(self, plot_limits=None, - which_data_rows='all', which_data_ycols='all', - fixed_inputs=None, resolution=None, - plot_raw=False, apply_link=False, visible_dims=None, - predict_kw=None, scatter_kwargs=None, **plot_kwargs): - """ - Plot the fit of the (Bayesian)GPLVM latent space prediction to the outputs. - This scatters two output dimensions against each other and a line - from the prediction in two dimensions between them. - - Give the Y_metadata in the predict_kw if you need it. - - :param which_data_rows: which of the training data to plot (default all) - :type which_data_rows: 'all' or a slice object to slice self.X, self.Y - :param array-like which_data_ycols: which columns of y to plot (array-like or list of ints) - :param fixed_inputs: a list of tuple [(i,v), (i,v)...], specifying that input dimension i should be set to value v. - :type fixed_inputs: a list of tuples - :param int resolution: The resolution of the prediction [defaults are 1D:200, 2D:50] - :param bool plot_raw: plot the latent function (usually denoted f) only? - :param bool apply_link: whether to apply the link function of the GP to the raw prediction. - :param array-like visible_dims: which columns of the input X (!) to plot (array-like or list of ints) - :param dict predict_kw: the keyword arguments for the prediction. If you want to plot a specific kernel give dict(kern=) in here - :param dict sactter_kwargs: kwargs for the scatter plot, specific for the plotting library you are using - :param kwargs plot_kwargs: kwargs for the data plot for the plotting library you are using - """ - canvas, kwargs = pl.get_new_canvas(**plot_kwargs) - plots = _plot_prediction_fit(self, canvas, plot_limits, which_data_rows, which_data_ycols, - fixed_inputs, resolution, plot_raw, - apply_link, visible_dims, - predict_kw, scatter_kwargs, **kwargs) - return pl.show_canvas(canvas, plots) - -def _plot_prediction_fit(self, canvas, plot_limits=None, - which_data_rows='all', which_data_ycols='all', - fixed_inputs=None, resolution=None, - plot_raw=False, apply_link=False, visible_dims=False, - predict_kw=None, scatter_kwargs=None, **plot_kwargs): - - ycols = get_which_data_ycols(self, which_data_ycols) - rows = get_which_data_rows(self, which_data_rows) - - if visible_dims is None: - visible_dims = self.get_most_significant_input_dimensions()[:1] - - X, _, Y, _, free_dims, Xgrid, _, _, _, _, resolution = helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resolution) - - plots = {} - - if len(free_dims)<2: - if len(free_dims)==1: - if scatter_kwargs is None: - scatter_kwargs = {} - update_not_existing_kwargs(scatter_kwargs, pl.defaults.data_y_1d) # @UndefinedVariable - plots['output'] = pl.scatter(canvas, Y[rows, ycols[0]], Y[rows, ycols[1]], - color=X[rows, free_dims[0]], - **scatter_kwargs) - if predict_kw is None: - predict_kw = {} - mu, _, _ = helper_predict_with_model(self, Xgrid, plot_raw, - apply_link, None, - ycols, predict_kw) - update_not_existing_kwargs(plot_kwargs, pl.defaults.data_y_1d_plot) # @UndefinedVariable - plots['output_fit'] = pl.plot(canvas, mu[:, 0], mu[:, 1], **plot_kwargs) - else: - pass #Nothing to plot! - else: - raise NotImplementedError("Cannot plot in more then one dimension.") - return plots - -def _plot_latent_scatter(self, canvas, X, visible_dims, labels, marker, num_samples, projection='2d', **kwargs): +def _plot_latent_scatter(canvas, X, visible_dims, labels, marker, num_samples, projection='2d', **kwargs): from .. import Tango Tango.reset() - if labels is None: - labels = np.ones(self.num_data) X, labels = subsample_X(X, labels, num_samples) - scatters = [] + scatters = [] + generate_colors = 'color' not in kwargs for x, y, z, this_label, _, m in scatter_label_generator(labels, X, visible_dims, marker): update_not_existing_kwargs(kwargs, pl.defaults.latent_scatter) - scatters.append(pl.scatter(canvas, x, y, Z=z, marker=m, color=Tango.nextMedium(), label=this_label, **kwargs)) + if generate_colors: + kwargs['color'] = Tango.nextMedium() + if projection == '3d': + scatters.append(pl.scatter(canvas, x, y, Z=z, marker=m, label=this_label, **kwargs)) + else: scatters.append(pl.scatter(canvas, x, y, marker=m, label=this_label, **kwargs)) return scatters def plot_latent_scatter(self, labels=None, @@ -147,43 +81,81 @@ def plot_latent_scatter(self, labels=None, :param str marker: markers to use - cycle if more labels then markers are given :param kwargs: the kwargs for the scatter plots """ - sig_dims = self.get_most_significant_input_dimensions(which_indices) - input_1, input_2, input_3 = [i for i in sig_dims if i is not None] - + input_1, input_2, input_3 = sig_dims = self.get_most_significant_input_dimensions(which_indices) + canvas, kwargs = pl.get_new_canvas(projection=projection, **kwargs) X, _, _ = get_x_y_var(self) - scatters = _plot_latent_scatter(self, canvas, X, sig_dims, labels, marker, num_samples, projection=projection, **kwargs) + if labels is None: + labels = np.ones(self.num_data) + legend = False + else: + legend = find_best_layout_for_subplots(len(np.unique(labels))) + scatters = _plot_latent_scatter(canvas, X, sig_dims, labels, marker, num_samples, projection=projection, **kwargs) if projection == '3d': - return pl.show_canvas(canvas, dict(scatter=scatters), legend=legend and (labels is not None), + return pl.show_canvas(canvas, dict(scatter=scatters), legend=legend, xlabel='latent dimension %i' % input_1, ylabel='latent dimension %i' % input_2, zlabel='latent dimension %i' % input_3) else: - return pl.show_canvas(canvas, dict(scatter=scatters), legend=legend and (labels is not None), + return pl.show_canvas(canvas, dict(scatter=scatters), legend=legend, + xlabel='latent dimension %i' % input_1, + ylabel='latent dimension %i' % input_2, + #zlabel='latent dimension %i' % input_3 + ) +def plot_latent_inducing(self, + which_indices=None, + legend=False, + plot_limits=None, + marker='^', + num_samples=1000, + projection='2d', + **kwargs): + """ + Plot a scatter plot of the inducing inputs. + + :param array-like labels: a label for each data point (row) of the inputs + :param (int, int) which_indices: which input dimensions to plot against each other + :param bool legend: whether to plot the legend on the figure + :param plot_limits: the plot limits for the plot + :type plot_limits: (xmin, xmax, ymin, ymax) or ((xmin, xmax), (ymin, ymax)) + :param str marker: markers to use - cycle if more labels then markers are given + :param kwargs: the kwargs for the scatter plots + """ + input_1, input_2, input_3 = sig_dims = self.get_most_significant_input_dimensions(which_indices) + + if 'color' not in kwargs: + kwargs['color'] = 'white' + canvas, kwargs = pl.get_new_canvas(projection=projection, **kwargs) + X, _, _ = get_x_y_var(self) + labels = np.ones(self.num_data) + scatters = _plot_latent_scatter(canvas, X, sig_dims, labels, marker, num_samples, projection=projection, **kwargs) + if projection == '3d': + return pl.show_canvas(canvas, dict(scatter=scatters), legend=legend, + xlabel='latent dimension %i' % input_1, + ylabel='latent dimension %i' % input_2, + zlabel='latent dimension %i' % input_3) + else: + return pl.show_canvas(canvas, dict(scatter=scatters), legend=legend, xlabel='latent dimension %i' % input_1, ylabel='latent dimension %i' % input_2, #zlabel='latent dimension %i' % input_3 ) - -def _plot_magnification(self, canvas, input_1, input_2, Xgrid, +def _plot_magnification(self, canvas, which_indices, Xgrid, xmin, xmax, resolution, mean=True, covariance=True, kern=None, **imshow_kwargs): def plot_function(x): Xtest_full = np.zeros((x.shape[0], Xgrid.shape[1])) - Xtest_full[:, [input_1, input_2]] = x + Xtest_full[:, which_indices] = x mf = self.predict_magnification(Xtest_full, kern=kern, mean=mean, covariance=covariance) return mf.reshape(resolution, resolution).T imshow_kwargs = update_not_existing_kwargs(imshow_kwargs, pl.defaults.magnification) - Y = plot_function(Xgrid[:, [input_1, input_2]]) - view = pl.imshow(canvas, Y, - (xmin[0], xmax[0], xmin[1], xmax[1]), - None, plot_function, resolution, - vmin=Y.min(), vmax=Y.max(), - **imshow_kwargs) - return view + try: + return pl.imshow_interact(canvas, plot_function, (xmin[0], xmax[0], xmin[1], xmax[1]), resolution=resolution, **imshow_kwargs) + except NotImplementedError: + return pl.imshow(canvas, plot_function(Xgrid), (xmin[0], xmax[0], xmin[1], xmax[1]), **imshow_kwargs) def plot_magnification(self, labels=None, which_indices=None, resolution=60, marker='<>^vsd', legend=True, @@ -211,13 +183,16 @@ def plot_magnification(self, labels=None, which_indices=None, :param imshow_kwargs: the kwargs for the imshow (magnification factor) :param kwargs: the kwargs for the scatter plots """ - input_1, input_2 = self.get_most_significant_input_dimensions(which_indices) + input_1, input_2 = which_indices = self.get_most_significant_input_dimensions(which_indices)[:2] canvas, imshow_kwargs = pl.get_new_canvas(**imshow_kwargs) - X, _, _, _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, plot_limits, (input_1, input_2), None, resolution) - scatters = _plot_latent_scatter(self, canvas, X, input_1, input_2, labels, marker, num_samples, **scatter_kwargs or {}) - view = _plot_magnification(self, canvas, input_1, input_2, Xgrid, xmin, xmax, resolution, mean, covariance, kern, **imshow_kwargs) - if (legend is True) and (labels is not None): + X, _, _, _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, plot_limits, which_indices, None, resolution) + if (labels is not None): legend = find_best_layout_for_subplots(len(np.unique(labels)))[1] + else: + labels = np.ones(self.num_data) + legend = False + scatters = _plot_latent_scatter(canvas, X, which_indices, labels, marker, num_samples, projection='2d', **scatter_kwargs or {}) + view = _plot_magnification(self, canvas, which_indices[:2], Xgrid, xmin, xmax, resolution, mean, covariance, kern, **imshow_kwargs) plots = pl.show_canvas(canvas, dict(scatter=scatters, imshow=view), legend=legend, xlim=(xmin[0], xmax[0]), ylim=(xmin[1], xmax[1]), @@ -228,24 +203,21 @@ def plot_magnification(self, labels=None, which_indices=None, -def _plot_latent(self, canvas, input_1, input_2, Xgrid, +def _plot_latent(self, canvas, which_indices, Xgrid, xmin, xmax, resolution, kern=None, **imshow_kwargs): def plot_function(x): Xtest_full = np.zeros((x.shape[0], Xgrid.shape[1])) - Xtest_full[:, [input_1, input_2]] = x + Xtest_full[:, which_indices] = x mf = np.log(self.predict(Xtest_full, kern=kern)[1]) return mf.reshape(resolution, resolution).T imshow_kwargs = update_not_existing_kwargs(imshow_kwargs, pl.defaults.latent) - Y = plot_function(Xgrid[:, [input_1, input_2]]).reshape(resolution, resolution).T - view = pl.imshow(canvas, Y, - (xmin[0], xmax[0], xmin[1], xmax[1]), - None, plot_function, resolution, - vmin=Y.min(), vmax=Y.max(), - **imshow_kwargs) - return view + try: + return pl.imshow_interact(canvas, plot_function, (xmin[0], xmax[0], xmin[1], xmax[1]), resolution=resolution, **imshow_kwargs) + except NotImplementedError: + return pl.imshow(canvas, plot_function(Xgrid), (xmin[0], xmax[0], xmin[1], xmax[1]), **imshow_kwargs) def plot_latent(self, labels=None, which_indices=None, resolution=60, legend=True, @@ -272,13 +244,16 @@ def plot_latent(self, labels=None, which_indices=None, :param imshow_kwargs: the kwargs for the imshow (magnification factor) :param scatter_kwargs: the kwargs for the scatter plots """ - input_1, input_2 = self.get_most_significant_input_dimensions(which_indices) + input_1, input_2 = which_indices = self.get_most_significant_input_dimensions(which_indices)[:2] canvas, imshow_kwargs = pl.get_new_canvas(**imshow_kwargs) - X, _, _, _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, plot_limits, (input_1, input_2), None, resolution) - scatters = _plot_latent_scatter(self, canvas, X, input_1, input_2, labels, marker, num_samples, **scatter_kwargs or {}) - view = _plot_latent(self, canvas, input_1, input_2, Xgrid, xmin, xmax, resolution, kern, **imshow_kwargs) - if (legend is True) and (labels is not None): + X, _, _, _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, plot_limits, which_indices, None, resolution) + if (labels is not None): legend = find_best_layout_for_subplots(len(np.unique(labels)))[1] + else: + labels = np.ones(self.num_data) + legend = False + scatters = _plot_latent_scatter(canvas, X, which_indices, labels, marker, num_samples, projection='2d', **scatter_kwargs or {}) + view = _plot_latent(self, canvas, which_indices, Xgrid, xmin, xmax, resolution, kern, **imshow_kwargs) plots = pl.show_canvas(canvas, dict(scatter=scatters, imshow=view), legend=legend, xlim=(xmin[0], xmax[0]), ylim=(xmin[1], xmax[1]), @@ -286,25 +261,25 @@ def plot_latent(self, labels=None, which_indices=None, _wait_for_updates(view, updates) return plots -def _plot_steepest_gradient_map(self, canvas, input_1, input_2, Xgrid, +def _plot_steepest_gradient_map(self, canvas, which_indices, Xgrid, xmin, xmax, resolution, output_labels, kern=None, annotation_kwargs=None, **imshow_kwargs): if output_labels is None: output_labels = range(self.output_dim) def plot_function(x): - Xgrid[:, [input_1, input_2]] = x - dmu_dX = self.predictive_gradients(Xgrid, kern=kern)[0].sum(1) + Xgrid[:, which_indices] = x + dmu_dX = np.sqrt(((self.predictive_gradients(Xgrid, kern=kern)[0])**2).sum(1)) + #dmu_dX = self.predictive_gradients(Xgrid, kern=kern)[0].sum(1) argmax = np.argmax(dmu_dX, 1).astype(int) - return dmu_dX.max(1).reshape(resolution, resolution).T, np.array(output_labels)[argmax].reshape(resolution, resolution) - Y, annotation = plot_function(Xgrid[:, [input_1, input_2]]) + return dmu_dX.max(1).reshape(resolution, resolution).T, np.array(output_labels)[argmax].reshape(resolution, resolution).T annotation_kwargs = update_not_existing_kwargs(annotation_kwargs or {}, pl.defaults.annotation) imshow_kwargs = update_not_existing_kwargs(imshow_kwargs or {}, pl.defaults.gradient) - imshow, annotation = pl.annotation_heatmap(canvas, Y, annotation, - (xmin[0], xmax[0], xmin[1], xmax[1]), - None, plot_function, resolution, - imshow_kwargs=imshow_kwargs, **annotation_kwargs) - return dict(heatmap=imshow, annotation=annotation) + try: + return dict(annotation=pl.annotation_heatmap_interact(canvas, plot_function, (xmin[0], xmax[0], xmin[1], xmax[1]), resolution=resolution, imshow_kwargs=imshow_kwargs, **annotation_kwargs)) + except NotImplementedError: + imshow, annotation = pl.annotation_heatmap(canvas, *plot_function(Xgrid), extent=(xmin[0], xmax[0], xmin[1], xmax[1]), imshow_kwargs=imshow_kwargs, **annotation_kwargs) + return dict(heatmap=imshow, annotation=annotation) def plot_steepest_gradient_map(self, output_labels=None, data_labels=None, which_indices=None, resolution=15, legend=True, @@ -333,13 +308,16 @@ def plot_steepest_gradient_map(self, output_labels=None, data_labels=None, which :param annotation_kwargs: the kwargs for the annotation plot :param scatter_kwargs: the kwargs for the scatter plots """ - input_1, input_2 = self.get_most_significant_input_dimensions(which_indices) + input_1, input_2 = which_indices = self.get_most_significant_input_dimensions(which_indices)[:2] canvas, imshow_kwargs = pl.get_new_canvas(**imshow_kwargs) - X, _, _, _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, plot_limits, (input_1, input_2), None, resolution) - plots = dict(scatter=_plot_latent_scatter(self, canvas, X, input_1, input_2, data_labels, marker, num_samples, **scatter_kwargs or {})) - plots.update(_plot_steepest_gradient_map(self, canvas, input_1, input_2, Xgrid, xmin, xmax, resolution, output_labels, kern, annotation_kwargs=annotation_kwargs, **imshow_kwargs)) - if (legend is True) and (data_labels is not None): + X, _, _, _, _, Xgrid, _, _, xmin, xmax, resolution = helper_for_plot_data(self, plot_limits, which_indices, None, resolution) + if (data_labels is not None): legend = find_best_layout_for_subplots(len(np.unique(data_labels)))[1] + else: + data_labels = np.ones(self.num_data) + legend = False + plots = dict(scatter=_plot_latent_scatter(canvas, X, which_indices, data_labels, marker, num_samples, **scatter_kwargs or {})) + plots.update(_plot_steepest_gradient_map(self, canvas, which_indices, Xgrid, xmin, xmax, resolution, output_labels, kern, annotation_kwargs=annotation_kwargs, **imshow_kwargs)) pl.show_canvas(canvas, plots, legend=legend, xlim=(xmin[0], xmax[0]), ylim=(xmin[1], xmax[1]), xlabel='latent dimension %i' % input_1, ylabel='latent dimension %i' % input_2) diff --git a/GPy/plotting/gpy_plot/plot_util.py b/GPy/plotting/gpy_plot/plot_util.py index f99ee5e6..031d5266 100644 --- a/GPy/plotting/gpy_plot/plot_util.py +++ b/GPy/plotting/gpy_plot/plot_util.py @@ -100,6 +100,8 @@ def helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resoluti """ 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) @@ -107,13 +109,13 @@ def helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resoluti if fixed_inputs is None: fixed_inputs = [] fixed_dims = get_fixed_dims(self, fixed_inputs) - free_dims = get_free_dims(self, visible_dims, fixed_dims) + free_dims = get_free_dims(self, visible_dims, fixed_dims)[:2] if len(free_dims) == 1: #define the frame on which to plot resolution = resolution or 200 Xnew, xmin, xmax = x_frame1D(X[:,free_dims], plot_limits=plot_limits, resolution=resolution) - Xgrid = np.empty((Xnew.shape[0],self.input_dim)) + Xgrid = np.zeros((Xnew.shape[0],self.input_dim)) Xgrid[:,free_dims] = Xnew for i,v in fixed_inputs: Xgrid[:,i] = v @@ -123,10 +125,12 @@ def helper_for_plot_data(self, plot_limits, visible_dims, fixed_inputs, resoluti #define the frame for plotting on resolution = resolution or 50 Xnew, x, y, xmin, xmax = x_frame2D(X[:,free_dims], plot_limits, resolution) - Xgrid = np.empty((Xnew.shape[0],self.input_dim)) + Xgrid = np.zeros((Xnew.shape[0], self.input_dim)) Xgrid[:,free_dims] = Xnew for i,v in fixed_inputs: - Xgrid[:,i] = v + 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 def scatter_label_generator(labels, X, visible_dims, marker=None): @@ -140,7 +144,16 @@ def scatter_label_generator(labels, X, visible_dims, marker=None): else: m = None - input_1, input_2, input_3 = visible_dims + try: + input_1, input_2, input_3 = visible_dims + except: + try: + # tuple or int? + input_1, input_2 = visible_dims + input_3 = None + except: + input_1 = visible_dims + input_2 = input_3 = None for ul in ulabels: if type(ul) is np.string_: @@ -280,10 +293,11 @@ def get_free_dims(model, visible_dims, fixed_dims): """ if visible_dims is None: visible_dims = np.arange(model.input_dim) - visible_dims = np.asanyarray(visible_dims) + dims = np.asanyarray(visible_dims) if fixed_dims is not None: - return np.setdiff1d(visible_dims, fixed_dims) - return visible_dims + dims = np.setdiff1d(dims, fixed_dims) + return np.asanyarray([dim for dim in dims if dim is not None]) + def get_fixed_dims(model, fixed_inputs): """ diff --git a/GPy/plotting/matplot_dep/controllers/imshow_controller.py b/GPy/plotting/matplot_dep/controllers/imshow_controller.py index 63ac743b..ceeda262 100644 --- a/GPy/plotting/matplot_dep/controllers/imshow_controller.py +++ b/GPy/plotting/matplot_dep/controllers/imshow_controller.py @@ -57,18 +57,18 @@ class ImAnnotateController(ImshowController): def _init_view(self, ax, X, xmin, xmax, ymin, ymax, **kwargs): view = [super(ImAnnotateController, self)._init_view(ax, X[0], xmin, xmax, ymin, ymax, **self.imshow_kwargs)] xoffset, yoffset = self._offsets(xmin, xmax, ymin, ymax) - xlin = numpy.linspace(xmin, xmax, self.resolution, endpoint=False) - ylin = numpy.linspace(ymin, ymax, self.resolution, endpoint=False) - for [i, x], [j, y] in itertools.product(enumerate(xlin), enumerate(ylin[::-1])): - view.append(ax.text(x + xoffset, y + yoffset, "{}".format(X[1][j, i]), ha='center', va='center', **kwargs)) + xlin = numpy.linspace(xmin-xoffset, xmax+xoffset, self.resolution, endpoint=False) + ylin = numpy.linspace(ymin-yoffset, ymax+yoffset, self.resolution, endpoint=False) + for [i, x], [j, y] in itertools.product(enumerate(xlin), enumerate(ylin)): + view.append(ax.text(x, y, "{}".format(X[1][j, i]), ha='center', va='center', **kwargs)) return view def update_view(self, view, X, xmin, xmax, ymin, ymax): super(ImAnnotateController, self).update_view(view[0], X[0], xmin, xmax, ymin, ymax) xoffset, yoffset = self._offsets(xmin, xmax, ymin, ymax) - xlin = numpy.linspace(xmin, xmax, self.resolution, endpoint=False) - ylin = numpy.linspace(ymin, ymax, self.resolution, endpoint=False) - for [[i, x], [j, y]], text in itertools.izip(itertools.product(enumerate(xlin), enumerate(ylin[::-1])), view[1:]): + xlin = numpy.linspace(xmin-xoffset, xmax+xoffset, self.resolution, endpoint=False) + ylin = numpy.linspace(ymin-yoffset, ymax+yoffset, self.resolution, endpoint=False) + for [[i, x], [j, y]], text in itertools.izip(itertools.product(enumerate(xlin), enumerate(ylin)), view[1:]): text.set_x(x + xoffset) text.set_y(y + yoffset) text.set_text("{}".format(X[1][j, i])) diff --git a/GPy/plotting/matplot_dep/plot_definitions.py b/GPy/plotting/matplot_dep/plot_definitions.py index 129bdf66..3744d86b 100644 --- a/GPy/plotting/matplot_dep/plot_definitions.py +++ b/GPy/plotting/matplot_dep/plot_definitions.py @@ -69,11 +69,14 @@ class MatplotlibPlots(AbstractPlottingLibrary): if zlabel is not None: ax.set_zlabel(zlabel) if title is not None: ax.set_title(title) fontdict=dict(family='sans-serif', weight='light', size=9) - if legend >= 1: + if legend is True: + ax.legend(*ax.get_legend_handles_labels()) + elif legend >= 1: #ax.legend(prop=fontdict) legend_ontop(ax, ncol=legend, fontdict=fontdict) if zlim is not None: ax.set_zlim(zlim) + #ax.figure.show() ax.figure.canvas.draw() return plots @@ -121,32 +124,44 @@ class MatplotlibPlots(AbstractPlottingLibrary): return ax.errorbar(X, Y, Z, yerr=error, ecolor=color, label=label, **kwargs) return ax.errorbar(X, Y, yerr=error, ecolor=color, label=label, **kwargs) - def imshow(self, ax, X, extent=None, label=None, plot_function=None, resolution=None, vmin=None, vmax=None, **imshow_kwargs): + def imshow(self, ax, X, extent=None, label=None, vmin=None, vmax=None, **imshow_kwargs): if 'origin' not in imshow_kwargs: imshow_kwargs['origin'] = 'lower' - if plot_function is not None: - return ImshowController(ax, plot_function, extent, resolution=resolution, vmin=vmin, vmax=vmax, **imshow_kwargs) + #xmin, xmax, ymin, ymax = extent + #xoffset, yoffset = (xmax - xmin) / (2. * X.shape[0]), (ymax - ymin) / (2. * X.shape[1]) + #xmin, xmax, ymin, ymax = extent = xmin-xoffset, xmax+xoffset, ymin-yoffset, ymax+yoffset return ax.imshow(X, label=label, extent=extent, vmin=vmin, vmax=vmax, **imshow_kwargs) - - def annotation_heatmap(self, ax, X, annotation, extent, label=None, plot_function=None, resolution=None, imshow_kwargs=None, **annotation_kwargs): + + def imshow_interact(self, ax, plot_function, extent=None, label=None, resolution=None, vmin=None, vmax=None, **imshow_kwargs): + if 'origin' not in imshow_kwargs: + imshow_kwargs['origin'] = 'lower' + return ImshowController(ax, plot_function, extent, resolution=resolution, vmin=vmin, vmax=vmax, **imshow_kwargs) + + def annotation_heatmap(self, ax, X, annotation, extent=None, label=None, imshow_kwargs=None, **annotation_kwargs): imshow_kwargs = imshow_kwargs or {} if 'origin' not in imshow_kwargs: imshow_kwargs['origin'] = 'lower' - if plot_function is not None: - return ImAnnotateController(ax, plot_function, extent, resolution=resolution, imshow_kwargs=imshow_kwargs or {}, **annotation_kwargs) if ('ha' not in annotation_kwargs) and ('horizontalalignment' not in annotation_kwargs): annotation_kwargs['ha'] = 'center' if ('va' not in annotation_kwargs) and ('verticalalignment' not in annotation_kwargs): annotation_kwargs['va'] = 'center' - imshow = self.imshow(ax, X, extent, label, None, resolution, **imshow_kwargs) + imshow = self.imshow(ax, X, extent, label, **imshow_kwargs) + if extent is None: + extent = (0, X.shape[0], 0, X.shape[1]) xmin, xmax, ymin, ymax = extent - xoffset, yoffset = (xmax - xmin) / (2. * resolution), (ymax - ymin) / (2. * resolution) - xlin = np.linspace(xmin, xmax, resolution, endpoint=False) - ylin = np.linspace(ymin, ymax, resolution, endpoint=False) + xoffset, yoffset = (xmax - xmin) / (2. * X.shape[0]), (ymax - ymin) / (2. * X.shape[1]) + xmin, xmax, ymin, ymax = extent = xmin+xoffset, xmax-xoffset, ymin+yoffset, ymax-yoffset + xlin = np.linspace(xmin, xmax, X.shape[0], endpoint=False) + ylin = np.linspace(ymin, ymax, X.shape[1], endpoint=False) annotations = [] - for [i, x], [j, y] in itertools.product(enumerate(xlin), enumerate(ylin[::-1])): - annotations.append(ax.text(x + xoffset, y + yoffset, "{}".format(annotation[j, i]), **annotation_kwargs)) + for [i, x], [j, y] in itertools.product(enumerate(xlin), enumerate(ylin)): + annotations.append(ax.text(x, y, "{}".format(annotation[j, i]), **annotation_kwargs)) return imshow, annotations + + def annotation_heatmap_interact(self, ax, plot_function, extent, label=None, resolution=15, imshow_kwargs=None, **annotation_kwargs): + if 'origin' not in imshow_kwargs: + imshow_kwargs['origin'] = 'lower' + return ImAnnotateController(ax, plot_function, extent, resolution=resolution, imshow_kwargs=imshow_kwargs or {}, **annotation_kwargs) def contour(self, ax, X, Y, C, levels=20, label=None, **kwargs): return ax.contour(X, Y, C, levels=np.linspace(C.min(), C.max(), levels), label=label, **kwargs) diff --git a/GPy/testing/plotting_tests.py b/GPy/testing/plotting_tests.py index 7121e792..2fb7cf70 100644 --- a/GPy/testing/plotting_tests.py +++ b/GPy/testing/plotting_tests.py @@ -145,11 +145,12 @@ def test_classification(): Y = f+np.random.normal(0, .1, f.shape) m = GPy.models.GPClassification(X, Y>Y.mean()) m.optimize() - m.plot() - m.plot(plot_raw=True) - m.plot(plot_raw=False, apply_link=True) + fig, ax = plt.subplots() + m.plot(plot_raw=False, apply_link=False, ax=ax) + fig, ax = plt.subplots() + m.plot(plot_raw=True, apply_link=False, ax=ax) m.plot(plot_raw=True, apply_link=True) - for do_test in _image_comparison(baseline_images=['gp_class_{}'.format(sub) for sub in ["", "raw", 'link', 'raw_link']], extensions=extensions): + for do_test in _image_comparison(baseline_images=['gp_class_{}'.format(sub) for sub in ["likelihood", "raw", 'raw_link']], extensions=extensions): yield (do_test, ) @@ -160,17 +161,17 @@ def test_sparse_classification(): Y = f+np.random.normal(0, .1, f.shape) m = GPy.models.SparseGPClassification(X, Y>Y.mean()) m.optimize() - m.plot() - m.plot(plot_raw=True) - m.plot(plot_raw=False, apply_link=True) + m.plot(plot_raw=False, apply_link=False) + m.plot(plot_raw=True, apply_link=False) m.plot(plot_raw=True, apply_link=True) - for do_test in _image_comparison(baseline_images=['sparse_gp_class_{}'.format(sub) for sub in ["", "raw", 'link', 'raw_link']], extensions=extensions): + for do_test in _image_comparison(baseline_images=['sparse_gp_class_{}'.format(sub) for sub in ["likelihood", "raw", 'raw_link']], extensions=extensions): yield (do_test, ) def test_gplvm(): from ..examples.dimensionality_reduction import _simulate_matern from ..kern import RBF from ..models import GPLVM + np.random.seed(11111) Q = 3 _, _, Ylist = _simulate_matern(5, 1, 1, 100, num_inducing=5, plot_sim=False) Y = Ylist[0] @@ -180,18 +181,18 @@ def test_gplvm(): m.likelihood.variance = .1 m.optimize(messages=0) labels = np.random.multinomial(1, np.random.dirichlet([.3333333, .3333333, .3333333]), size=(m.Y.shape[0])).nonzero()[1] - m.plot_prediction_fit(which_data_ycols=(0,1)) # ignore this test, as plotting is not consistent!! - plt.close('all') m.plot_latent() + m.plot_latent_scatter(projection='3d', labels=labels) m.plot_magnification(labels=labels) m.plot_steepest_gradient_map(resolution=7) - for do_test in _image_comparison(baseline_images=['gplvm_{}'.format(sub) for sub in ["latent", "magnification", 'gradient']], extensions=extensions): + for do_test in _image_comparison(baseline_images=['gplvm_{}'.format(sub) for sub in ["latent", "latent_3d", "magnification", 'gradient']], extensions=extensions): yield (do_test, ) def test_bayesian_gplvm(): from ..examples.dimensionality_reduction import _simulate_matern from ..kern import RBF from ..models import BayesianGPLVM + np.random.seed(11111) Q = 3 _, _, Ylist = _simulate_matern(5, 1, 1, 100, num_inducing=5, plot_sim=False) Y = Ylist[0] @@ -201,12 +202,12 @@ def test_bayesian_gplvm(): m.likelihood.variance = .1 m.optimize(messages=0) labels = np.random.multinomial(1, np.random.dirichlet([.3333333, .3333333, .3333333]), size=(m.Y.shape[0])).nonzero()[1] - m.plot_prediction_fit(which_data_ycols=(0,1)) # ignore this test, as plotting is not consistent!! - plt.close('all') - m.plot_latent() + m.plot_latent_inducing(projection='2d') + m.plot_latent_inducing(projection='3d') + m.plot_latent_scatter(projection='3d') m.plot_magnification(labels=labels) m.plot_steepest_gradient_map(resolution=7) - for do_test in _image_comparison(baseline_images=['bayesian_gplvm_{}'.format(sub) for sub in ["latent", "magnification", 'gradient']], extensions=extensions): + for do_test in _image_comparison(baseline_images=['bayesian_gplvm_{}'.format(sub) for sub in ["inducing", "inducing_3d", "latent_3d", "magnification", 'gradient']], extensions=extensions): yield (do_test, ) if __name__ == '__main__': diff --git a/GPy/testing/plotting_tests/baseline/bayesian_gplvm_gradient.png b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_gradient.png new file mode 100644 index 00000000..8e2d0e38 Binary files /dev/null and b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_gradient.png differ diff --git a/GPy/testing/plotting_tests/baseline/bayesian_gplvm_inducing.png b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_inducing.png new file mode 100644 index 00000000..28a2cb17 Binary files /dev/null and b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_inducing.png differ diff --git a/GPy/testing/plotting_tests/baseline/bayesian_gplvm_inducing_3d.png b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_inducing_3d.png new file mode 100644 index 00000000..503c0503 Binary files /dev/null and b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_inducing_3d.png differ diff --git a/GPy/testing/plotting_tests/baseline/bayesian_gplvm_latent_3d.png b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_latent_3d.png new file mode 100644 index 00000000..19261f60 Binary files /dev/null and b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_latent_3d.png differ diff --git a/GPy/testing/plotting_tests/baseline/bayesian_gplvm_magnification.png b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_magnification.png new file mode 100644 index 00000000..ca7f121e Binary files /dev/null and b/GPy/testing/plotting_tests/baseline/bayesian_gplvm_magnification.png differ diff --git a/GPy/testing/plotting_tests/baseline/gp_class_.png b/GPy/testing/plotting_tests/baseline/gp_class_likelihood.png similarity index 100% rename from GPy/testing/plotting_tests/baseline/gp_class_.png rename to GPy/testing/plotting_tests/baseline/gp_class_likelihood.png diff --git a/GPy/testing/plotting_tests/baseline/gp_class_link.png b/GPy/testing/plotting_tests/baseline/gp_class_link.png deleted file mode 100644 index 7569660f..00000000 Binary files a/GPy/testing/plotting_tests/baseline/gp_class_link.png and /dev/null differ diff --git a/GPy/testing/plotting_tests/baseline/gplvm_gradient.png b/GPy/testing/plotting_tests/baseline/gplvm_gradient.png new file mode 100644 index 00000000..39b84415 Binary files /dev/null and b/GPy/testing/plotting_tests/baseline/gplvm_gradient.png differ diff --git a/GPy/testing/plotting_tests/baseline/gplvm_latent.png b/GPy/testing/plotting_tests/baseline/gplvm_latent.png new file mode 100644 index 00000000..634c2ba8 Binary files /dev/null and b/GPy/testing/plotting_tests/baseline/gplvm_latent.png differ diff --git a/GPy/testing/plotting_tests/baseline/gplvm_latent_3d.png b/GPy/testing/plotting_tests/baseline/gplvm_latent_3d.png new file mode 100644 index 00000000..f23923bf Binary files /dev/null and b/GPy/testing/plotting_tests/baseline/gplvm_latent_3d.png differ diff --git a/GPy/testing/plotting_tests/baseline/gplvm_magnification.png b/GPy/testing/plotting_tests/baseline/gplvm_magnification.png new file mode 100644 index 00000000..6e9144be Binary files /dev/null and b/GPy/testing/plotting_tests/baseline/gplvm_magnification.png differ diff --git a/GPy/testing/plotting_tests/baseline/sparse_gp_class_.png b/GPy/testing/plotting_tests/baseline/sparse_gp_class_likelihood.png similarity index 100% rename from GPy/testing/plotting_tests/baseline/sparse_gp_class_.png rename to GPy/testing/plotting_tests/baseline/sparse_gp_class_likelihood.png diff --git a/GPy/testing/plotting_tests/baseline/sparse_gp_class_link.png b/GPy/testing/plotting_tests/baseline/sparse_gp_class_link.png deleted file mode 100644 index aaf92882..00000000 Binary files a/GPy/testing/plotting_tests/baseline/sparse_gp_class_link.png and /dev/null differ