[density] plot added

This commit is contained in:
mzwiessele 2015-10-01 20:06:31 +01:00
parent 6b6ca60bb5
commit d8243383b4
3 changed files with 186 additions and 0 deletions

View file

@ -595,6 +595,45 @@ class GP(Model):
data_symbol=data_symbol, predict_kw=predict_kw,
plot_training_data=plot_training_data, samples_y=samples_y, apply_link=apply_link, **kw)
def plot_density(self, levels=20, plot_limits=None, fignum=None, ax=None,
fixed_inputs=[], plot_raw=False, edgecolor='none', facecolor='#3465a4',
predict_kw=None,Y_metadata=None,
apply_link=False, resolution=200, **patch_kw):
"""
Plot the posterior density of the GP.
- In one dimension, the function is plotted with a shaded gradient, visualizing the density of the posterior.
- Only implemented for one dimension, for higher dimensions use `plot`.
:param levels: number of levels to plot in the density plot. This is a number between 1 and 100. 1 corresponds to the normal plot_fit.
:type levels: int
:param plot_limits: The limits of the plot. If 1D [xmin,xmax], if 2D [[xmin,ymin],[xmax,ymax]]. Defaluts to data limits
:type plot_limits: np.array
:param fixed_inputs: a list of tuple [(i,v), (i,v)...], specifying that input index i should be set to value v.
:type fixed_inputs: a list of tuples
:param resolution: the number of intervals to sample the GP on. Defaults to 200 in 1D and 50 (a 50x50 grid) in 2D
:type resolution: int
:param edgecolor: color of line to plot [Tango.colorsHex['darkBlue']]
:type edgecolor: color either as Tango.colorsHex object or character ('r' is red, 'g' is green) as is standard in matplotlib
:param facecolor: color of fill [Tango.colorsHex['lightBlue']]
:type facecolor: color either as Tango.colorsHex object or character ('r' is red, 'g' is green) as is standard in matplotlib
:param Y_metadata: additional data associated with Y which may be needed
:type Y_metadata: dict
:param apply_link: if there is a link function of the likelihood, plot the link(f*) rather than f*, when plotting posterior samples f
:type apply_link: boolean
:param resolution: resolution of interpolation (how many points to interpolate of the posterior).
:type resolution: int
:param: patch_kw: the keyword arguments for the patchcollection fill.
"""
assert "matplotlib" in sys.modules, "matplotlib package has not been imported."
from ..plotting.matplot_dep import models_plots
return models_plots.plot_density(self, levels, plot_limits, fignum, ax,
fixed_inputs, plot_raw=plot_raw,
Y_metadata=Y_metadata,
predict_kw=predict_kw,
apply_link=apply_link,
edgecolor=edgecolor, facecolor=facecolor,
**patch_kw)
def plot_data(self, which_data_rows='all',
which_data_ycols='all', visible_dims=None,

View file

@ -40,6 +40,88 @@ def gpplot(x, mu, lower, upper, edgecol='#3300FF', fillcol='#33CCFF', ax=None, f
return plots
def plot_gradient_fill(ax, x, percentiles, **kwargs):
plots = []
#here's the box
if 'linewidth' not in kwargs:
kwargs['linewidth'] = 0.5
if not 'alpha' in kwargs.keys():
kwargs['alpha'] = 1./(len(percentiles))
# pop where from kwargs
where = kwargs.pop('where') if 'where' in kwargs else None
# pop interpolate, which we actually do not do here!
if 'interpolate' in kwargs: kwargs.pop('interpolate')
def pairwise(inlist):
l = len(inlist)
for i in range(int(np.ceil(l/2.))):
yield inlist[:][i], inlist[:][(l-1)-i]
polycol = []
for y1, y2 in pairwise(percentiles):
import matplotlib.mlab as mlab
# Handle united data, such as dates
ax._process_unit_info(xdata=x, ydata=y1)
ax._process_unit_info(ydata=y2)
# Convert the arrays so we can work with them
from numpy import ma
x = ma.masked_invalid(ax.convert_xunits(x))
y1 = ma.masked_invalid(ax.convert_yunits(y1))
y2 = ma.masked_invalid(ax.convert_yunits(y2))
if y1.ndim == 0:
y1 = np.ones_like(x) * y1
if y2.ndim == 0:
y2 = np.ones_like(x) * y2
if where is None:
where = np.ones(len(x), np.bool)
else:
where = np.asarray(where, np.bool)
if not (x.shape == y1.shape == y2.shape == where.shape):
raise ValueError("Argument dimensions are incompatible")
mask = reduce(ma.mask_or, [ma.getmask(a) for a in (x, y1, y2)])
if mask is not ma.nomask:
where &= ~mask
polys = []
for ind0, ind1 in mlab.contiguous_regions(where):
xslice = x[ind0:ind1]
y1slice = y1[ind0:ind1]
y2slice = y2[ind0:ind1]
if not len(xslice):
continue
N = len(xslice)
X = np.zeros((2 * N + 2, 2), np.float)
# the purpose of the next two lines is for when y2 is a
# scalar like 0 and we want the fill to go all the way
# down to 0 even if none of the y1 sample points do
start = xslice[0], y2slice[0]
end = xslice[-1], y2slice[-1]
X[0] = start
X[N + 1] = end
X[1:N + 1, 0] = xslice
X[1:N + 1, 1] = y1slice
X[N + 2:, 0] = xslice[::-1]
X[N + 2:, 1] = y2slice[::-1]
polys.append(X)
polycol.extend(polys)
from matplotlib.collections import PolyCollection
plots.append(PolyCollection(polycol, **kwargs))
ax.add_collection(plots[-1], autolim=True)
ax.autoscale_view()
return plots
def gperrors(x, mu, lower, upper, edgecol=None, ax=None, fignum=None, **kwargs):
_, axes = ax_default(fignum, ax)

View file

@ -9,6 +9,7 @@ from ...models.sparse_gp_coregionalized_regression import SparseGPCoregionalized
from scipy import sparse
from ...core.parameterization.variational import VariationalPosterior
from matplotlib import pyplot as plt
from GPy.plotting.matplot_dep.base_plots import plot_gradient_fill
def plot_data(model, which_data_rows='all',
@ -299,6 +300,70 @@ def plot_fit(model, plot_limits=None, which_data_rows='all',
raise NotImplementedError("Cannot define a frame with more than two input dimensions")
return plots
def plot_density(model, levels=20, plot_limits=None, fignum=None, ax=None,
fixed_inputs=[], plot_raw=False, edgecolor='none', facecolor='#3465a4',
predict_kw=None,Y_metadata=None,
apply_link=False, resolution=200, **patch_kwargs):
#deal with optional arguments
if ax is None:
fig = plt.figure(num=fignum)
ax = fig.add_subplot(111)
if hasattr(model, 'has_uncertain_inputs') and model.has_uncertain_inputs():
X = model.X.mean
else:
X = model.X
Y = model.Y
if sparse.issparse(Y): Y = Y.todense().view(np.ndarray)
if predict_kw is None:
predict_kw = {}
#work out what the inputs are for plotting (1D or 2D)
fixed_dims = np.array([i for i,v in fixed_inputs])
free_dims = np.setdiff1d(np.arange(model.input_dim),fixed_dims)
plots = {}
#one dimensional plotting
if len(free_dims) == 1:
#define the frame on which to plot
Xnew, xmin, xmax = x_frame1D(X[:,free_dims], plot_limits=plot_limits, resolution=resolution)
Xgrid = np.empty((Xnew.shape[0],model.input_dim))
Xgrid[:,free_dims] = Xnew
for i,v in fixed_inputs:
Xgrid[:,i] = v
percs = np.linspace(2.5, 97.5, levels*2)
#make a prediction on the frame and plot it
if plot_raw:
raise NotImplementedError('What to do? What to do?')
#===================================================================
# m, v = model._raw_predict(Xgrid, **predict_kw)
# percentiles = model.predict_quantiles(Xgrid, )
# if apply_link:
# lower = model.likelihood.gp_link.transf(m - 2*np.sqrt(v))
# upper = model.likelihood.gp_link.transf(m + 2*np.sqrt(v))
# #Once transformed this is now the median of the function
# m = model.likelihood.gp_link.transf(m)
# else:
# lower = m - 2*np.sqrt(v)
# upper = m + 2*np.sqrt(v)
#===================================================================
else:
if isinstance(model,GPCoregionalizedRegression) or isinstance(model,SparseGPCoregionalizedRegression):
extra_data = Xgrid[:,-1:].astype(np.int)
if Y_metadata is None:
Y_metadata = {'output_index': extra_data}
else:
Y_metadata['output_index'] = extra_data
percentiles = [i[:, 0] for i in model.predict_quantiles(Xgrid, percs, Y_metadata=Y_metadata, **predict_kw)]
patch_kwargs['facecolor'] = facecolor
patch_kwargs['edgecolor'] = edgecolor
plots['density'] = plot_gradient_fill(ax, Xgrid[:, 0], percentiles, **patch_kwargs)
else:
raise NotImplementedError('Only 1D density plottable.')
return plots
def plot_fit_f(model, *args, **kwargs):
"""
Plot the GP's view of the world, where the data is normalized and before applying a likelihood.