Raw File
{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Making models with GPflow\n",
    "--\n",
    "\n",
    "*James Hensman November 2015, January 2016*\n",
    "\n",
    "GPflow is a Gaussian process framework in python which build on tensorflow. One of the key ingredients in GPflow is the model class, which allows the user to carefully control parameters. This notebook shows how some of these parameter control features work, and how to build your own model with GPflow. First we'll look at\n",
    "\n",
    " - how to view models and parameters\n",
    " - how to set parameter values\n",
    " - how to constrain parameters (e.g. variance > 0)\n",
    " - how to fix model parameters\n",
    " - how to apply priors to parameters\n",
    " - how to optimize models\n",
    "\n",
    "Then we'll show how to build a simple logistic regression model, demonstrating the ease of the parameter framework. For a more complicated example, have a look at the fully_nonstationary_gp notebook (todo).\n",
    "\n",
    "GPy users should feel right at home, but there are some small differences.\n",
    "\n",
    "First, let's deal with the usual notebook boilerplate and make a simple GP regression model. See the Regression notebook for specifics of the model: we just want some parameters to play with."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import GPflow\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "#build a very simple GPR model\n",
    "X = np.random.rand(20,1)\n",
    "Y = np.sin(12*X) + 0.66*np.cos(25*X) + np.random.randn(20,1)*0.01\n",
    "m = GPflow.gpr.GPR(X, Y, kern=GPflow.kernels.Matern32(1) + GPflow.kernels.Linear(1))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Viewing and setting parameters\n",
    "You can display the state of the model in a terminal with `print m` (or `print(m)`), and by simply returning it in a notebook"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table id='parms' width=100%><tr><td>Name</td><td>values</td><td>prior</td><td>constriant</td></tr><tr><td>model.kern.matern32.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.matern32.lengthscales</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.linear.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr><tr><td>model.likelihood.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr></table>"
      ],
      "text/plain": [
       "<GPflow.gpr.GPR at 0x7feeb7c06e90>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This model has four parameters. The kernel is made of the sum of two parts: the RBF kernel has a variance parameter and a lengthscale parameter, the linear kernel only has a variance parameter. There is also a parmaeter controlling the variance of the noise, as part of the likelihood. \n",
    "\n",
    "All of the model variables have been initialized at one. Individual parameters can be accessed in the same way as they are displayed in the table: to see all the parameters that are part of the likelihood, do"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table id='parms' width=100%><tr><td>Name</td><td>values</td><td>prior</td><td>constriant</td></tr><tr><td>likelihood.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr></table>"
      ],
      "text/plain": [
       "<GPflow.likelihoods.Gaussian at 0x7feeb7c06ed0>"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.likelihood"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "This gets more useful with more complex models!"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To set the value of a parameter, just assign."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table id='parms' width=100%><tr><td>Name</td><td>values</td><td>prior</td><td>constriant</td></tr><tr><td>model.kern.matern32.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.matern32.lengthscales</td><td>[ 0.5]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.linear.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr><tr><td>model.likelihood.variance</td><td>[ 0.01]</td><td>None</td><td>+ve</td></tr></table>"
      ],
      "text/plain": [
       "<GPflow.gpr.GPR at 0x7feeb7c06e90>"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.kern.matern32.lengthscales = 0.5\n",
    "m.likelihood.variance = 0.01\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Constraints and fixes\n",
    "\n",
    "GPflow helpfully creates a 'free' vector, containing an unconstrained representation of all the variables. Above, all the variables are constrained positive (see right hand table column), the unconstrained representation is given by $\\alpha = \\log(\\exp(\\theta)-1)$. You can get at this vector with `m.get_free_state()`."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.54132485 -0.43275213  0.54132485 -4.60016602]\n"
     ]
    }
   ],
   "source": [
    "print m.get_free_state()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Constraints are handled by the `Transform` classes. You might prefer the constrain $\\alpha = \\log(\\theta)$: this is easily done by changing setting the transform attribute on a parameter:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.54132485 -0.69314718  0.54132485 -4.60016602]\n"
     ]
    }
   ],
   "source": [
    "m.kern.matern32.lengthscales.transform = GPflow.transforms.Exp()\n",
    "print m.get_free_state()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The second free parameter, representing unconstrained lengthscale has changed (though the lengthscale itself remains the same). Another helpful feature is the ability to fix parameters. This is done by simply setting the fixed boolean to True: a 'fixed' notice appears in the representation and the corresponding variable is removed from the free state."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table id='parms' width=100%><tr><td>Name</td><td>values</td><td>prior</td><td>constriant</td></tr><tr><td>model.kern.matern32.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.matern32.lengthscales</td><td>[ 0.5]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.linear.variance</td><td>[ 1.]</td><td>None</td><td>[FIXED]</td></tr><tr><td>model.likelihood.variance</td><td>[ 0.01]</td><td>None</td><td>+ve</td></tr></table>"
      ],
      "text/plain": [
       "<GPflow.gpr.GPR at 0x7feeb7c06e90>"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.kern.linear.variance.fixed = True\n",
    "m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 0.54132485 -0.69314718 -4.60016602]\n"
     ]
    }
   ],
   "source": [
    "print m.get_free_state()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "To unfix a parameter, just flip the boolean back. The transformation (+ve) reappears."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table id='parms' width=100%><tr><td>Name</td><td>values</td><td>prior</td><td>constriant</td></tr><tr><td>model.kern.matern32.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.matern32.lengthscales</td><td>[ 0.5]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.linear.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr><tr><td>model.likelihood.variance</td><td>[ 0.01]</td><td>None</td><td>+ve</td></tr></table>"
      ],
      "text/plain": [
       "<GPflow.gpr.GPR at 0x7feeb7c06e90>"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.kern.linear.variance.fixed = False\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Priors\n",
    "\n",
    "Priors are set just like transforms and fixes, using members of the `GPflow.priors.` module. Let's set a Gamma prior on the RBF-variance."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table id='parms' width=100%><tr><td>Name</td><td>values</td><td>prior</td><td>constriant</td></tr><tr><td>model.kern.matern32.variance</td><td>[ 1.]</td><td>Ga([ 2.],[ 3.])</td><td>+ve</td></tr><tr><td>model.kern.matern32.lengthscales</td><td>[ 0.5]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.linear.variance</td><td>[ 1.]</td><td>None</td><td>+ve</td></tr><tr><td>model.likelihood.variance</td><td>[ 0.01]</td><td>None</td><td>+ve</td></tr></table>"
      ],
      "text/plain": [
       "<GPflow.gpr.GPR at 0x7feeb7c06e90>"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.kern.matern32.variance.prior = GPflow.priors.Gamma(2,3)\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Optimization\n",
    "\n",
    "Optimization is done by calling `m.optimize()` which has optional arguments that are passed through to `scipy.optimize.minimize` (we minimize the negative log-likelihood). Variables that have priors are MAP-estimated, others are ML, i.e. we add the log prior to the log likelihood."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "compiling tensorflow function...\n",
      "done\n",
      "optimization terminated, setting model state\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table id='parms' width=100%><tr><td>Name</td><td>values</td><td>prior</td><td>constriant</td></tr><tr><td>model.kern.matern32.variance</td><td>[ 1.72070801]</td><td>Ga([ 2.],[ 3.])</td><td>+ve</td></tr><tr><td>model.kern.matern32.lengthscales</td><td>[ 0.16981122]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.linear.variance</td><td>[  4.80524329e-08]</td><td>None</td><td>+ve</td></tr><tr><td>model.likelihood.variance</td><td>[ 0.]</td><td>None</td><td>+ve</td></tr></table>"
      ],
      "text/plain": [
       "<GPflow.gpr.GPR at 0x7feeb7c06e90>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.optimize()\n",
    "m"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Building new models\n",
    "\n",
    "To build new models, you'll need to inherrit from `GPflow.model.Model`. Parameters are instantiated with `GPflow.param.Param`. You may also be interested in `GPflow.param.Parameterized` which acts as a 'container' of `Param`s (e.g. kernels are Parameterized). \n",
    "\n",
    "In this very simple demo, we'll implement linear multiclass classification. There will be two parameters: a weight matrix and a 'bias' (offset). The key thing to implement is the `build_likelihood` method, which should return a tensorflow scalar representing the (log) likelihood. Param objects can be used inside `build_likelihood`: they will appear as appropriate (unconstrained) tensors. "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "class LinearMulticlass(GPflow.model.Model):\n",
    "    def __init__(self, X, Y):\n",
    "        GPflow.model.Model.__init__(self) # always call the parent constructor\n",
    "        self.X = X.copy() # X is a numpy array of inputs\n",
    "        self.Y = Y.copy() # Y is a 1-of-k representation of the labels\n",
    "        \n",
    "        self.num_data, self.input_dim = X.shape\n",
    "        _, self.num_classes = Y.shape\n",
    "        \n",
    "        #make some parameters\n",
    "        self.W = GPflow.param.Param(np.random.randn(self.input_dim, self.num_classes))\n",
    "        self.b = GPflow.param.Param(np.random.randn(self.num_classes))\n",
    "       \n",
    "        # ^^ You must make the parameters attributes of the class for\n",
    "        # them to be picked up by the model. i.e. this won't work:\n",
    "        #\n",
    "        # W = GPflow.param.Param(...    <-- must be self.W\n",
    "    \n",
    "    def build_likelihood(self): # takes no arguments\n",
    "        \n",
    "        p = tf.nn.softmax(tf.matmul(self.X, self.W) + self.b) # Param variables are used as tensorflow arrays. \n",
    "        return tf.reduce_sum(tf.log(p) * self.Y) # be sure to return a scalar"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "...and that's it. let's build a really simple demo to show that it works."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x7feeaee171d0>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nmdfLKVimQgAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7feeb7c060d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "X = np.vstack([np.random.randn(10,2) + [2,2],\n",
    "               np.random.randn(10,2) + [-2,2],\n",
    "               np.random.randn(10,2) + [2,-2]])\n",
    "Y = np.repeat(np.eye(3), 10, 0)\n",
    "\n",
    "from matplotlib import pyplot as plt\n",
    "%matplotlib inline\n",
    "import matplotlib\n",
    "matplotlib.rcParams['figure.figsize'] = (12,6)\n",
    "matplotlib.style.use('ggplot')\n",
    "\n",
    "\n",
    "plt.scatter(X[:,0], X[:,1], 100, np.argmax(Y, 1), lw=2, cmap=plt.cm.viridis)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/html": [
       "<table id='parms' width=100%><tr><td>Name</td><td>values</td><td>prior</td><td>constriant</td></tr><tr><td>model.b</td><td>[-0.15227413 -0.32901366 -0.13460059]</td><td>None</td><td>(none)</td></tr><tr><td>model.W</td><td>[[-1.89538857 -0.61907231  0.33386851]</br> [-0.7726943   0.38047682 -0.62809918]]</td><td>None</td><td>(none)</td></tr></table>"
      ],
      "text/plain": [
       "<__main__.LinearMulticlass at 0x7feeaeee6090>"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = LinearMulticlass(X, Y)\n",
    "m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "compiling tensorflow function...\n",
      "done\n",
      "optimization terminated, setting model state\n"
     ]
    },
    {
     "data": {
      "text/html": [
       "<table id='parms' width=100%><tr><td>Name</td><td>values</td><td>prior</td><td>constriant</td></tr><tr><td>model.b</td><td>[ 14.56482929 -29.13858934  13.95787167]</td><td>None</td><td>(none)</td></tr><tr><td>model.W</td><td>[[  8.37398774 -18.77191408   8.21733397]</br> [ -6.06497721  15.28041936 -10.23575881]]</td><td>None</td><td>(none)</td></tr></table>"
      ],
      "text/plain": [
       "<__main__.LinearMulticlass at 0x7feeaeee6090>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.optimize()\n",
    "m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {
    "collapsed": false
   },
   "outputs": [],
   "source": [
    "xx, yy = np.mgrid[-4:4:200j, -4:4:200j]\n",
    "X_test = np.vstack([xx.flatten(), yy.flatten()]).T\n",
    "f_test = np.dot(X_test, m.W._array) + m.b._array\n",
    "p_test = np.exp(f_test)\n",
    "p_test /= p_test.sum(1)[:,None]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x7feeac336f90>"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nZ6dc1+16uIYxstbKWqswDJOOh35EEQYAAFDXzXO/vCHOdd0E06ASuFkOAAAAmUQRBgAAQCZRhAEA\nAJBJFGEAAABkEkUYAAAAmUQRBgAAQCZRhAEAAJBJFGEAAABkEkUYAAAAmUQRBgAAQCZRhAEAAJBJ\nFGEAAABkkrHW2qRDAAAAAJWWuSvCW7duTTrCgMGsysesysesysesysesysesysesyjdQZ5W5IgwA\nAABIFGEAAABklPvII488knSISrv44ouTjjBgMKvyMavyMavyMavyMavyMavyMavyDcRZcbMcAAAA\nMomlEQAAAMgkijAAAAAyyUs6QJK2b9+uzZs364UXXtCwYcOSjpNKr776qpqbm2WMUXV1tZYsWaLh\nw4cnHSuVNm/erM8++0ye52n06NG6++67VVVVlXSsVNqxY4dee+01HTp0SGvXrtXll1+edKTU2b17\nt1566SVZazVjxgzdcsstSUdKpQ0bNujzzz9XdXW1nnzyyaTjpFpra6vWr1+vY8eOyRijWbNmae7c\nuUnHSqVisaiVK1cqDENFUaSpU6dq/vz5ScdKrTiO9eCDD6qmpkYPPPBA0nF+k0zeLCd1fUN49913\nFUWRZs+eLd/3k46USvX19Zo7d65mz56tkydPaseOHZo8eXLSsVJr8eLFmjNnjr7++mt99dVXuuqq\nq5KOlEqO42jatGk6ePCgrr76ao0YMSLpSKkSx7HWrFmjFStWaN68edq4caMaGhp04YUXJh0tdS64\n4ALNnDlTO3fu1E033ZR0nFQLgkATJ07UwoULdeONN+q5557TpEmT+Ht1Gq7rqrGxUTfffLNmz56t\nV155RZdeeqlqamqSjpZK3X0qDEM1NjYmHec3yezSiE2bNmnx4sVJx0i9IUOGlH5dKBRkjEkwTbpN\nmjRJjtP1JTVhwgS1trYmnCi9xo4dqzFjxiQdI7X279+vMWPGaNSoUfI8T9OmTdOuXbuSjpVKEydO\n1NChQ5OOMSAMHz5cdXV1krq+t48bN05tbW3JhkqxfD4vqevqcBRFCadJr9bWVrW0tGjWrFlJRzkn\nmVwa0dzcrJEjR6q2tjbpKAPCli1b9NFHH2no0KFauXJl0nEGhA8++EDTpk1LOgYGqLa2No0cObL0\nuqamRvv3708wEQabo0eP6sCBA5owYULSUVIrjmMtW7ZMR44c0Zw5c1RfX590pFTqvrDY3t6edJRz\nMmiL8KpVq3Ts2LHSa2utjDFqamrStm3btHz58h7HsuxMs7ruuuvU1NSkpqYmvfXWW3rvvfe0YMGC\nBNMm62yzkqQ333yz9GO1LCtnVgAqr7OzU08//bRuu+22Hj/1Q0+O4+jxxx9Xe3u7nnjiCR06dEjj\nx49POlaqdK/Pr6ur0549ewZknxq0RXjFihWnff/Bgwd19OhR3XfffbLWqq2tTcuWLdOaNWtUXV1d\n4ZTp0NusTtXY2Ki1a9dmugifbVYffvihWlpa9PDDD1coUXqV+/cKv1ZTU6Mffvih9LqtrY21iegT\nURTpqaee0vTp03X99dcnHWdAqKqqUkNDg3bv3k0RPsW+ffvU3NyslpYWBUGgjo4OrV+/XkuXLk06\nWtkGbRHuTW1trZ5//vnS6yVLlmjdunXsGtGLw4cP65JLLpEk7dq1S+PGjUs4UXrt3r1b77zzjh59\n9FHlcrmk42AAq6+v1+HDh/X9999rxIgR+vTTT3XPPfckHSu1rLUD8kpUEjZs2KDx48ezW8RZHD9+\nXJ7nqaqqSkEQ6Msvv9S8efOSjpU6ixYt0qJFiyRJe/fu1fbt2wdUCZYyWIRPxc1fZ/byyy/ru+++\nkzFGo0aN0p133pl0pNR68cUXFYahVq9eLanrhrk77rgj4VTptHPnTm3cuFHHjx/XY489prq6Oj30\n0ENJx0oNx3F0++23a/Xq1bLWaubMmVyJ6sUzzzyjvXv36qefftJdd92lBQsWaMaMGUnHSqV9+/bp\n448/Vm1tre6//34ZY3TrrbfqmmuuSTpa6vz444969tlnFcexrLW64YYbdO211yYdC/2ARywDAAAg\nkzK7fRoAAACyjSIMAACATKIIAwAAIJMowgAAAMgkijAAAAAyiSIMAACATKIIAwAAIJMowgAAAMik\n/wMDmFWGmlpHKAAAAABJRU5ErkJggg==\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7feeac3413d0>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "for i in range(3):\n",
    "    plt.contour(xx, yy, p_test[:,i].reshape(200,200), [0.5], colors='k', linewidths=1)\n",
    "plt.scatter(X[:,0], X[:,1], 100, np.argmax(Y, 1), lw=2, cmap=plt.cm.viridis)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "That concludes the new model example and this notebook. You might want to convince yourself that the `LinearMulticlass` model and its parameters have all the functionality demonstrated above. You could also add some priors and run Hamiltonian Monte Carlo using `m.sample`. See the sparse_MCMC notebook for details of running the sampler."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 2",
   "language": "python",
   "name": "python2"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 2
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython2",
   "version": "2.7.11"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 0
}
back to top