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 0x7f41fa6490d0>"
      ]
     },
     "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 0x7f41fa649110>"
      ]
     },
     "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": 5,
   "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 0x7f41fa6490d0>"
      ]
     },
     "execution_count": 5,
     "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": 6,
   "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": 7,
   "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": 8,
   "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 0x7f41fa6490d0>"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.kern.linear.variance.fixed = True\n",
    "m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "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": 10,
   "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 0x7f41fa6490d0>"
      ]
     },
     "execution_count": 10,
     "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": 11,
   "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 0x7f41fa6490d0>"
      ]
     },
     "execution_count": 11,
     "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": 12,
   "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.60935952]</td><td>Ga([ 2.],[ 3.])</td><td>+ve</td></tr><tr><td>model.kern.matern32.lengthscales</td><td>[ 0.14710273]</td><td>None</td><td>+ve</td></tr><tr><td>model.kern.linear.variance</td><td>[  6.61494604e-08]</td><td>None</td><td>+ve</td></tr><tr><td>model.likelihood.variance</td><td>[  5.11135070e-05]</td><td>None</td><td>+ve</td></tr></table>"
      ],
      "text/plain": [
       "<GPflow.gpr.GPR at 0x7f41fa6490d0>"
      ]
     },
     "execution_count": 12,
     "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": 13,
   "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": 14,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x7f41f042ac50>"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\nrSkGAAAAahWhGAAAAJlXtgvtdsSdd96phx56KNnX+IwzztC+++5bySFVtfvuu0+33nqrbrrpJg0b\nNqzSw6k6d9xxhxYuXChjjEaMGKELLrhAI0eOrPSwqtKtt96qZ555Ro7jaJdddtH555+vxsbGSg+r\n6jzxxBO68847tWLFCl111VWaMmVKpYdUVRYvXqybb75ZcRxr9uzZOuWUUyo9pKp0ww036Nlnn9WI\nESP0ne98p9LDqVqrV6/W/PnztW7dOhljdPTRR+uEE06o9LCqku/7mjt3roIgUBiGOvTQQ/XRj360\n0sOqWlEU6bLLLlNTU5MuueSSXvtVNBRL0kknnaSTTjqp0sOoeqtXr9aSJUs0ZsyYSg+lap188sk6\n/fTTJUn333+/7rzzTp177rkVHlV12nvvvXXmmWfKsizddtttuueee3TmmWdWelhVZ9KkSbrooot0\n4403VnooVSeKIt1000264oorNGrUKF122WU66KCDNH78+EoPrerMnj1bxx9/PLs09cG2bX3yk5/U\n5MmT1dXVpUsuuUT77LMPz6keuK6ruXPnKpfLKYoiXX755dpvv/00derUSg+tKv3mN7/R+PHj1dnZ\nuc1+FV8+wXV+6dxyyy0666yzKj2MqtbQ0JB8nc/n2Tt7G/bee29ZVvf//tOmTdPq1asrPKLq1Nzc\nrF133bXSw6hKL7/8snbddVeNHTtWjuNo1qxZevrppys9rKo0ffp0DR06tNLDqHojR47U5MmTJXW/\nno8fP15r1qyp7KCqWC6Xk9Q9axyGYYVHU71Wr16tRYsW6eijj+6zb8Vnih944AH94Q9/0O67765P\nfOITfITbg4ULF2r06NGaNGlSpYdS9W6//XY9+uijGjp0qObOnVvp4dSEhx9+WLNmzar0MFBj1qxZ\no9GjRye3m5qa9PLLL1dwRKgnb731ll599VVNmzat0kOpWlEU6dJLL9Wbb76pY489llniXhQnFTs6\nOvrsO+CheN68eVq3bl1yO45jGWM0Z84cHXvssTrttNNkjNHtt9+uW265Reedd95AD6kqbatOd999\nt772ta+VtGXVtup04IEHas6cOZozZ47uuece3X///Wptba3gaCurr1pJ0l133SXbtnX44YdXapgV\nl6ZOAAZPV1eXvvvd7+rss88u+QQQpSzL0jXXXKOOjg5de+21WrFihSZMmFDpYVWV4lr+yZMnq62t\nrc/8NOCh+PLLL0/V7+ijj9bVV189wKOpXr3Vafny5Xrrrbf05S9/WXEca82aNbr00kv1rW99K7lA\nMUvSPp8OP/xwXXXVVZkOxX3V6pFHHtGiRYt0xRVXDNKIqlPa5xRKNTU16e23305ur1mzRk1NTRUc\nEepBGIa67rrrdOSRR+qggw6q9HBqQmNjo1paWrR48WJC8T9ZunSpFi5cqEWLFqlQKKizs1Pz58/X\nhRde2GP/ii6fWLt2bbI7wJNPPqmJEydWcjhVadKkSfrxj3+c3L7gggt09dVXs/tED1auXKlx48ZJ\nkp5++mkuztiGxYsX695779U3vvENua5b6eGgBk2dOlUrV67UqlWrNGrUKD3++OP6/Oc/X+lhVa04\njjP9KV9aN9xwgyZMmMCuE31Yv369HMdRY2OjCoWCnnvuOZ188smVHlbVOfPMM5OLyF944QXdd999\nvQZiqcKh+NZbb9WyZctkjNHYsWP16U9/upLDqQlcPNa72267TW+88UbyfGLnid795Cc/URAEuvLK\nKyV1X2z3qU99qsKjqj5PPfWUfvrTn2r9+vX69re/rcmTJ+srX/lKpYdVFSzL0jnnnKMrr7xScRzr\nAx/4ALNUvbj++uv1wgsvaMOGDTrvvPPU2tqq2bNnV3pYVWfp0qV67LHHNGnSJF188cUyxrBVay/W\nrl2rH/7wh4qiSHEca+bMmdp///0rPayaxzHPAAAAyLyKb8kGAAAAVBqhGAAAAJlHKAYAAEDmEYoB\nAACQeYRiAAAAZB6hGAAAAJlHKAYAAEDmEYoBAACQef8fxfWFKLb8VlIAAAAASUVORK5CYII=\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f41f0735fd0>"
      ]
     },
     "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": 15,
   "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.63834543 -1.20815029 -1.82042359]</td><td>None</td><td>(none)</td></tr><tr><td>model.W</td><td>[[-0.92923651 -1.69574692  1.05649427]</br> [-0.68789544 -0.81365612 -0.73554506]]</td><td>None</td><td>(none)</td></tr></table>"
      ],
      "text/plain": [
       "<__main__.LinearMulticlass at 0x7f41f0735150>"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m = LinearMulticlass(X, Y)\n",
    "m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "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>[ 0.26730288 -5.73999646  3.08246513]</td><td>None</td><td>(none)</td></tr><tr><td>model.W</td><td>[[  5.83909396 -13.55470198   6.14711886]</br> [  3.83778751   3.03005646  -9.10494059]]</td><td>None</td><td>(none)</td></tr></table>"
      ],
      "text/plain": [
       "<__main__.LinearMulticlass at 0x7f41f0735150>"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "m.optimize()\n",
    "m"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "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.value) + m.b._array\n",
    "p_test = np.exp(f_test)\n",
    "p_test /= p_test.sum(1)[:,None]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<matplotlib.collections.PathCollection at 0x7f41f04a7d50>"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7f41f04e72d0>"
      ]
     },
     "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