diff --git a/docs/source/notebooks/best-api.ipynb b/docs/source/notebooks/best-api.ipynb new file mode 100644 index 0000000000..0b89100086 --- /dev/null +++ b/docs/source/notebooks/best-api.ipynb @@ -0,0 +1,398 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Introduction\n", + "\n", + "This notebook is intended as an introduction to the BEST model available as a \"default model\" in PyMC3.\n", + "\n", + "John Kruschke introduced the BEST model in 2013 as a way to show how Bayesian estimation can provide a superior way of summarizing a two-sample comparison, i.e. treatment vs. control. Here, I have done the necessary software engineering to extend it to a multi-sample comparison, i.e. multiple treatments vs. control." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "import pymc3 as pm\n", + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt\n", + "import seaborn as sns\n", + "\n", + "sns.set_style('white')\n", + "\n", + "from pymc3.models.best import BEST\n", + "\n", + "%load_ext autoreload\n", + "%autoreload 2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We will first start by generating some synthetic data. Here, we are assuming that there are:\n", + "\n", + "- 10 treatments (including the control)\n", + "- 4 replicate measurements each" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": { + "collapsed": false + }, + "outputs": [], + "source": [ + "n_treatments = 10\n", + "n_replicates = 4\n", + "means = np.random.randint(low=10, high=50, size=n_treatments)\n", + "sigmas = np.random.random(size=n_treatments) * 3\n", + "\n", + "data = []\n", + "indices = []\n", + "for idx, tmt in enumerate(range(n_treatments)):\n", + " for rep in range(n_replicates):\n", + " data.append(np.random.normal(loc=means[idx], scale=sigmas[idx]))\n", + " indices.append(idx)\n", + "\n", + "# Cast as a numpy array for convenience.\n", + "data = np.array(data)\n", + "indices = np.array(indices)" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([ 21.51804962, 19.17406042, 16.51748568, 21.1254247 ,\n", + " 15.98845044, 16.01062808, 16.03388728, 15.98152944,\n", + " 11.55567225, 14.61522226, 13.82675371, 16.480401 ,\n", + " 38.81548662, 36.42769763, 38.78238235, 40.44465029,\n", + " 15.08502181, 14.0348035 , 10.01033688, 15.71514256,\n", + " 30.59898852, 29.99291836, 27.70848322, 27.48400447,\n", + " 24.09975511, 23.82401982, 21.77444056, 21.37802053,\n", + " 29.6104827 , 30.32411378, 35.00388415, 30.21269507,\n", + " 33.38952711, 35.06357773, 32.66744472, 32.57797696,\n", + " 39.77090017, 35.94262292, 38.0648428 , 37.21283409])" + ] + }, + "execution_count": 3, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "data" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/plain": [ + "array([0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5, 5,\n", + " 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 8, 9, 9, 9, 9])" + ] + }, + "execution_count": 4, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "indices" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The BEST model accepts a `pandas` DataFrame object, and assumes that the data are structured as such:\n", + "\n", + "- Each row is one measurement\n", + "- Replicates are indicated by an identifying \"name\" (e.g. \"control\", \"treatment_1\", \"my_treatment_name\") etc.\n", + "- The replicate measurements do not necessarily have to be in order.\n", + "\n", + "While in this example we only use 10 different treatments, in principle it is possible to go much higher, even on the order of ~103 to ~104, as might be the case with replicate high throughput measurements." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
treatmentsmeasurements
0021.518050
1019.174060
2016.517486
3021.125425
4115.988450
5116.010628
6116.033887
7115.981529
8211.555672
9214.615222
\n", + "
" + ], + "text/plain": [ + " treatments measurements\n", + "0 0 21.518050\n", + "1 0 19.174060\n", + "2 0 16.517486\n", + "3 0 21.125425\n", + "4 1 15.988450\n", + "5 1 16.010628\n", + "6 1 16.033887\n", + "7 1 15.981529\n", + "8 2 11.555672\n", + "9 2 14.615222" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "df = pd.DataFrame()\n", + "df['treatments'] = indices\n", + "df['measurements'] = data\n", + "df.head(10)" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": { + "collapsed": false, + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Sample name 0 has the index 0\n", + "Sample name 1 has the index 1\n", + "Sample name 2 has the index 2\n", + "Sample name 3 has the index 3\n", + "Sample name 4 has the index 4\n", + "Sample name 5 has the index 5\n", + "Sample name 6 has the index 6\n", + "Sample name 7 has the index 7\n", + "Sample name 8 has the index 8\n", + "Sample name 9 has the index 9\n" + ] + } + ], + "source": [ + "b = BEST(data=df, sample_col='treatments', output_col='measurements', baseline_name=0)" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": { + "collapsed": false, + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Iteration 0 [0%]: ELBO = -1538.66\n", + "Iteration 50000 [10%]: Average ELBO = -333.06\n", + "Iteration 100000 [20%]: Average ELBO = -169.59\n", + "Iteration 150000 [30%]: Average ELBO = -133.72\n", + "Iteration 200000 [40%]: Average ELBO = -121.73\n", + "Iteration 250000 [50%]: Average ELBO = -121.09\n", + "Iteration 300000 [60%]: Average ELBO = -121.04\n", + "Iteration 350000 [70%]: Average ELBO = -121.07\n", + "Iteration 400000 [80%]: Average ELBO = -121.03\n", + "Iteration 450000 [90%]: Average ELBO = -121.09\n", + "Interrupted at 450113 [90%]: Average ELBO = -121.09\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "100%|██████████| 2000/2000 [00:00<00:00, 7032.20it/s]\n" + ] + } + ], + "source": [ + "b.fit(n_steps=500000)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Call the `plot_elbo()` function to visually check that the ADVI steps have converged." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAArwAAAHcCAYAAAA0pnmEAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAAPYQAAD2EBqD+naQAAIABJREFUeJzs3Xd4VGXexvF7JmUS0jsJBAgtoQQIhCaELggrKAuoKLCi\niA1Qii4IiAU77rq89sZaWMvuuqzddWXVlUVUQDoiBCkCoRoChCQkef9AhgyZmcwkM5nJyfdzXV4y\n5zxz5pd+z3OeYiovLy8XAAAAYFBmXxcAAAAAeBOBFwAAAIZG4AUAAIChEXgBAABgaAReAAAAGBqB\nFwAAAIZG4AUAAIChEXgBAABgaAReAAAAGJpHA29BQYHmzp2rXr16qWfPnpozZ44KCgoctt+7d68m\nTpyorKwsXXrppVqxYoUnywEAAAA8G3jvvvtubdu2TS+88IJefvll7dixQ/Pnz3fY/tZbb1ViYqL+\n/ve/a8SIEZoyZYoOHDjgyZIAAABQz5nKy8vLPXGhwsJCde3aVW+88YYyMzMlSd9//73GjRunNWvW\nKDg42Kb9ypUrdeutt2rlypWyWCySpIkTJ6pLly6aMmWKJ0oCAAAAPNfDazab9eyzzyojI8N6rLy8\nXKWlpTp16lSl9uvXr1e7du2sYVeSunTpou+//95TJQEAAAAK9NSFLBaLevfubXPs1VdfVXp6uqKj\noyu1P3TokBITE22OxcXFKS8vz1MlAQAAAO4F3qKiIoeBNCEhQaGhodbHr7/+uj755BO99NJLdtsX\nFhZWGuYQHBys4uJil2rJzs5WcXGxEhISXKweAAAAtenQoUMKDg7Wd99959M63Aq869at04QJE2Qy\nmSqde/LJJzVw4EBJ0tKlS/XAAw9o7ty56tmzp91rWSwW5efn2xwrLi5WSEiIS7UUFRWptLTUnfIB\nAABQi86cOSMPTRerEbcCb7du3bR161anbV566SU99thjmj17tsaNG+ewXVJSkrZv325z7PDhwy73\n2J4bDvHZZ5+51B4AAAC161xnqK95dFmyf/zjH1q0aJHmzp2ra6+91mnbjh07avPmzTZDGFavXq1O\nnTp5siQAAADUcx4LvPn5+br//vt1+eWXa+jQoTp8+LD1v7KyMknS0aNHrSs2dOvWTcnJyZo9e7a2\nb9+u559/Xhs2bNDo0aM9VRIAOOUPt9mqUl5erryjp+pErXAPX1Og9ngs8K5YsUKFhYVatmyZcnJy\nlJOTo969eysnJ8e6mcTo0aP18ssvn31hs1lPP/20Dh06pFGjRum9997TU089pYYNG3qqJKDeKC8v\n16bcIzp1usR67O/Lf9TTf1unkjNlLl+nqKRUJwtLdLr4jA4cOakl723S7gPHra/x7292ac3WgzpZ\nWKJbHv1Mb3yyVfknivT5mr0qLDqj/BNFeuTVb/X7J/+r/BNFTl+rrKxcP+0/ruKSUm3bfUylZY7/\n+J86XaKVG/arsOiM3fO7DxzXjr2/2BwrOFWsZ99Zr5378iu1Ly8v130vfa1JD3yqY8dP2xy/8DVO\nF5/RicISnSwsUWlZuU4Xn1HBKdvJtYd/KdTy7/Y4rK+i77bk6eFXv9XegwU6capYJypca+OOw7rt\n8c/15dq91mOvfLBZkx74VH/97Eeb61T8um7ZeVRLP95qc62K7Rx9LU67UK909mu1btsh/ePz7cr9\nufLn011Hj5/W6x9v0a79x9163uniM1q5Yb/+/c1uvf7xFhWVOJ7HUV5err0HC7T2h4M6eLTy0phV\nOX6y2ObruX3PL/py7V49+8567T14dgfRf63apVc/3KwzpWUqOVP1nJLy8nJt3nlEB4+e0oEjJ3X9\nA5/qj2+scbs2STpRWKLZT32lZ99ZX63nX+id/2zXvS9+rV8KnP/cVuV08RnN/NMXuvfFr1Va6vrv\nHm8rLDqj0tKyKt9krN6ap2VfbNeZC2o/97ytu45q1cb9Ki0t04nCEnuXkCR9sWavlry3yen3KGqX\nxzaeqG3nxoQwhhdGV15eruMnixUVfnbN6v2HT2rrrqPq1SFFwUEBKi8v14hZ71rbd2gZr/XbD9tc\nIzYyRA/d2ktbfzqmT7/ZpY07jkiSurZNUv8uqSorK9dfP9umXQfsbwXer0tjfb56r91zFQUGmG3+\nUMy8potiwi1KSQhXQIBJn36zS5L0+kf25wKEWgI0fmhbhVoCdPxksdb+cEihIYFauWF/pbYLb7pI\nL/5zo36qEJoev62Pfv/kVwoJDrD5Y9QzM1lxUSHauOOIDhw5qQnD2ur5ZRsqXbN5SpRy9+UrPjpU\nh38p1KCuTfTvb3c7/HifmN5XgQFmTVn0H5vjd1/fXWGhQTpxqkTLV+9Ri0ZRGjOwtdb+cFB3P79S\nkhQcaFbxr6E1NSlC997QU9ct/Fel69z30iqHn6sbR3bQ6x9v1eFfCq3HR+Q0V5+sRkqMaaDjJ4ut\n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\npTeN8cr1Rw9opeljO8sSFOCV6/vSuSEmFw41qa77b7xIrVKjdcso99dIBgCgLjFkDy+8IyT4/LeL\n2Vy9SU2j+rdUx1bxatKQ9V3dNefablr34yF1bOWZwJuWEqU/3N7XI9eqsXLepAIAvMdwPbyHanBb\nvj5Lc2GDgXFDMxQTYVGbZrFq0Siqyvb2mEwmtUqN8Yse2LqWsUItgerRPtnpOGYAAFCZRwNvQUGB\n5s6dq169eqlnz56aM2eOCgoKHLZfuHChMjIy1KZNG+v/ly5dWqMarlvIcmTu6pKRqJt+W/Vt7ZiI\nEC2ZP1iPTOldJ5at6tAy3tclAAAAP+DRrqK7775be/fu1QsvvCCTyaQFCxZo/vz5euKJJ+y2z83N\n1axZszRy5EjrsfDw6q+5evwkE3Cq454beto8djZcobbG+nrCzGu66PWPtqhH+2RflwIAAHzIY4G3\nsLBQn376qd544w21bXt2YtJdd92lcePGqbi4WMHBlXdu2rFjhyZNmqS4OM8s6fPVup89cp366sqL\nW+uTlbs059quvi7FI2IjQzTNyRa6dWxEAwAAqCaPBV6z2axnn31WGRkZ1mPl5eUqLS3VqVOnKgXe\nEydOKC8vT82aNfNUCXrm7+s9dq36aNwlbXTNkIw6MVwBAADAVR67P22xWNS7d28FBZ1f/P/VV19V\nenq6oqOjK7XPzc2VyWTSM888o759++qyyy7TsmXLPFUOqqk+hd3IBpXvOsA34mMa+LoEAICBudXD\nW1RUpLy8PLvnEhISFBp6fvvT119/XZ988oleeuklu+1zc3NlNpvVokULjR8/Xt98843mz5+v8PBw\nDRo0yJ2yJEl7DzqeHAfH7p3cs+pGBjO4e1Ot3LBPs39njKEbRjBvYjfd//Iq9enUyNelAAAMyFRe\n7vriTN98840mTJhgtxfwySef1MCBAyVJS5cu1cKFCzV37lyNGzfO4fWOHz+uyMjzy2EtXLhQO3fu\ndBiSKzr3Wp999pkkacyc93W6uNTVD6WS7u0aVrkVrdEsmpaj9Kaxvi7DJ0rLyhVQzbWEAQCAay7M\na77iVg9vt27dtHXrVqdtXnrpJT322GOaPXu207ArySbsSlLz5s21atUqd0qyqknYlaR513XX8Jn/\nrNE16pr6NHzhQoRdAADqD48uS/aPf/xDixYt0ty5czV+/HinbRcvXqy1a9dqyZIl1mNbtmxRWlqa\n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\nrfn8AgmW+W3v53AHefXVV1leXk6v18uOjg7a7XZ2dHQs9WmJW8jMzFS3HYpGoywvL+eBAwd46dIl\nulwu2mw2da/M4eFhKorCY8eO8dKlS9y/fz+dTqf6WmfPnmV2djY7OjrY29vL8vJy1tXVqfW55ka8\n3mL+fD4f169fzyNHjnB8fFzzJVnrUzQa5Y4dO/j000/T5/Oxs7OTBQUFPHnyJKPRKLdt2yaZ61RN\nTY26TdTk5CTz8/NZV1dHn8/H2tpabtmyRd0X1ePxMCsri83NzRwYGGBlZSWfe+459bVcLhcLCwvZ\n3d3Nn376iQ6Hg5988olaf+aZZ1hZWcnBwUF+/vnnVBSFfX19t9VbLNzff//NrVu38oUXXuBvv/3G\nzs5OOhwOHj9+nJOTk8zLy0vYzBNywRsKhVhTU0Or1crCwkJ+9tlnS31KYg43/uGJP/74gxUVFdy0\naRPLy8vZ1dWlOf67775jWVkZLRYLd+3ape7hN+PYsWPMz89nTk4OX3nlFUYiEbUWb27E6y3mx+Vy\n0Ww2a74yMzNpNptJ/re3omStP2NjY6yqqmJ2djYdDgddLpdak8+3fl2/4CVJr9fLRx99lIqicOfO\nnRwYGNAcf+bMGRYVFdFqtbKqqorBYFCtRaNRvv3229y8eTMffPDBWfu+TkxMcM+ePVQUhSUlJTx7\n9qymHq+3WDifz8ddu3bRZrPR4XDw/fffV2uJnPky8rpNUoUQQgghhNCZhLuGVwghhBBCiPmQBa8Q\nQgghhNA1WfAKIYQQQghdkwWvEEIIIYTQNVnwCiGEEEIIXZMFrxBCCCGE0DVZ8AohhBBCCF2TBa8Q\nQgghhNA1WfAKIYQQQghdkwWvEEIIIYTQNVnwCiGEEEIIXfsf+xxcuu70xd4AAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b.plot_elbo()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Looks like convergence has happened! Let's also look at the posterior plot.\n", + "\n", + "What's provided is a `seaborn` swarm plot combined with the 95% HPD and IQR of the posterior distribution." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "collapsed": false + }, + "outputs": [ + { + "data": { + "image/png": "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\nIiYAAAAASUVORK5CYII=\n", + "text/plain": [ + "" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "b.plot_posterior() # can pass in rotate_xticks=True if needed" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [] + } + ], + "metadata": { + "anaconda-cloud": {}, + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.5.2" + } + }, + "nbformat": 4, + "nbformat_minor": 1 +} diff --git a/pymc3/distributions/__init__.py b/pymc3/distributions/__init__.py index b300c6dc4b..f6901f8624 100644 --- a/pymc3/distributions/__init__.py +++ b/pymc3/distributions/__init__.py @@ -79,8 +79,8 @@ 'Gamma', 'Weibull', 'Bound', - 'Lognormal', - 'HalfStudentT', + 'Lognormal', + 'HalfStudentT', 'StudentTpos', 'ChiSquared', 'HalfNormal', diff --git a/pymc3/models/__init__.py b/pymc3/models/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/pymc3/models/best.py b/pymc3/models/best.py new file mode 100644 index 0000000000..4cf680221c --- /dev/null +++ b/pymc3/models/best.py @@ -0,0 +1,168 @@ +""" +Written by: Eric J. Ma +Date: 11 November 2016 +Inspiration taken from many places, including the PyMC3 documentation. + +A note on the API design, for future contributors. + +There were some design choices made here for "default models" that may be +modified in the future. I list the choices below: + +- A "model" is an object, like scikit-learn. +- A model is instantiated with a DataFrame that houses the data. +- Models accept other parameters as necessary. +- Every model has a `.fit()` function that performs model fitting, like in + scikit-learn. +- Every model has a `.plot_posterior()` function that returns a figure showing + the posterior distribution. Inspired by the pymc3 GLM module. +- BEST uses ADVI, but this can (and should) be made an option; MCMC is also a + good tool to use. +""" + +from ..distributions import StudentT, Exponential, Uniform, HalfCauchy +from .. import Model +from ..variational import advi, sample_vp +import seaborn as sns +import numpy as np +import matplotlib.pyplot as plt +import pandas as pd + + +class BEST(object): + """BEST Model, based on Kruschke (2013). + + Parameters + ---------- + data : pandas DataFrame + A pandas dataframe which has the following data: + - Each row is one replicate measurement. + - There is a column that records the treatment name. + - There is a column that records the measured value for that replicate. + + sample_col : str + The name of the column containing sample names. + + output_col : str + The name of the column containing values to estimate. + + baseline_name : str + The name of the "control" or "baseline". + + Output + ------ + model : PyMC3 model + Returns the BEST model containing + """ + def __init__(self, data, sample_col, output_col, baseline_name): + super(BEST, self).__init__() + self.data = data + self.sample_col = sample_col + self.output_col = output_col + self.baseline_name = baseline_name + self.trace = None + + self._convert_to_indices() + + def _convert_to_indices(self): + """ + Adds the "indices" column to self.data (DataFrame). This is necessary + for the simplified model specification in the "fit" function below. + """ + sample_names = dict() + for i, name in enumerate( + list(np.unique(self.data[self.sample_col].values))): + print('Sample name {0} has the index {1}'.format(name, i)) + sample_names[name] = i + self.data['indices'] = self.data[self.sample_col].apply( + lambda x: sample_names[x]) + + def fit(self, n_steps=500000): + """ + Creates a Bayesian Estimation model for replicate measurements of + treatment(s) vs. control. + + Parameters + ---------- + n_steps : int + The number of steps to run ADVI. + """ + + sample_names = set(self.data[self.sample_col].values) + + mean_test = self.data.groupby('indices').mean()[self.output_col].values + sd_test = self.data.groupby('indices').std()[self.output_col].values + + with Model() as model: + # Hyperpriors + upper = Exponential('upper', lam=0.05) + nu = Exponential('nu_minus_one', 1/29.) + 1 + + # "fold", which is the estimated fold change. + fold = Uniform('fold', lower=1E-10, upper=upper, + shape=len(sample_names), testval=mean_test) + + # Assume that data have heteroskedastic (i.e. variable) error but + # are drawn from the same HalfCauchy distribution. + sigma = HalfCauchy('sigma', beta=1, shape=len(sample_names), + testval=sd_test) + + # Model prediction + mu = fold[self.data['indices']] + sig = sigma[self.data['indices']] + + # Data likelihood + like = StudentT('like', nu=nu, mu=mu, sd=sig**-2, + observed=self.data[self.output_col]) + + params = advi(n=n_steps) + trace = sample_vp(params, draws=2000) + + self.trace = trace + self.params = params + self.model = model + + def plot_posterior(self, rotate_xticks=False): + """ + Plots a swarm plot of the data overlaid on top of the 95% HPD and IQR + of the posterior distribution. + """ + + # Make summary plot # + fig = plt.figure() + ax = fig.add_subplot(111) + + # 1. Get the lower error and upper errorbars for 95% HPD and IQR. + lower, lower_q, upper_q, upper = np.percentile(self.trace['fold'], + [2.5, 25, 75, 97.5], + axis=0) + summary_stats = pd.DataFrame() + summary_stats['mean'] = self.trace['fold'].mean(axis=0) + err_low = summary_stats['mean'] - lower + err_high = upper - summary_stats['mean'] + iqr_low = summary_stats['mean'] - lower_q + iqr_high = upper_q - summary_stats['mean'] + + # 2. Plot the swarmplot and errorbars. + summary_stats['mean'].plot(ls='', ax=ax, + yerr=[err_low, err_high]) + summary_stats['mean'].plot(ls='', ax=ax, + yerr=[iqr_low, iqr_high], + elinewidth=4, color='red') + sns.swarmplot(data=self.data, x=self.sample_col, y=self.output_col, + ax=ax, alpha=0.5) + + if rotate_xticks: + print('rotating xticks') + plt.xticks(rotation='vertical') + plt.ylabel(self.output_col) + + return fig, ax + + def plot_elbo(self): + """ + Plots the ELBO values to help check for convergence. + """ + fig = plt.figure() + plt.plot(-np.log10(-self.params.elbo_vals)) + + return fig