{ "cells": [ { "cell_type": "markdown", "metadata": {}, "source": [ "# Bayesian Gaussian Process Latent Variable Model (Bayesian GPLVM)\n", "This notebook shows how to use the Bayesian GPLVM model. This is an unsupervised learning method usually used for dimensionality reduction. For an in-depth overview of GPLVMs,see *[1, 2]*." ] }, { "cell_type": "code", "execution_count": 1, "metadata": { "ExecuteTime": { "end_time": "2018-06-19T09:41:37.159594Z", "start_time": "2018-06-19T09:41:36.178948Z" } }, "outputs": [], "source": [ "import gpflow\n", "import numpy as np\n", "\n", "import matplotlib.pyplot as plt\n", "%matplotlib inline" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Data\n", "We are using the \"three phase oil flow\" dataset used initially for demonstrating the Generative Topographic mapping from *[3]*." ] }, { "cell_type": "code", "execution_count": 2, "metadata": { "ExecuteTime": { "end_time": "2018-06-19T09:41:37.164944Z", "start_time": "2018-06-19T09:41:37.160737Z" } }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "Number of points: 100 and Number of dimensions: 12\n" ] } ], "source": [ "data = np.load('./data/three_phase_oil_flow.npz')\n", "Y = data['Y'] # following the GPflow notation we assume this dataset has size [num_data, output_dim]\n", "labels = data['labels'] # integer in [0, 2] indicating to which class the datapoint belongs [num_data,]. Not used for model fitting, only for plotting afterwards.\n", "\n", "print('Number of points: {} and Number of dimensions: {}'.format(Y.shape[0], Y.shape[1]))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Model construction\n", "\n", "We start by initialising the required variables:" ] }, { "cell_type": "code", "execution_count": 3, "metadata": { "ExecuteTime": { "end_time": "2018-06-19T09:42:12.018601Z", "start_time": "2018-06-19T09:41:37.165915Z" }, "scrolled": false }, "outputs": [], "source": [ "latent_dim = 2 # number of latent dimensions\n", "num_inducing = 20 # number of inducing pts\n", "num_data = Y.shape[0] # number of data points\n", "X_mean_init = gpflow.models.PCA_reduce(Y, latent_dim) # Initialise via PCA\n", "X_var_init = np.ones((num_data, latent_dim))\n", "Z_inducing_inputs_init = np.random.permutation(X_mean_init.copy())[:num_inducing] # Pick inducing inputs randomly from dataset initialisation" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We construct a Squared Exponential (SE) kernel operating on the two-dimensional latent space. \n", "The `ARD` parameter stands for Automatic Relevance Determination, which in practice means that\n", "we learn a different lengthscale for each of the input dimensions. See [Manipulating kernels](../advanced/kernels.ipynb) for more information." ] }, { "cell_type": "code", "execution_count": 4, "metadata": {}, "outputs": [], "source": [ "kernel = gpflow.kernels.RBF(latent_dim, ARD=True)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "We have all the necessary ingredients to construct the model. GPflow contains an implementation of the Bayesian GPLVM:" ] }, { "cell_type": "code", "execution_count": 5, "metadata": {}, "outputs": [], "source": [ "m = gpflow.models.BayesianGPLVM(\n", " X_mean=X_mean_init,\n", " X_var=X_var_init,\n", " Y=Y,\n", " kern=kernel,\n", " M=num_inducing,\n", " Z=Z_inducing_inputs_init\n", ")\n", "\n", "# we change the default likelihood variance, which is 1, to 0.01.\n", "m.likelihood.variance = 0.01" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "Next we optimise the created model. Given that this model has a deterministic evidence lower bound (ELBO), we can use SciPy's L-BFGS-B optimiser." ] }, { "cell_type": "code", "execution_count": 6, "metadata": { "ExecuteTime": { "end_time": "2018-06-19T09:42:12.018601Z", "start_time": "2018-06-19T09:41:37.165915Z" }, "scrolled": false }, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "INFO:tensorflow:Optimization terminated with:\n", " Message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", " Objective function value: -173.650389\n", " Number of iterations: 1309\n", " Number of functions evaluations: 1364\n" ] }, { "name": "stderr", "output_type": "stream", "text": [ "INFO:tensorflow:Optimization terminated with:\n", " Message: b'CONVERGENCE: REL_REDUCTION_OF_F_<=_FACTR*EPSMCH'\n", " Objective function value: -173.650389\n", " Number of iterations: 1309\n", " Number of functions evaluations: 1364\n" ] } ], "source": [ "opt = gpflow.train.ScipyOptimizer()\n", "opt.minimize(m, maxiter=gpflow.test_util.notebook_niter(10000))" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Model analysis\n", "GPflow allows you to inspect the learned model hyperparameters." ] }, { "cell_type": "code", "execution_count": 7, "metadata": { "ExecuteTime": { "end_time": "2018-06-19T09:42:12.050803Z", "start_time": "2018-06-19T09:42:12.027308Z" } }, "outputs": [ { "data": { "text/html": [ "
\n", " | class | \n", "prior | \n", "transform | \n", "trainable | \n", "shape | \n", "fixed_shape | \n", "value | \n", "
---|---|---|---|---|---|---|---|
BayesianGPLVM/X_mean | \n", "Parameter | \n", "None | \n", "(none) | \n", "True | \n", "(100, 2) | \n", "True | \n", "[[0.5335858726494092, -3.585462463168241], [-0... | \n", "
BayesianGPLVM/X_var | \n", "Parameter | \n", "None | \n", "+ve | \n", "True | \n", "(100, 2) | \n", "True | \n", "[[0.00025938337775691946, 0.002987260607075345... | \n", "
BayesianGPLVM/feature/Z | \n", "Parameter | \n", "None | \n", "(none) | \n", "True | \n", "(20, 2) | \n", "True | \n", "[[0.723448722354364, 0.0216113992401794], [-1.... | \n", "
BayesianGPLVM/kern/lengthscales | \n", "Parameter | \n", "None | \n", "+ve | \n", "True | \n", "(2,) | \n", "True | \n", "[0.5724092125532642, 2.7044551950083004] | \n", "
BayesianGPLVM/kern/variance | \n", "Parameter | \n", "None | \n", "+ve | \n", "True | \n", "() | \n", "True | \n", "0.7480714466964397 | \n", "
BayesianGPLVM/likelihood/variance | \n", "Parameter | \n", "None | \n", "+ve | \n", "True | \n", "() | \n", "True | \n", "0.005255421275529302 | \n", "