├── README.md ├── requirements.txt ├── SimpleGaussian.ipynb ├── Captcha.ipynb └── MarkovPath.ipynb /README.md: -------------------------------------------------------------------------------- 1 | # MLHEP-pyprob 2 | 3 | [![Binder](https://mybinder.org/badge_logo.svg)](https://mybinder.org/v2/gh/lukasheinrich/MLHEP-pyprob/master) 4 | 5 | Tutorial Code for MLHEP pyprob 6 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | appnope==0.1.0 2 | attrs==19.1.0 3 | backcall==0.1.0 4 | bleach==3.1.0 5 | cycler==0.10.0 6 | decorator==4.4.0 7 | defusedxml==0.6.0 8 | entrypoints==0.3 9 | flatbuffers==1.10 10 | ipykernel==5.1.1 11 | ipython==7.6.0 12 | ipython-genutils==0.2.0 13 | ipywidgets==7.5.0 14 | jedi==0.14.0 15 | Jinja2==2.10.1 16 | jsonschema==3.0.1 17 | jupyter==1.0.0 18 | jupyter-client==5.2.4 19 | jupyter-console==6.0.0 20 | jupyter-core==4.5.0 21 | kiwisolver==1.1.0 22 | MarkupSafe==1.1.1 23 | matplotlib==3.1.0 24 | mistune==0.8.4 25 | nbconvert==5.5.0 26 | nbformat==4.4.0 27 | notebook==5.7.8 28 | numpy==1.16.4 29 | pandocfilters==1.4.2 30 | parso==0.5.0 31 | pexpect==4.7.0 32 | pickleshare==0.7.5 33 | Pillow==6.0.0 34 | prometheus-client==0.7.1 35 | prompt-toolkit==2.0.9 36 | ptyprocess==0.6.0 37 | pydotplus==2.0.2 38 | Pygments==2.4.2 39 | pyparsing==2.4.0 40 | pyprob==0.13.0 41 | pyrsistent==0.15.2 42 | python-dateutil==2.8.0 43 | pyzmq==18.0.2 44 | qtconsole==4.5.1 45 | scipy==1.3.0 46 | Send2Trash==1.5.0 47 | six==1.12.0 48 | termcolor==1.1.0 49 | terminado==0.8.2 50 | testpath==0.4.2 51 | tornado==6.0.3 52 | traitlets==4.3.2 53 | wcwidth==0.1.7 54 | webencodings==0.5.1 55 | widgetsnbextension==3.5.0 56 | awkward 57 | uproot_methods 58 | -------------------------------------------------------------------------------- /SimpleGaussian.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 1, 6 | "metadata": {}, 7 | "outputs": [ 8 | { 9 | "name": "stdout", 10 | "output_type": "stream", 11 | "text": [ 12 | "\u001b[1m\u001b[31mWarning: Empirical distributions on disk may perform slow because GNU DBM is not available. Please install and configure gdbm library for Python for better speed.\u001b[0m\n" 13 | ] 14 | } 15 | ], 16 | "source": [ 17 | "import pyprob\n", 18 | "%matplotlib inline\n", 19 | "import matplotlib.pyplot as plt\n", 20 | "from pyprob import Model\n", 21 | "import numpy as np" 22 | ] 23 | }, 24 | { 25 | "cell_type": "markdown", 26 | "metadata": {}, 27 | "source": [ 28 | "# Intro into `pyprob`\n", 29 | "\n", 30 | "`pyprob` is very easy. You only need to subclass `pyprob.Model` and add a `forward()` method that implements your generative model. Within the body of the model you can use `pyprob.sample` and `pyprob.observe` which are the necessary keywords of a probabilistic programming language.\n", 31 | "\n", 32 | "In this case it's a model which draws to random numbers `a` and `b` and draws the final value from a Gaussian with mean `a+b`, whatever their value was, with a small standard deviation.\n", 33 | "\n", 34 | "You can try thinking about what the posterior p(x,z) of prior p(z) look like." 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": 4, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "import math\n", 44 | "import pyprob\n", 45 | "from pyprob import Model\n", 46 | "from pyprob.distributions import Normal\n", 47 | "\n", 48 | "class SimpleGaussian(Model):\n", 49 | " def __init__(self):\n", 50 | " super().__init__(name=\"Simple Gaussian\") # give the model a name\n", 51 | " self.prior_mean = 1\n", 52 | " self.prior_std = 4\n", 53 | " self.likelihood_std = 0.5\n", 54 | "\n", 55 | " def forward(self): # Needed to specifcy how the generative model is run forward\n", 56 | " # sample the (latent) mean variable to be inferred:\n", 57 | " a = pyprob.sample(Normal(self.prior_mean, self.prior_std), name = 'input1') # NOTE: sample -> denotes latent variables\n", 58 | " b = pyprob.sample(Normal(self.prior_mean, self.prior_std), name = 'input2') # NOTE: sample -> denotes latent variables\n", 59 | "\n", 60 | " mu = a+b\n", 61 | "\n", 62 | " pyprob.observe(Normal(mu, self.likelihood_std), name='obs0') # NOTE: observe -> denotes observable variables\n", 63 | " return a,b\n", 64 | "\n", 65 | "model = SimpleGaussian()" 66 | ] 67 | }, 68 | { 69 | "cell_type": "markdown", 70 | "metadata": {}, 71 | "source": [ 72 | "## Learning to Infer\n", 73 | "\n", 74 | "inference means that we can efficiently get samples that follow the posterior `p(z|x)`. In the \"inference compilation\" method, we train a network that, when running the `forward()` will propose appropriate distribution to sample from such that the overall trace approaches the true posterior. Let's train this \"smart ML agent\" that will steer our simulation code in the right direction." 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": 5, 80 | "metadata": {}, 81 | "outputs": [ 82 | { 83 | "name": "stdout", 84 | "output_type": "stream", 85 | "text": [ 86 | "Creating new inference network...\n", 87 | "Observable obs0: observe embedding not specified, using the default FEEDFORWARD.\n", 88 | "Observe embedding dimension: 32\n", 89 | "Train. time | Epoch| Trace | Init. loss| Min. loss | Curr. loss| T.since min | Traces/sec\n", 90 | "New layers, address: 20__forward__a__Normal__1, distribution: Normal\n", 91 | "New layers, address: 44__forward__b__Normal__1, distribution: Normal\n", 92 | "Total addresses: 2, parameters: 6,926\n", 93 | "0d:00:00:06 | 1 | 10,048 | +5.77e+00 | +4.50e+00 | \u001b[31m+5.08e+00\u001b[0m | 0d:00:00:02 | 1,053.0 \n" 94 | ] 95 | } 96 | ], 97 | "source": [ 98 | "model.learn_inference_network(\n", 99 | " num_traces=10000,\n", 100 | " observe_embeddings={'obs0': {'dim': 32, 'depth': 3}}\n", 101 | ")" 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "Let's now collect some samples from both the prior and the posterior so we can compare" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": 7, 114 | "metadata": {}, 115 | "outputs": [ 116 | { 117 | "name": "stdout", 118 | "output_type": "stream", 119 | "text": [ 120 | "Time spent | Time remain.| Progress | Trace | Traces/sec\n", 121 | "0d:00:00:00 | 0d:00:00:00 | #################### | 1000/1000 | 2,388.31 \n", 122 | "Time spent | Time remain.| Progress | Trace | Traces/sec\n", 123 | "0d:00:00:03 | 0d:00:00:00 | #################### | 1000/1000 | 332.45 \n" 124 | ] 125 | } 126 | ], 127 | "source": [ 128 | "condition = {'obs0': 2}\n", 129 | "\n", 130 | "prior = model.prior_distribution(\n", 131 | " num_traces=1000,\n", 132 | ")\n", 133 | "posterior = model.posterior_distribution(\n", 134 | " num_traces=1000,\n", 135 | " inference_engine=pyprob.InferenceEngine.IMPORTANCE_SAMPLING_WITH_INFERENCE_NETWORK,\n", 136 | " observe=condition\n", 137 | ")" 138 | ] 139 | }, 140 | { 141 | "cell_type": "code", 142 | "execution_count": 8, 143 | "metadata": {}, 144 | "outputs": [], 145 | "source": [ 146 | "edges = np.linspace(-10,10, 25)" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": 9, 152 | "metadata": {}, 153 | "outputs": [], 154 | "source": [ 155 | "prior = np.asarray([[x.item() for x in prior.sample()] for x in range(1000)])\n", 156 | "posterior = np.asarray([[x.item() for x in posterior.sample()] for x in range(1000)])" 157 | ] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": {}, 162 | "source": [ 163 | "## The conditioned posterior\n", 164 | "\n", 165 | "\n", 166 | "As we plot the latent state of the simulator (the numbers `a` and `b`) below we see the effect of the conditioning. Conditioning on a particular value `c` forces the relation `a+b = c` to approximately hold (within the range of the standard deviation). What will happen if you decreate the standard deviation?" 167 | ] 168 | }, 169 | { 170 | "cell_type": "code", 171 | "execution_count": 11, 172 | "metadata": {}, 173 | "outputs": [ 174 | { 175 | "data": { 176 | "image/png": "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\n", 177 | "text/plain": [ 178 | "
" 179 | ] 180 | }, 181 | "metadata": { 182 | "needs_background": "light" 183 | }, 184 | "output_type": "display_data" 185 | } 186 | ], 187 | "source": [ 188 | "plt.scatter(prior[:,0],prior[:,1], alpha = 0.2)\n", 189 | "plt.scatter(posterior[:,0],posterior[:,1], alpha = 0.2)\n", 190 | "plt.xlim(-20,20)\n", 191 | "plt.ylim(-20,20)\n", 192 | "plt.gcf().set_size_inches(5,5)" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "metadata": {}, 199 | "outputs": [], 200 | "source": [] 201 | } 202 | ], 203 | "metadata": { 204 | "kernelspec": { 205 | "display_name": "Python 3", 206 | "language": "python", 207 | "name": "python3" 208 | }, 209 | "language_info": { 210 | "codemirror_mode": { 211 | "name": "ipython", 212 | "version": 3 213 | }, 214 | "file_extension": ".py", 215 | "mimetype": "text/x-python", 216 | "name": "python", 217 | "nbconvert_exporter": "python", 218 | "pygments_lexer": "ipython3", 219 | "version": "3.6.6" 220 | } 221 | }, 222 | "nbformat": 4, 223 | "nbformat_minor": 2 224 | } 225 | -------------------------------------------------------------------------------- /Captcha.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Probabilistic Programming to break CAPTCHAS\n", 8 | "\n", 9 | "Captchas are puzzles usually given as part of a verification procedure to ensure a internet user is indeed a human and not a bit. It involves identifying a string of letters (or numbers)\n", 10 | "\n", 11 | "\n", 12 | "In this example we will write a probabilistic CAPTCHA generator and instrument it using the probabilistic programming library `pyprob` in order to run amortized inference." 13 | ] 14 | }, 15 | { 16 | "cell_type": "markdown", 17 | "metadata": {}, 18 | "source": [ 19 | "First, we import some basic libraries we will need later on." 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": 1, 25 | "metadata": {}, 26 | "outputs": [ 27 | { 28 | "name": "stdout", 29 | "output_type": "stream", 30 | "text": [ 31 | "\u001b[1m\u001b[31mWarning: Empirical distributions on disk may perform slow because GNU DBM is not available. Please install and configure gdbm library for Python for better speed.\u001b[0m\n" 32 | ] 33 | } 34 | ], 35 | "source": [ 36 | "%matplotlib inline\n", 37 | "import numpy as np\n", 38 | "import torch\n", 39 | "import time\n", 40 | "import matplotlib.pyplot as plt\n", 41 | "\n", 42 | "import pyprob\n", 43 | "import pyprob.distributions\n", 44 | "import IPython\n", 45 | "\n", 46 | "from PIL import Image, ImageFilter, ImageDraw, ImageFont\n" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "## Writing a Generator\n", 54 | "\n", 55 | "Here we use the `Pillow` library to write a generator. This is a good example how probabilistic programs allow you use general purpose host languages (in this case Python, but could also be C++) with all their nice libraries, instead of restricting you to a statistical modeling framework (try writing this in RooFit :) )" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 2, 61 | "metadata": {}, 62 | "outputs": [], 63 | "source": [ 64 | "# prepare the set of letters from which we \n", 65 | "\n", 66 | "alphabetorder = list('abcdefghijklmnopqrstuvw')\n", 67 | "alphabet = dict(zip(range(len(alphabetorder)),alphabetorder))\n", 68 | "\n", 69 | "\n", 70 | "def message_to_picture(width, height, message, blur):\n", 71 | " canvas = Image.new('L', (width, height), \"white\")\n", 72 | " font = ImageFont.load_default()\n", 73 | " ImageDraw.Draw(canvas).text((2,0), message, 'black', font)\n", 74 | " canvas = canvas.filter(ImageFilter.GaussianBlur(blur))\n", 75 | " d = np.asarray(list(canvas.getdata()), dtype = np.float)\n", 76 | " return d\n", 77 | "\n", 78 | "def random_captcha(width, height, blur = 0.5):\n", 79 | " letter_distr = pyprob.distributions.Categorical([1/len(alphabet)]*len(alphabet))\n", 80 | " length = 3\n", 81 | " word = ''.join([alphabet[letter_distr.sample().item()] for i in range(length)])\n", 82 | " d = message_to_picture(width, height, word,blur)\n", 83 | " return word, torch.tensor(d, dtype = torch.float).view(-1)/255-0.5\n", 84 | "\n", 85 | "def likelihoood(observation,eps):\n", 86 | " lhood = pyprob.distributions.Normal(observation,eps*torch.ones(observation.shape))\n", 87 | " return lhood" 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": {}, 93 | "source": [ 94 | "# An Example CAPTCHA\n", 95 | "\n", 96 | "Note that our captcha generator is very un-sophisticated, but it has the correct components: sampling latters, adding some blur, etc...\n", 97 | "\n", 98 | "Let's generate a CAPTCHA to see how it looks" 99 | ] 100 | }, 101 | { 102 | "cell_type": "code", 103 | "execution_count": 3, 104 | "metadata": {}, 105 | "outputs": [ 106 | { 107 | "data": { 108 | "text/plain": [ 109 | "Text(0.5, 1.0, 'ground truth: ian')" 110 | ] 111 | }, 112 | "execution_count": 3, 113 | "metadata": {}, 114 | "output_type": "execute_result" 115 | }, 116 | { 117 | "data": { 118 | "image/png": "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\n", 119 | "text/plain": [ 120 | "
" 121 | ] 122 | }, 123 | "metadata": { 124 | "needs_background": "light" 125 | }, 126 | "output_type": "display_data" 127 | } 128 | ], 129 | "source": [ 130 | "word, img = random_captcha(20,12, blur = 0.2)\n", 131 | "plt.imshow(img.reshape(12,20))\n", 132 | "plt.title('ground truth: {}'.format(word))" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "... and another one" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": 4, 145 | "metadata": {}, 146 | "outputs": [ 147 | { 148 | "data": { 149 | "text/plain": [ 150 | "Text(0.5, 1.0, 'ground truth: ckm')" 151 | ] 152 | }, 153 | "execution_count": 4, 154 | "metadata": {}, 155 | "output_type": "execute_result" 156 | }, 157 | { 158 | "data": { 159 | "image/png": "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\n", 160 | "text/plain": [ 161 | "
" 162 | ] 163 | }, 164 | "metadata": { 165 | "needs_background": "light" 166 | }, 167 | "output_type": "display_data" 168 | } 169 | ], 170 | "source": [ 171 | "word, img = random_captcha(20,12, blur = 0.7)\n", 172 | "plt.imshow(img.reshape(12,20))\n", 173 | "plt.title('ground truth: {}'.format(word))" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "metadata": {}, 179 | "source": [ 180 | "# Integrating into `pyprob`\n", 181 | "\n", 182 | "Now we will see how we integrate this existing generative model into `pyprob`\n", 183 | "\n", 184 | "In `pyprob` we only need to write a `forward()` method and inherit frmo the `Model` class. So integrating it is straight forward!\n", 185 | "\n", 186 | "In the end we want to `observe` the resulting image (we allow the pixel values of the generated image to be sampled frmo the mean determined by the latent rendered image)" 187 | ] 188 | }, 189 | { 190 | "cell_type": "code", 191 | "execution_count": 5, 192 | "metadata": {}, 193 | "outputs": [], 194 | "source": [ 195 | "import math\n", 196 | "import pyprob\n", 197 | "from pyprob import Model\n", 198 | "from pyprob.distributions import Normal\n", 199 | "\n", 200 | "class CaptchaModel(Model):\n", 201 | " def __init__(self):\n", 202 | " super().__init__(name=\"CAPTCHA model\") # give the model a name\n", 203 | "\n", 204 | " def forward(self): # Needed to specifcy how the generative model is run forward\n", 205 | " mu = pyprob.sample(pyprob.distributions.Normal(0,1))\n", 206 | " blur = pyprob.sample(pyprob.distributions.Normal(0.5,0.3))\n", 207 | " word, d = random_captcha(20,12, blur = blur)\n", 208 | " obs_distr = likelihoood(d,1.0)\n", 209 | " pyprob.observe(pyprob.distributions.Normal(d,0.5*torch.ones(d.shape)), name = 'obs0')\n", 210 | " return {\n", 211 | " 'word': word,\n", 212 | " 'image': d,\n", 213 | " 'blur': blur\n", 214 | " }\n", 215 | "\n", 216 | "model = CaptchaModel()" 217 | ] 218 | }, 219 | { 220 | "cell_type": "markdown", 221 | "metadata": {}, 222 | "source": [ 223 | "# The prior distribution (unconditioned)\n", 224 | "\n", 225 | "let's see what type of CAPTCHAS we get if we just run the generator. This is basically the same way we ran it above, but now it's integrated in `pyprob`." 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": 7, 231 | "metadata": {}, 232 | "outputs": [ 233 | { 234 | "name": "stdout", 235 | "output_type": "stream", 236 | "text": [ 237 | "Time spent | Time remain.| Progress | Trace | Traces/sec\n", 238 | "0d:00:00:00 | 0d:00:00:00 | #################### | 10/10 | 566.42 \n" 239 | ] 240 | }, 241 | { 242 | "data": { 243 | "image/png": "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\n", 244 | "text/plain": [ 245 | "
" 246 | ] 247 | }, 248 | "metadata": { 249 | "needs_background": "light" 250 | }, 251 | "output_type": "display_data" 252 | }, 253 | { 254 | "data": { 255 | "image/png": "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\n", 256 | "text/plain": [ 257 | "
" 258 | ] 259 | }, 260 | "metadata": { 261 | "needs_background": "light" 262 | }, 263 | "output_type": "display_data" 264 | } 265 | ], 266 | "source": [ 267 | "prior = model.prior_distribution()\n", 268 | "sample = prior.sample()\n", 269 | "plt.imshow(sample['image'].numpy().reshape(12,-1))\n", 270 | "plt.title('ground truth: {}'.format(sample['word']))\n", 271 | "plt.show()\n", 272 | "\n", 273 | "sample = prior.sample()\n", 274 | "plt.imshow(sample['image'].numpy().reshape(12,-1))\n", 275 | "plt.title('ground truth: {}'.format(sample['word']))\n", 276 | "plt.show()" 277 | ] 278 | }, 279 | { 280 | "cell_type": "markdown", 281 | "metadata": {}, 282 | "source": [ 283 | "## Learning the inference network\n", 284 | "\n", 285 | "\n", 286 | "During inference we want to steer the simulator with a \"smart ML agent\" such that we only get samples that match our observed captcha. This way we can inspect the latent state of the sampled traces and quickly extract the solution.\n", 287 | "\n", 288 | "We will now train the ML agent on 5000 traces." 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "execution_count": 8, 294 | "metadata": {}, 295 | "outputs": [ 296 | { 297 | "name": "stdout", 298 | "output_type": "stream", 299 | "text": [ 300 | "Creating new inference network...\n", 301 | "Observable obs0: observe embedding not specified, using the default FEEDFORWARD.\n", 302 | "Observe embedding dimension: 32\n", 303 | "Train. time | Epoch| Trace | Init. loss| Min. loss | Curr. loss| T.since min | Traces/sec\n", 304 | "New layers, address: 16__forward__mu__Normal__1, distribution: Normal\n", 305 | "New layers, address: 36__forward__blur__Normal__1, distribution: Normal\n", 306 | "Total addresses: 2, parameters: 61,870\n", 307 | "0d:00:00:07 | 1 | 5,056 | +1.44e+00 | +1.31e+00 | \u001b[32m+1.32e+00\u001b[0m | 0d:00:00:00 | 617.0 \n" 308 | ] 309 | } 310 | ], 311 | "source": [ 312 | "model.learn_inference_network(\n", 313 | " num_traces=5000,\n", 314 | " observe_embeddings={'obs0': {'dim': 32, 'depth': 3}}\n", 315 | ")" 316 | ] 317 | }, 318 | { 319 | "cell_type": "markdown", 320 | "metadata": {}, 321 | "source": [ 322 | "## Sampling from the Posterior\n", 323 | "\n", 324 | "Now we will generate the posterior distribution. `pyprob` will generate 10,000 weighted traces from which we can sample according to their weights, which gives us unweighted samples frmo the posterior." 325 | ] 326 | }, 327 | { 328 | "cell_type": "code", 329 | "execution_count": 9, 330 | "metadata": {}, 331 | "outputs": [ 332 | { 333 | "data": { 334 | "image/png": "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\n", 335 | "text/plain": [ 336 | "
" 337 | ] 338 | }, 339 | "metadata": { 340 | "needs_background": "light" 341 | }, 342 | "output_type": "display_data" 343 | } 344 | ], 345 | "source": [ 346 | "condition = prior.sample()\n", 347 | "plt.imshow(condition['image'].numpy().reshape(12,-1))\n", 348 | "plt.title('ground truth: {}'.format(condition['word']))\n", 349 | "plt.show()" 350 | ] 351 | }, 352 | { 353 | "cell_type": "code", 354 | "execution_count": 10, 355 | "metadata": {}, 356 | "outputs": [ 357 | { 358 | "name": "stdout", 359 | "output_type": "stream", 360 | "text": [ 361 | "Time spent | Time remain.| Progress | Trace | Traces/sec\n", 362 | "0d:00:00:53 | 0d:00:00:00 | #################### | 10000/10000 | 188.66 \n" 363 | ] 364 | } 365 | ], 366 | "source": [ 367 | "posterior = model.posterior_distribution(\n", 368 | " num_traces=10000,\n", 369 | " inference_engine=pyprob.InferenceEngine.IMPORTANCE_SAMPLING_WITH_INFERENCE_NETWORK,\n", 370 | " observe={'obs0': condition['image'].numpy()}\n", 371 | ")" 372 | ] 373 | }, 374 | { 375 | "cell_type": "markdown", 376 | "metadata": {}, 377 | "source": [ 378 | "## Making the Animations\n", 379 | "\n", 380 | "Now that we have the prior and posterior distributions we can sample a few captchas to observe the effect of the conditioning on the above \"observation\"\n", 381 | "\n", 382 | "We will draw 100 captchas each. If everything worked, the prior will be changing very rapidly while the posterior should almost always yield a CAPTCHA that looks much like the condition" 383 | ] 384 | }, 385 | { 386 | "cell_type": "code", 387 | "execution_count": 12, 388 | "metadata": { 389 | "scrolled": false 390 | }, 391 | "outputs": [ 392 | { 393 | "name": "stdout", 394 | "output_type": "stream", 395 | "text": [ 396 | "0\n", 397 | "10\n", 398 | "20\n", 399 | "30\n", 400 | "40\n", 401 | "50\n", 402 | "60\n", 403 | "70\n", 404 | "80\n", 405 | "90\n", 406 | "make animation\n", 407 | "display image\n" 408 | ] 409 | }, 410 | { 411 | "data": { 412 | "text/html": [ 413 | "" 414 | ], 415 | "text/plain": [ 416 | "" 417 | ] 418 | }, 419 | "execution_count": 12, 420 | "metadata": {}, 421 | "output_type": "execute_result" 422 | }, 423 | { 424 | "data": { 425 | "text/plain": [ 426 | "
" 427 | ] 428 | }, 429 | "metadata": {}, 430 | "output_type": "display_data" 431 | } 432 | ], 433 | "source": [ 434 | "for i in range(100):\n", 435 | " if i%10 == 0:\n", 436 | " print(i)\n", 437 | " sample = prior.sample()\n", 438 | " plt.imshow(sample['image'].reshape(12,-1))\n", 439 | " plt.title('generated {}'.format(sample['word']))\n", 440 | " plt.savefig('foranim_prior_{}.png'.format(str(i).zfill(6)))\n", 441 | "plt.clf()\n", 442 | "print('make animation')\n", 443 | "uniq = time.time()\n", 444 | "!convert -delay 5 -loop 0 foranim_prior_*.png prior_{uniq}.gif\n", 445 | "!rm foranim_prior_*png\n", 446 | "print('display image')\n", 447 | "IPython.display.Image(url='prior_{}.gif'.format(uniq).format(uniq))" 448 | ] 449 | }, 450 | { 451 | "cell_type": "code", 452 | "execution_count": 13, 453 | "metadata": { 454 | "scrolled": false 455 | }, 456 | "outputs": [ 457 | { 458 | "name": "stdout", 459 | "output_type": "stream", 460 | "text": [ 461 | "0\n", 462 | "10\n", 463 | "20\n", 464 | "30\n", 465 | "40\n", 466 | "50\n", 467 | "60\n", 468 | "70\n", 469 | "80\n", 470 | "90\n", 471 | "make animation\n", 472 | "display image\n" 473 | ] 474 | }, 475 | { 476 | "data": { 477 | "text/html": [ 478 | "" 479 | ], 480 | "text/plain": [ 481 | "" 482 | ] 483 | }, 484 | "execution_count": 13, 485 | "metadata": {}, 486 | "output_type": "execute_result" 487 | }, 488 | { 489 | "data": { 490 | "text/plain": [ 491 | "
" 492 | ] 493 | }, 494 | "metadata": {}, 495 | "output_type": "display_data" 496 | } 497 | ], 498 | "source": [ 499 | "for i in range(100):\n", 500 | " if i%10 == 0:\n", 501 | " print(i)\n", 502 | " sample = posterior.sample()\n", 503 | " plt.imshow(sample['image'].reshape(12,-1))\n", 504 | " plt.title('ground truth: {}, generated: {}'.format(condition['word'],sample['word']))\n", 505 | " plt.savefig('foranim_posterior_{}.png'.format(str(i).zfill(6)))\n", 506 | "plt.clf()\n", 507 | "print('make animation')\n", 508 | "uniq = time.time()\n", 509 | "!convert -delay 5 -loop 0 foranim_posterior_*.png posterior_{uniq}.gif\n", 510 | "!rm -rf foranim_posterior_*png\n", 511 | "print('display image')\n", 512 | "IPython.display.Image(url='posterior_{}.gif'.format(uniq))" 513 | ] 514 | }, 515 | { 516 | "cell_type": "markdown", 517 | "metadata": {}, 518 | "source": [ 519 | "## Inspecting the Latent State\n", 520 | "\n", 521 | "For evey sample we draw from the posterior we have full access to the trace. We can e.g. construct marginal posterior distributions for specific letters of the captcha" 522 | ] 523 | }, 524 | { 525 | "cell_type": "code", 526 | "execution_count": 14, 527 | "metadata": {}, 528 | "outputs": [ 529 | { 530 | "data": { 531 | "text/plain": [ 532 | "" 533 | ] 534 | }, 535 | "execution_count": 14, 536 | "metadata": {}, 537 | "output_type": "execute_result" 538 | }, 539 | { 540 | "data": { 541 | "image/png": "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\n", 542 | "text/plain": [ 543 | "
" 544 | ] 545 | }, 546 | "metadata": { 547 | "needs_background": "light" 548 | }, 549 | "output_type": "display_data" 550 | } 551 | ], 552 | "source": [ 553 | "letter_num = 2\n", 554 | "\n", 555 | "reverse_alphabet = {v:k for k,v in alphabet.items()} \n", 556 | "c,_,_ = plt.hist([reverse_alphabet[posterior.sample()['word'][letter_num]] for i in range(1000)], bins = np.linspace(-0.5,len(alphabet)+0.5,len(alphabet)+2))\n", 557 | "\n", 558 | "plt.xticks(range(len(alphabetorder)),list(alphabetorder));\n", 559 | "plt.vlines(reverse_alphabet[condition['word'][letter_num]],0,1.2*max(c), colors = 'r', linestyles = 'dashed')" 560 | ] 561 | }, 562 | { 563 | "cell_type": "markdown", 564 | "metadata": {}, 565 | "source": [ 566 | "## Solving the CAPTCHA\n", 567 | "\n", 568 | "A good solution is the MAP, the maximum a posteriori value of the posterior. If we sample traces from the posterior and pick the solution which appears most often, it has a good chance to be the true solution" 569 | ] 570 | }, 571 | { 572 | "cell_type": "code", 573 | "execution_count": 15, 574 | "metadata": {}, 575 | "outputs": [ 576 | { 577 | "data": { 578 | "text/plain": [ 579 | "'wpw'" 580 | ] 581 | }, 582 | "execution_count": 15, 583 | "metadata": {}, 584 | "output_type": "execute_result" 585 | } 586 | ], 587 | "source": [ 588 | "solutions, counts = np.unique([posterior.sample()['word'] for i in range(1000)], return_counts = True)\n", 589 | "solutions[np.argmax(counts)]" 590 | ] 591 | }, 592 | { 593 | "cell_type": "code", 594 | "execution_count": null, 595 | "metadata": {}, 596 | "outputs": [], 597 | "source": [] 598 | } 599 | ], 600 | "metadata": { 601 | "kernelspec": { 602 | "display_name": "Python 3", 603 | "language": "python", 604 | "name": "python3" 605 | }, 606 | "language_info": { 607 | "codemirror_mode": { 608 | "name": "ipython", 609 | "version": 3 610 | }, 611 | "file_extension": ".py", 612 | "mimetype": "text/x-python", 613 | "name": "python", 614 | "nbconvert_exporter": "python", 615 | "pygments_lexer": "ipython3", 616 | "version": "3.7.3" 617 | } 618 | }, 619 | "nbformat": 4, 620 | "nbformat_minor": 2 621 | } 622 | -------------------------------------------------------------------------------- /MarkovPath.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Forcing a Markov Chain to arrive at the right place\n", 8 | "\n", 9 | "\n", 10 | "Markov Chains are sequences of random variables, where the value of the current sequence index only depends on the value just before it. Given a current position, the next position is simply defined by a probability distribution p(z,z').\n", 11 | "\n", 12 | "Here we look at a Markov Chain starting at `[0,0]`, which at each point can make exactly two moves \"up\" and \"down\".\n", 13 | "\n", 14 | "If you just let the Markov Chain run freely, we will it be after 10 iteratinos? or 20? or 100? You might have heard about the Galton Board." 15 | ] 16 | }, 17 | { 18 | "cell_type": "markdown", 19 | "metadata": {}, 20 | "source": [ 21 | "Before we start, we will import some libraries as always" 22 | ] 23 | }, 24 | { 25 | "cell_type": "code", 26 | "execution_count": 1, 27 | "metadata": {}, 28 | "outputs": [ 29 | { 30 | "name": "stdout", 31 | "output_type": "stream", 32 | "text": [ 33 | "\u001b[1m\u001b[31mWarning: Empirical distributions on disk may perform slow because GNU DBM is not available. Please install and configure gdbm library for Python for better speed.\u001b[0m\n" 34 | ] 35 | } 36 | ], 37 | "source": [ 38 | "import pyprob\n", 39 | "%matplotlib inline\n", 40 | "import matplotlib.pyplot as plt\n", 41 | "from pyprob import Model\n", 42 | "import numpy as np\n", 43 | "\n", 44 | "import math\n", 45 | "import pyprob\n", 46 | "from pyprob import Model\n", 47 | "from pyprob.distributions import Normal, Uniform, Categorical\n", 48 | "import torch\n", 49 | "import IPython\n" 50 | ] 51 | }, 52 | { 53 | "cell_type": "code", 54 | "execution_count": 2, 55 | "metadata": {}, 56 | "outputs": [ 57 | { 58 | "data": { 59 | "text/html": [ 60 | "" 61 | ], 62 | "text/plain": [ 63 | "" 64 | ] 65 | }, 66 | "execution_count": 2, 67 | "metadata": {}, 68 | "output_type": "execute_result" 69 | } 70 | ], 71 | "source": [ 72 | "IPython.display.Image(url = 'https://thumbs.gfycat.com/QuaintTidyCockatiel-max-1mb.gif')" 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "## Implementing the Galton Board in Code\n", 80 | "\n", 81 | "we will have a Galton board with 20 steps. At each step the position can move either up and down in a fair way." 82 | ] 83 | }, 84 | { 85 | "cell_type": "code", 86 | "execution_count": 3, 87 | "metadata": {}, 88 | "outputs": [], 89 | "source": [ 90 | "class MarkovChainPath(Model):\n", 91 | " def __init__(self):\n", 92 | " super().__init__(name=\"Markov Chain Path\") # give the model a name\n", 93 | "\n", 94 | " def forward(self): # Needed to specifcy how the generative model is run forward\n", 95 | " # sample the (latent) mean variable to be inferred:\n", 96 | " coords = [[0,0]]\n", 97 | " moves = {0: -1, 1: 1, 2: 1}\n", 98 | " for i in range(1,20):\n", 99 | " last = coords[-1][1]\n", 100 | " move = pyprob.sample(Categorical([1/2.,1/2.]), name = 'input{}'.format(i))\n", 101 | " move = moves[move.item()]\n", 102 | " coords.append([i,last+move])\n", 103 | "\n", 104 | " obs_distr = Normal(coords[-1][1], 0.1)\n", 105 | " pyprob.observe(obs_distr, name='obs0') # NOTE: observe -> denotes observable variables\n", 106 | " return coords\n", 107 | "\n", 108 | "model = MarkovChainPath()" 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "metadata": {}, 114 | "source": [ 115 | "## Learning to Guide the Chain\n", 116 | "\n", 117 | "As usual we will be training our inference network!" 118 | ] 119 | }, 120 | { 121 | "cell_type": "code", 122 | "execution_count": 4, 123 | "metadata": {}, 124 | "outputs": [ 125 | { 126 | "name": "stdout", 127 | "output_type": "stream", 128 | "text": [ 129 | "Creating new inference network...\n", 130 | "Observable obs0: observe embedding not specified, using the default FEEDFORWARD.\n", 131 | "Observe embedding dimension: 100\n", 132 | "Train. time | Epoch| Trace | Init. loss| Min. loss | Curr. loss| T.since min | Traces/sec\n", 133 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__1, distribution: Categorical\n", 134 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__2, distribution: Categorical\n", 135 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__3, distribution: Categorical\n", 136 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__4, distribution: Categorical\n", 137 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__5, distribution: Categorical\n", 138 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__6, distribution: Categorical\n", 139 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__7, distribution: Categorical\n", 140 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__8, distribution: Categorical\n", 141 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__9, distribution: Categorical\n", 142 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__10, distribution: Categorical\n", 143 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__11, distribution: Categorical\n", 144 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__12, distribution: Categorical\n", 145 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__13, distribution: Categorical\n", 146 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__14, distribution: Categorical\n", 147 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__15, distribution: Categorical\n", 148 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__16, distribution: Categorical\n", 149 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__17, distribution: Categorical\n", 150 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__18, distribution: Categorical\n", 151 | "New layers, address: 74__forward__move__Categorical(len_probs:2)__19, distribution: Categorical\n", 152 | "Total addresses: 19, parameters: 132,895\n", 153 | "0d:00:00:47 | 1 | 10,048 | +1.32e+01 | +1.23e+01 | \u001b[32m+1.27e+01\u001b[0m | 0d:00:00:29 | 216.0 \n" 154 | ] 155 | } 156 | ], 157 | "source": [ 158 | "model.learn_inference_network(\n", 159 | " num_traces=10000,\n", 160 | " observe_embeddings={'obs0': {'dim': 100, 'depth': 5}}\n", 161 | ")" 162 | ] 163 | }, 164 | { 165 | "cell_type": "markdown", 166 | "metadata": {}, 167 | "source": [ 168 | "# Generating Prior and Posterior Traces\n", 169 | "\n", 170 | "As in the other examples we have prior and posterior traces. What will they look like? Have a guess." 171 | ] 172 | }, 173 | { 174 | "cell_type": "code", 175 | "execution_count": 5, 176 | "metadata": {}, 177 | "outputs": [ 178 | { 179 | "name": "stdout", 180 | "output_type": "stream", 181 | "text": [ 182 | "Time spent | Time remain.| Progress | Trace | Traces/sec\n", 183 | "0d:00:00:04 | 0d:00:00:00 | #################### | 1000/1000 | 229.92 \n" 184 | ] 185 | } 186 | ], 187 | "source": [ 188 | "prior = model.prior_traces(\n", 189 | " num_traces=1000,\n", 190 | ")" 191 | ] 192 | }, 193 | { 194 | "cell_type": "markdown", 195 | "metadata": {}, 196 | "source": [ 197 | "We will also generate some sampled from the **conditioned** model. Feel free to change the condition value from 5 to a number you like." 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "execution_count": 14, 203 | "metadata": {}, 204 | "outputs": [ 205 | { 206 | "name": "stdout", 207 | "output_type": "stream", 208 | "text": [ 209 | "Time spent | Time remain.| Progress | Trace | Traces/sec\n", 210 | "0d:00:00:18 | 0d:00:00:00 | #################### | 1000/1000 | 53.91 \n" 211 | ] 212 | } 213 | ], 214 | "source": [ 215 | "condition = {'obs0': 5}\n", 216 | "posterior = model.posterior_traces(\n", 217 | " num_traces=1000,\n", 218 | " inference_engine=pyprob.InferenceEngine.IMPORTANCE_SAMPLING_WITH_INFERENCE_NETWORK,\n", 219 | " observe=condition\n", 220 | ")" 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": {}, 226 | "source": [ 227 | "Let's get a representative set of paths for both the **conditioned** model as well as the **unconditioned** one" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": 15, 233 | "metadata": {}, 234 | "outputs": [], 235 | "source": [ 236 | "post_paths = [posterior.sample().result for i in range(1000)]\n", 237 | "prior_paths = [prior.sample().result for i in range(1000)]" 238 | ] 239 | }, 240 | { 241 | "cell_type": "markdown", 242 | "metadata": {}, 243 | "source": [ 244 | "## The Plots!\n", 245 | "\n", 246 | "As expected the conoditioned paths always arrive at the same spot, no matter where they wandered off to in the middle of their path. At some point the proposals from the agent will steer it in the correct direction.\n", 247 | "\n", 248 | "\n", 249 | "We can also plot the final position distribution. As expected the unconditinoed one follows a normal distribution while the conditioned one, is basically a delta distribution on the conditioned value" 250 | ] 251 | }, 252 | { 253 | "cell_type": "code", 254 | "execution_count": 16, 255 | "metadata": {}, 256 | "outputs": [ 257 | { 258 | "data": { 259 | "text/plain": [ 260 | "Text(0, 0.5, 'position')" 261 | ] 262 | }, 263 | "execution_count": 16, 264 | "metadata": {}, 265 | "output_type": "execute_result" 266 | }, 267 | { 268 | "data": { 269 | "image/png": "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\n", 270 | "text/plain": [ 271 | "
" 272 | ] 273 | }, 274 | "metadata": { 275 | "needs_background": "light" 276 | }, 277 | "output_type": "display_data" 278 | } 279 | ], 280 | "source": [ 281 | "for p in prior_paths:\n", 282 | " p = np.asarray(p)\n", 283 | " plt.plot(p[:,0],p[:,1], c = 'orangered', alpha = 0.1) \n", 284 | " \n", 285 | " \n", 286 | "for p in post_paths:\n", 287 | " p = np.asarray(p)\n", 288 | " plt.plot(p[:,0],p[:,1] + 0.5, c = 'steelblue', alpha = 0.1, )\n", 289 | "plt.xlabel('step number')\n", 290 | "plt.ylabel('position')" 291 | ] 292 | }, 293 | { 294 | "cell_type": "code", 295 | "execution_count": 17, 296 | "metadata": {}, 297 | "outputs": [ 298 | { 299 | "data": { 300 | "text/plain": [ 301 | "Text(0.5, 0, 'final position')" 302 | ] 303 | }, 304 | "execution_count": 17, 305 | "metadata": {}, 306 | "output_type": "execute_result" 307 | }, 308 | { 309 | "data": { 310 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAUUAAAE9CAYAAACcBXDxAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADh0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uMy4xLjAsIGh0dHA6Ly9tYXRwbG90bGliLm9yZy+17YcXAAAboElEQVR4nO3deZhdVbnn8e9PgpRASCCkaUjgVmxDGGQIFug1CCpepo4J2gSiGBLJNSKTjdISmucqD+ptEC40k8FgGI0yRIG6tspQTO1lDHMgRAqMUDGQIkAuaQwSefuPvRL2TSqpU3VO7b0r+X2eZz1777Wn95zn5M1ae1iliMDMzDIfKDsAM7MqcVI0M8txUjQzy3FSNDPLcVI0M8txUjQzyxlQdgDrs+2220Zzc3PZYZjZBubRRx99LSKGdrWu0kmxubmZuXPnlh2GmW1gJP1pXevcfTYzy3FSNDPLcVI0M8up9DVFM4N3332Xjo4OVqxYUXYo/U5TUxPDhw9n0003rXkfJ0Wziuvo6GDgwIE0Nzcjqexw+o2IYOnSpXR0dDBixIia93P32aziVqxYwZAhQ5wQe0gSQ4YM6XEL20nRrB9wQuyd3nxv3SZFSVdKWiJpXq7uPEnPSXpK0s2SBufWnSGpXdICSYfk6g9Nde2Spvc4UjOrvO9+97vceeedZYdRl1quKV4NXApcm6u7AzgjIlZKOhc4Azhd0m7ARGB3YAfgTkk7p30uA/4B6AAekdQaEc825mOYbTye7ljW0OPtMXxQQ47zt7/9jbPPPrvH+2yyySYNOX+jdNtSjIj7gNfXqLs9IlamxQeB4Wl+PHB9RLwTEX8E2oH9UmmPiBcj4q/A9WlbM+sHFi5cyC677MIxxxzDrrvuypFHHsnbb79Nc3Mzp59+Ovvssw833XQTU6ZMYc6cOQC0tbUxevRo9thjD4477jjeeecdgLX2qZpGXFM8Dvhtmh8GvJxb15Hq1lVvZv3EggULOOGEE5g/fz5bbbUVP/7xjwEYMmQIjz32GBMnTly97YoVK5gyZQo33HADTz/9NCtXrmTGjBmr13e1T1XUlRQlnQmsBGY3JhyQNE3SXElzOzs7G3VYs/J9+tNZ6ad23HFHxowZA8BXvvIVfv/73wNw9NFHr7XtggULGDFiBDvvnF09mzx5Mvfdd9/q9V3tUxW9ToqSpgBjgWPi/b9+tQjYMbfZ8FS3rvq1RMTMiGiJiJahQ7scxMLMSrDmndxVy1tssUWPj9WbfYrSq6Qo6VDgO8C4iHg7t6oVmChpM0kjgJHAw8AjwEhJIyR9kOxmTGt9oZtZkV566SUeeOABAH7+85+z//77r3PbUaNGsXDhQtrb2wG47rrrOPDAAwuJs161PJLzC+ABYJSkDklTye5GDwTukPSEpMsBIuIZ4EbgWeB3wIkR8bd0U+Yk4DZgPnBj2tbM+olRo0Zx2WWXseuuu/LGG2/wjW98Y53bNjU1cdVVVzFhwgT22GMPPvCBD3D88ccXGG3vqcp/97mlpSU8nqJtMM4/P5uedlqPdps/fz677rprHwRUu4ULFzJ27FjmzZvX/cYV09X3J+nRiGjpanu/+2xWlB4mQyuHX/Mzs241Nzf3y1ZibzgpmhWlnz+Ss7FwUjQzy3FSNDPLcVI0M8txUjSzQtxyyy08+2zPB8ZqbW3lnHPO6YOIuuZHcsyKctRRjTnOnx9vzHFW2WF0Y4+3Drfccgtjx45lt912q3mflStXMm7cOMaNG9ejfQYM6H1qc1I0K8oJJ5QdQa8tXLiQQw89lI997GM89thj7L777lx77bU88MADnHbaaaxcuZJ9992XGTNmsNlmmzF9+nRaW1sZMGAABx98MF/84hdpbW3l3nvv5Qc/+AG//OUvATjxxBPp7Oxk880354orrmCXXXZhypQpNDU18fjjjzNmzBj23HNP5s6dy6WXXsrChQs57rjjeO211xg6dChXXXUVO+2001r7XHDBBb3+rE6KZkV5Ow0TsPnm5cbRSwsWLGDWrFmMGTOG4447jgsuuICf/OQntLW1sfPOO3PssccyY8YMJk2axM0338xzzz2HJN58800GDx7MuHHjGDt2LEceeSQABx10EJdffjkjR47koYce4oQTTuCuu+4Csj/Wdf/997PJJptw9dVXr47h5JNPZvLkyUyePJkrr7ySU045hVtuuWWtferha4pmRTn88Kz0U2sOHdbW1tbl8GCDBg2iqamJqVOn8qtf/YrNu/hPYPny5dx///1MmDCBvffem69//essXrx49foJEyZ0mdweeOABvvzlLwMwadKk1cOXrW+fnnJL0cxqsubQYYMHD2bp0qVrbTdgwAAefvhh2tramDNnDpdeeunqFuAq7733HoMHD+aJJ57o8lxlDkfmlqKZ1WTNocNaWlq6HB5s+fLlLFu2jMMPP5wLL7yQJ598EoCBAwfy1ltvAbDVVlsxYsSI1X+OICJWb7c+n/zkJ7n++usBmD17Np/61Kca/jmdFM2sJmsOHXbqqad2OTzYW2+9xdixY9lzzz3Zf//9V9/0mDhxIueddx6jR4/mhRdeYPbs2cyaNYu99tqL3XffnVtvvbXbGC655BKuuuoq9txzT6677jouuuiihn9ODx1mVpRV7z3fc0+PdvPQYfXx0GFmVTVlStkRWA2cFM2K0o+ToocOM7PGe+21rFiluaVoVpT00HJPrylCdnd2zUdirHu9uWfilqJZxTU1NbF06dJe/QPfmEUES5cupampqUf7uaVoVnHDhw+no6ODzs7OskPpd5qamhg+fHiP9nFSNKu4TTfdlBEjRpQdxkbD3Wczsxy3FM2Ksp4/Hm/V4aRoVpSjjy47AquBu89mRXn55axYpbmlaFaUSZOyaS+eU7TiuKVoZpbjpGhmluOkaGaW46RoZpbjGy1mRfn2t8uOwGrgpGhWlM9/vuwIrAbuPpsVZcGCrFildZsUJV0paYmkebm6bSTdIen5NN061UvSxZLaJT0laZ/cPpPT9s9Lmtw3H8eswr7+9axYpdXSUrwaOHSNuulAW0SMBNrSMsBhwMhUpgEzIEuiwPeAjwP7Ad9blUjNzKqk26QYEfcBr69RPR64Js1fAxyRq782Mg8CgyVtDxwC3BERr0fEG8AdrJ1ozcxK19trittFxOI0/wqwXZofBuRf7uxIdeuqNzOrlLrvPkdESGrYOOmSppF1vdlpp50adVizcvz58ffn/7p87bodRhcbj3Wrt0nxVUnbR8Ti1D1ekuoXATvmthue6hYBn16j/p6uDhwRM4GZAC0tLf6jFLbhOOUfy47AatDb7nMrsOoO8mTg1lz9seku9CeAZambfRtwsKSt0w2Wg1Od2cbjgI9nxSqt25aipF+QtfK2ldRBdhf5HOBGSVOBPwFHpc1/AxwOtANvA18FiIjXJX0feCRtd3ZErHnzxmzDNi89o/jRUeXGYevVbVKMiC+tY9VBXWwbwInrOM6VwJU9is5sQ3LW+dl0zhXlxmHr5TdazMxynBTNzHKcFM3McpwUzcxyPHSYWVFOP6nsCKwGTopmRdl3r7IjsBq4+2xWlEeezIpVmluKZkU599Js6ucUK80tRTOzHCdFM7McJ0UzsxwnRTOzHN9oMSvKWaeVHYHVwEnRrCgeMqxfcPfZrCj3PZQVqzS3FM2KcvFPs6lH3640txTNzHKcFM3McpwUzcxynBTNzHJ8o8WsKOecWXYEVgMnRbOifKS57AisBu4+mxXl9nuzYpXmlqJZUWb+LJsefGC5cdh6uaVoZpbjpGhmluOkaGaW46RoZpbjGy1mRbno+2VHYDVwUjQryrD/XHYEVgN3n82KcuttWbFKc0vRrCjXzcmm4w8pNw5bL7cUzcxynBTNzHLqSoqSTpX0jKR5kn4hqUnSCEkPSWqXdIOkD6ZtN0vL7Wl9cyM+gJlZI/U6KUoaBpwCtETER4FNgInAucCFEfER4A1gatplKvBGqr8wbWdmVin1dp8HAB+SNADYHFgMfBZIV5S5BjgizY9Py6T1B0lSnec36z9m/igrVmm9TooRsQg4H3iJLBkuAx4F3oyIlWmzDmBYmh8GvJz2XZm2H9Lb85v1O9tsnRWrtHq6z1uTtf5GADsAWwCH1huQpGmS5kqa29nZWe/hzKrjhtasWKXV033+HPDHiOiMiHeBXwFjgMGpOw0wHFiU5hcBOwKk9YOApWseNCJmRkRLRLQMHTq0jvDMKuamf82KVVo9SfEl4BOSNk/XBg8CngXuBo5M20wGbk3zrWmZtP6uiIg6zm9m1nD1XFN8iOyGyWPA0+lYM4HTgW9Jaie7Zjgr7TILGJLqvwVMryNuM7M+UddrfhHxPeB7a1S/COzXxbYrgAn1nM/MrK/5jRYzsxwPCGFWlOsuLjsCq4GTollRPvShsiOwGrj7bFaUq2/MilWak6JZUX59R1as0pwUzcxynBTNzHKcFM3McpwUzcxy/EiOWVHmXFF2BFYDtxTNzHKcFM2Kcvm1WbFKc1I0K8qd/zcrVmlOimZmOU6KZmY5TopmZjl+JMesKE2blR2B1cBJ0awoP7u07AisBu4+m5nlOCmaFeXCK7JileakaFaUf3s4K1ZpTopmZjlOimZmOU6KZmY5fiTHrChbDyo7AquBk6JZUa44v+wIrAbuPpuZ5TgpmhXlf12SFas0d5/NivLoU2VHYDVwS9HMLMdJ0cwsx0nRzCzH1xTNirL9fyo7AquBk6JZUS75YdkRWA3cfTYzy6krKUoaLGmOpOckzZf095K2kXSHpOfTdOu0rSRdLKld0lOS9mnMRzDrJ757Xlas0uptKV4E/C4idgH2AuYD04G2iBgJtKVlgMOAkalMA2bUeW6z/uXZP2TFKq3XSVHSIOAAYBZARPw1It4ExgPXpM2uAY5I8+OBayPzIDBY0va9jtzMrA/U01IcAXQCV0l6XNJPJW0BbBcRi9M2rwDbpflhwMu5/TtS3X8gaZqkuZLmdnZ21hGemVnP1ZMUBwD7ADMiYjTw/3i/qwxARAQQPTloRMyMiJaIaBk6dGgd4ZmZ9Vw9SbED6IiIh9LyHLIk+eqqbnGaLknrFwE75vYfnurMNg4f3ikrVmm9fk4xIl6R9LKkURGxADgIeDaVycA5aXpr2qUVOEnS9cDHgWW5brbZhu9H/1R2BFaDeh/ePhmYLemDwIvAV8lanzdKmgr8CTgqbfsb4HCgHXg7bWtmVil1JcWIeAJo6WLVQV1sG8CJ9ZzPrF/7zvezqVuMlebX/MyK8uJLZUdgNfBrfmZmOU6KZmY5TopmZjm+pmhWlN12LjsCq4GTollRzv4fZUdgNXD32cwsx0nRrCgnn5kVqzR3n82KsnhJ99tY6dxSNDPLcVI0M8txUjQzy/E1RbOifGzPsiOwGjgpmhXljJPLjsBq4O6zmVmOk6JZUb52Wlas0tx9NivKG8vKjsBq4JaimVmOk6KZWY6ToplZjq8pmhVlzH5lR2A1cFI0K8qpXys7AquBu89mZjlOimZF+cpJWbFKc/fZrCgr3ik7AquBW4pmZjlOimZmOU6KZmY5vqZoVpTPfarsCKwGTopmRTn+2LIjsBq4+2xmluOkaFaUI7+WFas0J0UzsxwnRTOznLqToqRNJD0u6ddpeYSkhyS1S7pB0gdT/WZpuT2tb6733GZmjdaIluI3gfm55XOBCyPiI8AbwNRUPxV4I9VfmLYzM6uUupKipOHAfwV+mpYFfBaYkza5BjgizY9Py6T1B6XtzTYOY/8hK1Zp9T6n+L+B7wAD0/IQ4M2IWJmWO4BhaX4Y8DJARKyUtCxt/1qdMZj1D1OOKjsCq0GvW4qSxgJLIuLRBsaDpGmS5kqa29nZ2chDm5XrL3/JilVaPd3nMcA4SQuB68m6zRcBgyWtaoEOBxal+UXAjgBp/SBg6ZoHjYiZEdESES1Dhw6tIzyzipl0Slas0nqdFCPijIgYHhHNwETgrog4BrgbODJtNhm4Nc23pmXS+rsiInp7fjOzvtAXzymeDnxLUjvZNcNZqX4WMCTVfwuY3gfnNjOrS0MGhIiIe4B70vyLwFp/tiwiVgATGnE+M7O+4jdazMxyPHSYWVEmfL7sCKwGTopmRTl6XNkRWA3cfTYryutvZMUqzS1Fs6JM+042nXNFuXHYermlaGaW46RoZpbjpGhmluOkaGaW4xstZkWZdGT321jpnBTNijL+kLIjsBq4+2xWlEWvZMUqzS1Fs6J885+yqZ9TrDS3FM3McpwUzcxynBTNzHKcFM3Mcnyjxawo075SdgRWAydFs6IcfGDZEVgN3H02K0r7wqxYpbmlaFaU6T/Mpn5OsdLcUjQzy3FSNDPLcVI0M8txUjQzy/GNFrOinPKPZUdgNXBSNCvKAR8vOwKrgbvPZkWZtyArVmluKZoV5azzs6mfU6w0txTNzHKcFM3McpwUzcxynBTNzHJ8o8WsKKefVHYEVoNetxQl7SjpbknPSnpG0jdT/TaS7pD0fJpuneol6WJJ7ZKekrRPoz6EWb+w715ZsUqrp/u8Evh2ROwGfAI4UdJuwHSgLSJGAm1pGeAwYGQq04AZdZzbrP955MmsWKX1OilGxOKIeCzNvwXMB4YB44Fr0mbXAEek+fHAtZF5EBgsafteR27W35x7aVas0hpyo0VSMzAaeAjYLiIWp1WvANul+WHAy7ndOlKdmVll1J0UJW0J/BL47xHx7/l1ERFA9PB40yTNlTS3s7Oz3vDMzHqkrqQoaVOyhDg7In6Vql9d1S1O0yWpfhGwY2734anuP4iImRHREhEtQ4cOrSc8M7Meq+fus4BZwPyIuCC3qhWYnOYnA7fm6o9Nd6E/ASzLdbPNzCqhnucUxwCTgKclPZHq/idwDnCjpKnAn4Cj0rrfAIcD7cDbwFfrOLdZ/3PWaWVHYDXodVKMiN8DWsfqg7rYPoATe3s+s37vo6PKjsBq4DdarLKe7li23vV7DB9UUCQNct9D2dSDzVaak6JZUS7+aTZ1Uqw0J0XrExtcK882Gk6KtsFyYrbe8NBhZmY5TopmZjnuPpsV5Zwzy47AauCkaLYO3V2ThB5el/xIc++DscK4+2xWlNvvzYpVmluKZkWZ+bNsevCB5cZh6+WWoplZjpOimVmOk6KZWY6ToplZjm+0mBXlou+XHYHVwEnRrA89v2T5+wubbplNc3Ujdyg4IOuWu89mBdnytja2vK2t7DCsG24pmhVk0E3ZnytafshaA9NbhTgpWpc87JZtrNx9NjPLcVI0M8txUjQzy/E1RbOCLD7v7LJDsBo4KZoV5L2tB5cdgtXA3Wezggxs/S0DW39bdhjWDbcUzQqyVUqIb407rORIbH2cFDdQfs7QrHfcfTYzy3FSNDPLcffZrMJ8GaR4TopmBfnzJT8qOwSrgZOiWUHiQ01lh2A1cFKsIHeZNkyDbrwZgGVHfaGwc3b3WwL/ntbkGy1mBdny9rvZ8va7yw7DulF4UpR0qKQFktolTS/6/GZm61NoUpS0CXAZcBiwG/AlSbsVGYOZ2foU3VLcD2iPiBcj4q/A9cD4gmMwM1unom+0DANezi13AB8vOIb1asSFad8osQ3JxvZ7rtzdZ0nTgGlpcbmkBXUeclvgtTqP0dccY2P0jxhHH1D9GPvD91hfjH+3rhVFJ8VFwI655eGpbrWImAnMbNQJJc2NiJZGHa8vOMbGcIyNsbHHWPQ1xUeAkZJGSPogMBFoLTgGM7N1KrSlGBErJZ0E3AZsAlwZEc8UGYOZ2foUfk0xIn4D/KbAUzasK96HHGNjOMbG2KhjVET01bHNzPodv+ZnZpazwSZFSRMkPSPpPUktufpmSX+R9EQql1ctxrTujPQq5AJJh5QVY56ksyQtyn13h5cdE/SPV0clLZT0dPre5pYdzyqSrpS0RNK8XN02ku6Q9Hyabl2x+Pr0d7jBJkVgHvBF4L4u1r0QEXuncnzBceV1GWN69XEisDtwKPDj9IpkFVyY++6KvDbcpX726uhn0vdWpcddrib7jeVNB9oiYiTQlpbLcjVrxwd9+DvcYJNiRMyPiHof/O5T64lxPHB9RLwTEX8E2slekbS1+dXROkTEfcDra1SPB65J89cARxQaVM464utTG2xS7MYISY9LulfSp8oOpgtdvQ45rKRY1nSSpKdSt6a0blVOlb+rvABul/RoemuryraLiMVp/hVguzKDWYc++x3266Qo6U5J87oo62spLAZ2iojRwLeAn0vaqmIxlqabeGcA/wXYm+x7/JdSg+1f9o+Ifci6+SdKOqDsgGoR2eMpVXtEpU9/h5V797knIuJzvdjnHeCdNP+opBeAnYE+ufjdmxip4XXIvlJrvJKuAH7dx+HUorTvqiciYlGaLpF0M1m3v6vr3VXwqqTtI2KxpO2BJWUHlBcRr66a74vfYb9uKfaGpKGrblpI+jAwEnix3KjW0gpMlLSZpBFkMT5cckykfyCrfIHsRlHZKv/qqKQtJA1cNQ8cTDW+u3VpBSan+cnArSXGspY+/x1GxAZZ0pfVQdYqfBW4LdX/N+AZ4AngMeDzVYsxrTsTeAFYABxW9veZYroOeBp4iuwfzvZlx5TiOhz4Q/q+ziw7ni7i+zDwZCrPVClG4BdkXdB3029xKjCE7K7z88CdwDYVi69Pf4d+o8XMLGej6z6bma2Pk6KZWY6ToplZjpOimVmOk6KZWY6TojWUpFMkzZc0W9K4ekatkbS8kbGtcezjJR2b5qdI2iG37qcVHlTC+pgfybGGkvQc8LmI6GjAsZZHxJYNCKu789wDnBYRlRnSy8rjlqI1TBqb8sPAbyWdmlpgl6Z1V0u6WNL9kl6UdGSq31JSm6TH0niD630nXNl4mM+lluh8SXMkbZ7WHZQG+ng6DRSwWao/R9KzaQCB81PdWZJOS3G0ALPT2HwfknSP0viWkr6UjjdP0rm5OJZL+qGkJyU9KKmKgyZYLzgpWsNENjbln8nGDbywi022B/YHxgLnpLoVwBciGyzhM8C/SFI3pxoF/DgidgX+HThBUhPZ2HtHR8QeZO/1f0PSELI3h3aPiD2BH6wR8xyy996PiWxsvr+sWpe61OcCnyUbfGBfSauG0doCeDAi9iJ7h/lr3cRs/YSTohXploh4LyKe5f3hqAT8s6SnyF4pG0b3Q1W9HBH/luZ/RpZoRwF/jIg/pPprgAOAZWSJd5akLwJv9yDefYF7IqIzIlYCs9MxAf7K+wMRPAo09+C4VmFOilakd3Lzq1qDxwBDgY9FxN5k74A3dXOcNS+Er/PCeEpm+wFzyFqov+tJwOvxbrx/Qf5v9PMRp+x9TopWtkHAkoh4V9JngL+rYZ+dJP19mv8y8HuygTOaJX0k1U8C7pW0JTAosiHrTwX26uJ4bwEDu6h/GDhQ0rZpZKUvAffW+sGsf/L/bla22cC/Snqa7NreczXss4BsoNYrgWeBGRGxQtJXgZskDSAbUuxyYBvg1nTNUWQDC6/pauBySX8BViVbIhtPcDpwd9r3/0REpYbRssbzIznWr0hqBn4dER8tORTbQLn7bGaW45aimVmOW4pmZjlOimZmOU6KZmY5TopmZjlOimZmOU6KZmY5/x9rtRJc/OvVxwAAAABJRU5ErkJggg==\n", 311 | "text/plain": [ 312 | "
" 313 | ] 314 | }, 315 | "metadata": { 316 | "needs_background": "light" 317 | }, 318 | "output_type": "display_data" 319 | } 320 | ], 321 | "source": [ 322 | "c1,_,_ = plt.hist([p[-1][1] for p in prior_paths], np.linspace(-15.5,15.5,32), alpha = 0.2, label = 'prior');\n", 323 | "c2,_,_ = plt.hist([p[-1][1] for p in post_paths], np.linspace(-15.5,15.5,32), alpha = 0.2, label = 'posterior');\n", 324 | "plt.vlines(condition['obs0'],0,np.max([c1.max(),c2.max()])*1.2, linestyle = 'dashed', color = 'red')\n", 325 | "plt.legend()\n", 326 | "plt.gcf().set_size_inches(5,5)\n", 327 | "plt.xlabel('final position')" 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": null, 333 | "metadata": {}, 334 | "outputs": [], 335 | "source": [] 336 | } 337 | ], 338 | "metadata": { 339 | "kernelspec": { 340 | "display_name": "Python 3", 341 | "language": "python", 342 | "name": "python3" 343 | }, 344 | "language_info": { 345 | "codemirror_mode": { 346 | "name": "ipython", 347 | "version": 3 348 | }, 349 | "file_extension": ".py", 350 | "mimetype": "text/x-python", 351 | "name": "python", 352 | "nbconvert_exporter": "python", 353 | "pygments_lexer": "ipython3", 354 | "version": "3.7.3" 355 | } 356 | }, 357 | "nbformat": 4, 358 | "nbformat_minor": 2 359 | } 360 | --------------------------------------------------------------------------------