├── Day1 └── probAI-day1.pdf ├── Day2-Evening └── probAI-day2_evening.pdf ├── Day2-AfterLunch ├── probAI-day2_after_lunch.pdf └── notebooks │ ├── Figures │ └── simple_pyro_exercise.png │ ├── solution_simple_gaussian_model_pyro.ipynb │ ├── student_simple_gaussian_model_pyro.ipynb │ └── students_bayesian_logistic_regression.ipynb ├── Day2-BeforeLunch ├── probAI-day2_before_lunch.pdf └── notebooks │ ├── Bayesian_linear_regression.png │ ├── Figures │ ├── updating_equations.png │ └── students_simple_model.png │ ├── solution_simple_model.ipynb │ └── students_simple_model.ipynb ├── README.md └── LICENSE /Day1/probAI-day1.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PGM-Lab/2022-ProbAI/HEAD/Day1/probAI-day1.pdf -------------------------------------------------------------------------------- /Day2-Evening/probAI-day2_evening.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PGM-Lab/2022-ProbAI/HEAD/Day2-Evening/probAI-day2_evening.pdf -------------------------------------------------------------------------------- /Day2-AfterLunch/probAI-day2_after_lunch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PGM-Lab/2022-ProbAI/HEAD/Day2-AfterLunch/probAI-day2_after_lunch.pdf -------------------------------------------------------------------------------- /Day2-BeforeLunch/probAI-day2_before_lunch.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PGM-Lab/2022-ProbAI/HEAD/Day2-BeforeLunch/probAI-day2_before_lunch.pdf -------------------------------------------------------------------------------- /Day2-AfterLunch/notebooks/Figures/simple_pyro_exercise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PGM-Lab/2022-ProbAI/HEAD/Day2-AfterLunch/notebooks/Figures/simple_pyro_exercise.png -------------------------------------------------------------------------------- /Day2-BeforeLunch/notebooks/Bayesian_linear_regression.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PGM-Lab/2022-ProbAI/HEAD/Day2-BeforeLunch/notebooks/Bayesian_linear_regression.png -------------------------------------------------------------------------------- /Day2-BeforeLunch/notebooks/Figures/updating_equations.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PGM-Lab/2022-ProbAI/HEAD/Day2-BeforeLunch/notebooks/Figures/updating_equations.png -------------------------------------------------------------------------------- /Day2-BeforeLunch/notebooks/Figures/students_simple_model.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/PGM-Lab/2022-ProbAI/HEAD/Day2-BeforeLunch/notebooks/Figures/students_simple_model.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # ProbAI 2022 - Probabilistic Programming, Variational Inference and Optimization Tutorial with Pryo 2 | 3 | 4 | ## Day 1 (June 13 -- 1.30pm - 4pm) 5 | 6 | * [Slides](https://github.com/PGM-Lab/2022-ProbAI/raw/main/Day1/probAI-day1.pdf) 7 | * Notebook: [students_PPLs_Intro](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day1/notebooks/students_PPLs_Intro.ipynb) 8 | * Notebook: [solutions_PPLs_Intro](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day1/notebooks/solutions_PPLs_Intro.ipynb) 9 | 10 | 11 | ## Day 2 - Before Lunch (June 14 -- 9am-12pm) 12 | * [Slides](https://github.com/PGM-Lab/2022-ProbAI/raw/main/Day2-BeforeLunch/probAI-day2_before_lunch.pdf) 13 | * Notebook: [students_simple_model](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-BeforeLunch/notebooks/students_simple_model.ipynb) 14 | * Notebook: [solutions_simple_model](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-BeforeLunch/notebooks/solution_simple_model.ipynb) 15 | * Notebook: [CAVI-linreg](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-BeforeLunch/notebooks/CAVI-linreg.ipynb) 16 | 17 | 18 | ## Day 2 - After Lunch (June 14 -- 1pm-4pm) 19 | * [Slides](https://github.com/PGM-Lab/2022-ProbAI/raw/main/Day2-AfterLunch/probAI-day2_after_lunch.pdf) 20 | * Notebook: [BayesianNeuralNetworks](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-AfterLunch/notebooks/BayesianNeuralNetworks.ipynb) 21 | * Notebook: [students_BBVI](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-AfterLunch/notebooks/students_BBVI.ipynb) 22 | * Notebook: [solutions_BBVI](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-AfterLunch/notebooks/solutions_BBVI.ipynb) 23 | * Notebook: [student_simple_gaussian_model_pyro](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-AfterLunch/notebooks/student_simple_gaussian_model_pyro.ipynb) 24 | * Notebook: [solution_simple_gaussian_model_pyro](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-AfterLunch/notebooks/solution_simple_gaussian_model_pyro.ipynb) 25 | * Notebook: [bayesian_linear_regression](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-AfterLunch/notebooks/bayesian_linear_regression.ipynb) 26 | * Notebook: [students_bayesian_logistic_regression](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-AfterLunch/notebooks/students_bayesian_logistic_regression.ipynb) 27 | * Notebook: [solutions_bayesian_logistic_regression](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-AfterLunch/notebooks/solutions_bayesian_logistic_regression.ipynb) 28 | 29 | 30 | ## Day 2 - Evening (June 14 -- 4.30pm-5.30pm) 31 | * [Slides](https://github.com/PGM-Lab/2022-ProbAI/raw/main/Day2-Evening/probAI-day2_evening.pdf) 32 | * Notebook: [students_VAE](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-Evening/notebooks/students_VAE.ipynb) 33 | * Notebook: [solutions_VAE](https://colab.research.google.com/github/PGM-Lab/2022-ProbAI/blob/main/Day2-Evening/notebooks/solutions_VAE.ipynb) 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Day2-AfterLunch/notebooks/solution_simple_gaussian_model_pyro.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "colab": { 6 | "name": "solution_simple_gaussian_model_pyro.ipynb", 7 | "provenance": [], 8 | "include_colab_link": true 9 | }, 10 | "kernelspec": { 11 | "display_name": "Python 3", 12 | "language": "python", 13 | "name": "python3" 14 | }, 15 | "language_info": { 16 | "codemirror_mode": { 17 | "name": "ipython", 18 | "version": 3 19 | }, 20 | "file_extension": ".py", 21 | "mimetype": "text/x-python", 22 | "name": "python", 23 | "nbconvert_exporter": "python", 24 | "pygments_lexer": "ipython3", 25 | "version": "3.6.6" 26 | } 27 | }, 28 | "cells": [ 29 | { 30 | "cell_type": "markdown", 31 | "metadata": { 32 | "id": "view-in-github", 33 | "colab_type": "text" 34 | }, 35 | "source": [ 36 | "\"Open" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": { 42 | "id": "dUtkG-f8oeI4" 43 | }, 44 | "source": [ 45 | "" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "metadata": { 51 | "id": "45sg92iioeI7", 52 | "colab": { 53 | "base_uri": "https://localhost:8080/" 54 | }, 55 | "outputId": "d14dc0f2-69f7-42c8-8cc0-4736dbc0ce21" 56 | }, 57 | "source": [ 58 | "!pip install -q --upgrade pyro-ppl torch \n", 59 | "\n", 60 | "import numpy as np\n", 61 | "import torch\n", 62 | "from torch.distributions import constraints\n", 63 | "import matplotlib.pyplot as plt\n", 64 | "\n", 65 | "import pyro\n", 66 | "from pyro.distributions import Normal, Gamma, MultivariateNormal\n", 67 | "from pyro.infer import SVI, Trace_ELBO\n", 68 | "from pyro.optim import Adam\n", 69 | "import pyro.optim as optim" 70 | ], 71 | "execution_count": null, 72 | "outputs": [ 73 | { 74 | "output_type": "stream", 75 | "name": "stdout", 76 | "text": [ 77 | "\u001b[K |████████████████████████████████| 750.6 MB 10 kB/s \n", 78 | "\u001b[?25h" 79 | ] 80 | } 81 | ] 82 | }, 83 | { 84 | "cell_type": "markdown", 85 | "metadata": { 86 | "id": "upVGYRd6oeI8" 87 | }, 88 | "source": [ 89 | "## Generate some data" 90 | ] 91 | }, 92 | { 93 | "cell_type": "code", 94 | "metadata": { 95 | "id": "x1SeB_bboeI8" 96 | }, 97 | "source": [ 98 | "# Sample data\n", 99 | "np.random.seed(123)\n", 100 | "N = 100\n", 101 | "correct_mean = 5\n", 102 | "correct_precision = 1\n", 103 | "data = torch.tensor(np.random.normal(loc=correct_mean, scale=np.sqrt(1./correct_precision), size=N), dtype=torch.float)\n" 104 | ], 105 | "execution_count": null, 106 | "outputs": [] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": { 111 | "id": "Ho5Uc-OToeI9" 112 | }, 113 | "source": [ 114 | "## Our model specification" 115 | ] 116 | }, 117 | { 118 | "cell_type": "code", 119 | "metadata": { 120 | "id": "stcxQyx5oeI9" 121 | }, 122 | "source": [ 123 | "def model(data):\n", 124 | " gamma = pyro.sample(\"gamma\", Gamma(torch.tensor(1.), torch.tensor(1.)))\n", 125 | " mu = pyro.sample(\"mu\", Normal(torch.zeros(1), torch.tensor(10000.0)))\n", 126 | " with pyro.plate(\"data\", len(data)):\n", 127 | " pyro.sample(\"x\", Normal(loc=mu, scale=torch.sqrt(1. / gamma)), obs=data)" 128 | ], 129 | "execution_count": null, 130 | "outputs": [] 131 | }, 132 | { 133 | "cell_type": "markdown", 134 | "metadata": { 135 | "id": "DsM46XV-oeI9" 136 | }, 137 | "source": [ 138 | "## Our guide specification" 139 | ] 140 | }, 141 | { 142 | "cell_type": "code", 143 | "metadata": { 144 | "id": "N2ejdORDoeI-" 145 | }, 146 | "source": [ 147 | "def guide(data=None):\n", 148 | " alpha_q = pyro.param(\"alpha_q\", torch.tensor(1.), constraint=constraints.positive)\n", 149 | " beta_q = pyro.param(\"beta_q\", torch.tensor(1.), constraint=constraints.positive)\n", 150 | " pyro.sample(\"gamma\", Gamma(alpha_q, beta_q))\n", 151 | "\n", 152 | " mean_q = pyro.param(\"mean_q\", torch.tensor(0.))\n", 153 | " scale_q = pyro.param(\"scale_q\", torch.tensor(1.), constraint=constraints.positive)\n", 154 | " pyro.sample(\"mu\", Normal(mean_q, scale_q))" 155 | ], 156 | "execution_count": null, 157 | "outputs": [] 158 | }, 159 | { 160 | "cell_type": "markdown", 161 | "metadata": { 162 | "id": "Cp_F7FgnoeI-" 163 | }, 164 | "source": [ 165 | "## Do learning" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "metadata": { 171 | "colab": { 172 | "base_uri": "https://localhost:8080/" 173 | }, 174 | "id": "D4CViT55oeI-", 175 | "outputId": "ee1de6f8-ff7b-40e7-ab4a-dad06f05aac2" 176 | }, 177 | "source": [ 178 | "# setup the optimizer\n", 179 | "adam_args = {\"lr\": 0.01}\n", 180 | "optimizer = Adam(adam_args)\n", 181 | "\n", 182 | "pyro.clear_param_store()\n", 183 | "svi = SVI(model, guide, optimizer, loss=Trace_ELBO())\n", 184 | "train_elbo = []\n", 185 | "# training loop\n", 186 | "for epoch in range(3000):\n", 187 | " loss = svi.step(data)\n", 188 | " train_elbo.append(-loss)\n", 189 | " if (epoch % 500) == 0:\n", 190 | " print(\"[epoch %03d] average training loss: %.4f\" % (epoch, loss))" 191 | ], 192 | "execution_count": null, 193 | "outputs": [ 194 | { 195 | "output_type": "stream", 196 | "name": "stderr", 197 | "text": [ 198 | "/usr/local/lib/python3.7/dist-packages/pyro/infer/svi.py:53: FutureWarning: The `num_samples` argument to SVI is deprecated and will be removed in a future release. Use `pyro.infer.Predictive` class to draw samples from the posterior.\n", 199 | " \"number of iterations.\",\n" 200 | ] 201 | }, 202 | { 203 | "output_type": "stream", 204 | "name": "stdout", 205 | "text": [ 206 | "[epoch 000] average training loss: 4678.7293\n", 207 | "[epoch 500] average training loss: 277.2488\n", 208 | "[epoch 1000] average training loss: 251.4889\n", 209 | "[epoch 1500] average training loss: 217.9515\n", 210 | "[epoch 2000] average training loss: 174.1540\n", 211 | "[epoch 2500] average training loss: 165.9747\n" 212 | ] 213 | } 214 | ] 215 | }, 216 | { 217 | "cell_type": "code", 218 | "metadata": { 219 | "colab": { 220 | "base_uri": "https://localhost:8080/" 221 | }, 222 | "id": "lpmXAE6xoeJA", 223 | "outputId": "b6a193fd-e360-4faf-a1cd-76f7f7c52e7f" 224 | }, 225 | "source": [ 226 | "for name, value in pyro.get_param_store().items():\n", 227 | " print(name, pyro.param(name).data.numpy())" 228 | ], 229 | "execution_count": null, 230 | "outputs": [ 231 | { 232 | "output_type": "stream", 233 | "name": "stdout", 234 | "text": [ 235 | "alphav 3.4341245\n", 236 | "beta_q 4.0748396\n", 237 | "mean_q 5.015445\n", 238 | "scale_q 0.19180033\n" 239 | ] 240 | } 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "metadata": { 246 | "colab": { 247 | "base_uri": "https://localhost:8080/", 248 | "height": 279 249 | }, 250 | "id": "bb39F8-loeJB", 251 | "outputId": "2e57dc01-e3b2-423b-b6fa-f09ad8e5ac9a" 252 | }, 253 | "source": [ 254 | "plt.plot(range(len(train_elbo)), train_elbo)\n", 255 | "plt.xlabel(\"Number of iterations\")\n", 256 | "plt.ylabel(\"ELBO\")\n", 257 | "plt.show()" 258 | ], 259 | "execution_count": null, 260 | "outputs": [ 261 | { 262 | "output_type": "display_data", 263 | "data": { 264 | "text/plain": [ 265 | "
" 266 | ], 267 | "image/png": "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\n" 268 | }, 269 | "metadata": { 270 | "needs_background": "light" 271 | } 272 | } 273 | ] 274 | } 275 | ] 276 | } -------------------------------------------------------------------------------- /Day2-AfterLunch/notebooks/student_simple_gaussian_model_pyro.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "nbformat": 4, 3 | "nbformat_minor": 0, 4 | "metadata": { 5 | "language_info": { 6 | "codemirror_mode": { 7 | "name": "ipython", 8 | "version": 3 9 | }, 10 | "file_extension": ".py", 11 | "mimetype": "text/x-python", 12 | "name": "python", 13 | "nbconvert_exporter": "python", 14 | "pygments_lexer": "ipython3", 15 | "version": "3.7.0" 16 | }, 17 | "colab": { 18 | "name": "student_simple_gaussian_model_pyro.ipynb", 19 | "provenance": [], 20 | "include_colab_link": true 21 | } 22 | }, 23 | "cells": [ 24 | { 25 | "cell_type": "markdown", 26 | "metadata": { 27 | "id": "view-in-github", 28 | "colab_type": "text" 29 | }, 30 | "source": [ 31 | "\"Open" 32 | ] 33 | }, 34 | { 35 | "cell_type": "markdown", 36 | "metadata": { 37 | "id": "wJ5e7RVcoKT-" 38 | }, 39 | "source": [ 40 | "\n" 41 | ] 42 | }, 43 | { 44 | "cell_type": "code", 45 | "metadata": { 46 | "id": "vNaU7LMtoKUB" 47 | }, 48 | "source": [ 49 | "!pip install -q --upgrade pyro-ppl torch \n", 50 | "\n", 51 | "\n", 52 | "import numpy as np\n", 53 | "import torch\n", 54 | "from torch.distributions import constraints\n", 55 | "import matplotlib.pyplot as plt\n", 56 | "\n", 57 | "import pyro\n", 58 | "from pyro.distributions import Normal, Gamma, MultivariateNormal\n", 59 | "from pyro.infer import SVI, Trace_ELBO\n", 60 | "from pyro.optim import Adam\n", 61 | "import pyro.optim as optim" 62 | ], 63 | "execution_count": null, 64 | "outputs": [] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "metadata": { 69 | "id": "bIp4KvsEoKUB" 70 | }, 71 | "source": [ 72 | "## Generate some data" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "metadata": { 78 | "id": "IvSrjN_4oKUC" 79 | }, 80 | "source": [ 81 | "# Sample data\n", 82 | "np.random.seed(123)\n", 83 | "N = 100\n", 84 | "correct_mean = 5\n", 85 | "correct_precision = 1\n", 86 | "data = torch.tensor(np.random.normal(loc=correct_mean, scale=np.sqrt(1./correct_precision), size=N), dtype=torch.float)\n" 87 | ], 88 | "execution_count": null, 89 | "outputs": [] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": { 94 | "id": "9TAlxpNToKUC" 95 | }, 96 | "source": [ 97 | "## Our model specification" 98 | ] 99 | }, 100 | { 101 | "cell_type": "code", 102 | "metadata": { 103 | "id": "jE4ItwMhoKUD" 104 | }, 105 | "source": [ 106 | "def model(data):\n", 107 | " gamma = pyro.sample(\"gamma\", Gamma(torch.tensor(1.), torch.tensor(1.)))\n", 108 | " mu = pyro.sample(\"mu\", Normal(torch.zeros(1), torch.tensor(10000.0)))\n", 109 | " with pyro.plate(\"data\", len(data)):\n", 110 | " pyro.sample(\"x\", Normal(loc=mu, scale=torch.sqrt(1. / gamma)), obs=data)" 111 | ], 112 | "execution_count": null, 113 | "outputs": [] 114 | }, 115 | { 116 | "cell_type": "markdown", 117 | "metadata": { 118 | "id": "U5AFBtuEoKUD" 119 | }, 120 | "source": [ 121 | "## Our guide specification" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "metadata": { 127 | "id": "venykT3VoKUD" 128 | }, 129 | "source": [ 130 | "# Define the right guide for the above model, including the variational parameters. \n", 131 | "def guide(data=None):\n" 132 | ], 133 | "execution_count": null, 134 | "outputs": [] 135 | }, 136 | { 137 | "cell_type": "markdown", 138 | "metadata": { 139 | "id": "0G7u3JOLoKUE" 140 | }, 141 | "source": [ 142 | "## Do learning" 143 | ] 144 | }, 145 | { 146 | "cell_type": "code", 147 | "metadata": { 148 | "id": "Sds04uVeoKUE", 149 | "outputId": "7779aa97-e02d-48df-d69d-341f96fc28c2" 150 | }, 151 | "source": [ 152 | "# setup the optimizer\n", 153 | "adam_args = {\"lr\": 0.01}\n", 154 | "optimizer = Adam(adam_args)\n", 155 | "\n", 156 | "pyro.clear_param_store()\n", 157 | "svi = SVI(model, guide, optimizer, loss=Trace_ELBO())\n", 158 | "train_elbo = []\n", 159 | "# training loop\n", 160 | "for epoch in range(3000):\n", 161 | " loss = svi.step(data)\n", 162 | " train_elbo.append(-loss)\n", 163 | " if (epoch % 500) == 0:\n", 164 | " print(\"[epoch %03d] average training loss: %.4f\" % (epoch, loss))" 165 | ], 166 | "execution_count": null, 167 | "outputs": [ 168 | { 169 | "output_type": "stream", 170 | "text": [ 171 | "[epoch 000] average training loss: 1599.6830\n", 172 | "[epoch 500] average training loss: 546.2211\n", 173 | "[epoch 1000] average training loss: 284.1279\n", 174 | "[epoch 1500] average training loss: 185.3350\n", 175 | "[epoch 2000] average training loss: 195.8745\n", 176 | "[epoch 2500] average training loss: 178.9226\n" 177 | ], 178 | "name": "stdout" 179 | } 180 | ] 181 | }, 182 | { 183 | "cell_type": "code", 184 | "metadata": { 185 | "id": "Kz5F9TzKoKUF", 186 | "outputId": "64b37913-0438-445e-81e6-c990d148b320" 187 | }, 188 | "source": [ 189 | "for name, value in pyro.get_param_store().items():\n", 190 | " print(name, pyro.param(name))" 191 | ], 192 | "execution_count": null, 193 | "outputs": [ 194 | { 195 | "output_type": "stream", 196 | "text": [ 197 | "rate tensor(1.8581, requires_grad=True)\n", 198 | "conc tensor(2.1757, requires_grad=True)\n", 199 | "mu_mean tensor(5.0201, requires_grad=True)\n", 200 | "mu_scale tensor(0.1044, requires_grad=True)\n" 201 | ], 202 | "name": "stdout" 203 | } 204 | ] 205 | }, 206 | { 207 | "cell_type": "code", 208 | "metadata": { 209 | "id": "-W3H0l_toKUG", 210 | "outputId": "1489c2ea-6b37-4f09-8a8c-523019601964" 211 | }, 212 | "source": [ 213 | "plt.plot(range(len(train_elbo)), train_elbo)\n", 214 | "plt.xlabel(\"Number of iterations\")\n", 215 | "plt.ylabel(\"ELBO\")\n", 216 | "plt.show()" 217 | ], 218 | "execution_count": null, 219 | "outputs": [ 220 | { 221 | "output_type": "display_data", 222 | "data": { 223 | "image/png": "iVBORw0KGgoAAAANSUhEUgAAAZcAAAEKCAYAAADenhiQAAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAALEgAACxIB0t1+/AAAADl0RVh0U29mdHdhcmUAbWF0cGxvdGxpYiB2ZXJzaW9uIDIuMi4yLCBodHRwOi8vbWF0cGxvdGxpYi5vcmcvhp/UCwAAIABJREFUeJzt3Xl8VPW9//HXZyYLIRASdsIW9kU2MYAooiwioBa12qK3VSu/InW5bW9bi1rrVq3Ltbb2WltatWp7r1q6SC2KuFtbFFzYXdgUEGSVnUCS7++PcxJmwkySIWcymfB+Ph7zyMz3fM+Z7zeTnM98l/M95pxDREQkSKFUF0BERBofBRcREQmcgouIiAROwUVERAKn4CIiIoFTcBERkcApuIiISOAUXEREJHAKLiIiEriMVBcgKGY2EfgFEAZ+55y7q7r8rVu3dkVFRfVRNBGRRuOdd97Z5pxrU1O+RhFczCwMPAicCWwAFprZHOfcinj7FBUVsWjRovoqoohIo2Bmn9QmX2PpFhsOrHLOrXHOHQKeBKakuEwiIsetxhJcOgLrI15v8NOimNl0M1tkZou2bt1ab4UTETneNJbgUivOuVnOuWLnXHGbNjV2GYqIyDFqLMFlI9A54nUnP01ERFKgsQSXhUAvM+tmZlnAVGBOisskInLcahSzxZxzpWZ2DTAPbyryI8655SkulojIcatRBBcA59xcYG6qyyEiIo0ouIjUxf5DpZSVO5o3yaxV/i/2H6LcQcvcrMq0NVv30javCc2yj/xb7S0pJSczTDhkbPziAAVNM9m+9xDtWzQB4M/vbKBrq1wcjo75OezYd4h/fryNddv3M6ZvGz774gDZGWFO6dGKjV8cYNbra8jKCDFlSCE92jTjk+37yW+aybOLN7F9Xwmn9mwNwKZdB2mVm8UpPVqzYtMuln+2m10HDvP57oN8pbgz2/aWsOKz3ZgZ553YkdysMI/+ax39O+RRXu7IzAjhHBTmN+Hvizfx9trtnDu4kHMGFfKrV1cxrKglpeWOnMwwQ7vk88mO/azfsZ9Pd+ynaVYG67btY0DHPDbtOkhRq1x2HThMrv97ee/TnbTLa8KzSz5jypCOTBvVjQ07D/De+p2s3rKXcwYV0r8wj/fXf8GidTvo1yGPDzbtodw52jTPJjMcIisjRGbY2LqnhO17D7Fy8x4mD2hPucN/rzDb9h6ibfNsSkrL6dwyh/U7DpCTGSYjbJSUlrOvpJRVW/Yyvn87XlzxOVv2lHDu4A5khUOs3LSHM/q0YeWm3azZuo+BnVrw1todFLVqSqeCHLbvO0RuVgYTB7Rn254S1mzbx5zFn7H3YCnhkDGqV2tO7JzP22t3MGlge1Zt2csHm/fQu11z+rZvzsdb9vLC8s10aZnLCys2M6ZPW8b2bcuCtdtZvnE3h8rKOalrAS+v3EJ+00wOlZWT1ySTolZNGdCxBc8t20xRq1yaZYf5dMd+WjfLZmjXAnKzM9i2p4R12/exc/8hXv9oG93b5HJ67zaEQ8a85Zu5eHgXJg3oQDhkQf37xGTOuaS+QUNVXFzsdBFl41FSWsatf1/BVWf0oFNB02rz7tx3iHtf+JCbz+1PdkaY9Tv2c9o9rwCw+s7JHCotJzsjxD+WbuLa/3uPvu2b8/0JfRjRvSUlpeUU/+TFymMN79aSt9fuSGrdRIL23k1nUhDxxSgRZvaOc664xnwKLpJMuw4cpklmiOyMcI15y8odzy75jHMGFUZ9qzpcVs6yjbt49M11/GLqEA6XOTLDhpmXp2jmP6KO87erT+W62YsZ0a0Vzy/fTNvm2Vw8vAun925D27xs+vzo+WArKZJm1t119jHvq+BSAwWX5Pp890EWrtvBNf/7HsOLWvL0jJGV6Ss37WbTroOs2rKXVz7cwg2T+rFq617ueu6Dyv0zw8bhMkePNrms3rovVdU47vzjP0dx9gP/THUxku6eLw/iuj8vqXydlRHiUGn5MR8vOyNESR32jzSqZ2v+uWpb5evpo7szaUB7ilrlcuLt8+t8/Bsm92X66B7HvL+CSw3qK7g8+fanjO3XlrbNm9Qq/+h7XqFZdgZzv31azO2fbN9HWbmje5tmMbeXlJZRWuYq+7cjvblqG2XljmFFLdm2t4R/r97OV4YduTxo8fov+HDzHgrzcyjIzeSWOcsZ1bMN3dvkMr5fO4p/Mp/zh3bkgqGd2LanhOlPvMMzV5/Kyx9s4RcvfczMSX35anFn5q/8nOtmL4l673MGdeDELgXc/mzc5d4khrU/nczBw+X0+3H9tLbW3XU2W/eUMOwOr+vvhxP7cvfzXtBvlu2NMcx+Z0Pc/U/u3pI/TBvBik27mf74O2zefTBmvg9un0h2Roj5Kz5n+hPvADCub1te+mBLzPx5TTLYfbCUa8b0ZO22ffxj6aaj8rx9wzi27zvEgcNlXPCrf3H/Vwfz3acWH5Xv79eMYmCnFnyyfR97DpZSkJtFx/wcSkrL4rZqf3R2P07u3opzfukF3nMHF3rHWvwZV47uznfG92b2uxu46W/LaJadwbfH9eKOuSsr92+f14SfTx1C+7wmXPLbBXy26yDhkPG9Cb254MROzPjDO7y//guW3DKBrHCIvjd55XjjujF0bhndzfvKB1vIyQrz/LLN/P5f6yrTX/vBGZx+76tHlf29m86MCkpPXzmS4d1axqxnbdQ2uGhAPwB/WrSeH8xewkc/mURWRoiyckdZuePAoTJm/mUp7fKyeeuG8Rw8XMacxZ9x3ewlvHvTmVGDwUDlgCjAb19fw9h+bVmy4QvOHVRIzxufi8r743P6c2KXfHq0bcagW16gV9tmnD+0I/c8/yEAXzu5C39Y8CkAs2eMZPY7G3hy4Xqq2rTrIF8+qSMfbt7DtMeODrYL1+2Mev2HBZ9WHhdgyoNvVj6/67kPolofkZ5dsolnlxx9QmgsrpvYp/J3fyyywiH6FeaxeP0XAAwrKuC+i4ZgZuRkhXnxv0Yz/mevAzB1WOeYn2WF753Zm/vmfwTAo5cP4xu/X1jte19+ShG//9c6ilp5J7E2zbMrt33rjB6VweXNH47l6UXx3xegf4cWZIRDDOqUz4IbxvGPJZvoX5hHt9a59LvpeQ4cLgOgSabXTVoxAQHgd5cVs/tAKYNve4EvDS6kc8scHnxlNVec2o1pp3Vj/Y79nNy9FQcPl/GPpZsY3Dmf/zqzNwAdWjShbZ73gCPdPhXBJfLEmxH2ulO7tsqNKntW2Lvsb3CnFvzsq0MYd99rldsm9G9Pl1ZHTvI/vWAg1/9lqVfnwjxyssKM7duWm/CC8DdHd68MLr/5+kkM6tSCDi1yAJj9rVN45v3PmHF698qu3dkzRlLmHNkZYcrLvS/8fds3PyqwAIzp2xaAk7u34vtn9WHAzfMq6xP5dwLw1g3jKMjN4g/TRjB/xWamn96Djvk58T/AACm41NETCz7hpr8tA+CXL39M62bZvLjyc974eBsvfHc0AJ/vLmHW66u5c+6RE+/D/1zDg6+sjnvcO+aurPzjjDyZV7itSgvg4y17o05ukftc+Ot/x32f+1/8iPtf/Ki6KkotdI4zieDK0d35zetrqt336StH0r8wj4tnLahM++6ZvaNOZj3bNq98fteXB0UFl3F921KYn8MTCz5hTJ82fHN0d+6b/xE3n9u/8kRUoVvrXNZui+5mrAgm00Z1q7acLZpmMm1UN9bv3M/j/45eGHfVHZN45M21XDqyKCr97EEdKp+X+b0kd10wsDItJzNMftNMZk7si5nRomkm/75+LK2bZVNW7th7sJRvj+9Fi5zMypNik8wwT0wbzoDCFjUOSn/j1CIefXMd7fKa0LNtM1Zt2UtGnFlSZsbbN44jPyeLrIwQ6+46m0+37+fP726gc0vvvX/z9ZPoVJBDs+wMCpp6MwubZnmn0Wb+z4kD2kcd96wTol8X5ufwrTOiu6UywqHKk3EoZPxr5tijvnzG0iw7g79cdQobdx4AoGN+U3Kzwuw75AXxdn6wHdWrNaN6tY57nGRQcElQSWkZ33h0ITdM7sfO/YcqAwvAL19eFZV3wv1HvkFEBhag2sBS1Tuf7Kw5kwTu2WtH0btdc/aWlDLU71Y4rVdrcjLD3DrlBEb+9OXKvFkZRy92MeP0HnxvQu/K4NIiJ5NdBw4D3jfrl1Z+ztY9JZVdFGX+N9Znrx3FgI4talXGD26fSEbIyAiHGNuvLcOKWtIkMxx3wHbigPY89Gr0397/O60bTTLDXDy8S43vFwoZt00ZcFRwyQiHauzHz2uSwba9h7hgaKeo473/4wlR+Sq+4WeG4dYpA2Ie67RetVsb8Edn9+d7E/rQJDPMzef25+ZnlsdsDVSo2n3dpVVTvuu3jiA6UPxwYl+6tsplnB/AWzTN5O0bxtUqKNSkMIHWxdAuBQztUgBATlaY5bdNZPveEvb7ASZVFFwS9OHmPfxr9XamP76Iz3bF7k+W9NQxP4eNXxyofN2/Qx6hkNEyI4thRQUsXLeTb4/rRXFRdH/1uzedycJ13nTk8f3acduUE1j+2W7O7N8uKt/U4Z35zWtruPyUIgDG9YveXu5/sw9Z/OsPKgLRPRcO4sTO+ZXdSwBj+rSNuU/FN/bXfnAGhfk5nNarNZf89i0AXvjuaLIzwke1Wv7nkhPZc7A0bjmOxZ9mnMIbH2+NGYiTJRyyyuuOTuvVhpe/f0Zgx87Nzjjq91bRLQdel2ReTu2umwpaq2bZtErJOx+hAf0Erd66N6ovVupH62bZbNtbUvl6zZ2T6X6DtyDD+z8+k1PuejnuN7WQgd8o4Edn9+PELvnkN82iTfNsJv/iDTbsPMBL3zudri2bMvjWF+jephlzrjm1sj8cvPGwh15bzW1fOoEMv2/++WWb2VtSyoUndeLDzXs46+evc8u5/bn81OgTTsVU6dV3TmbPwcPkN439zXbhuh3c9vcV/GnGyKigUWFfSal/8WBiJ+fycoeDqOndf1q0nn4d8mrVQlq8/gtCZgzsdCTv0g27yMoIkZMZZteBw1HbpHHTgL40KlXPp6GIE2V+0yxW3DbxqOtdKjTNyiC/aSYbdh7ghMIWnNT1SMvjqjN6csNfl9I+rwkZ4RDLb5sY8xidWzblzvMHRqVF9q33ad+cBdePo11edtVd+f6E3mSEQ4RDFjewAAwrasnfrx0Vd3usGYC1EYoxxnBRcecYOWMb3Dn/qDQFE6mJgkuCjtOGXspV/N5//bWTaNUs9gn6spFdeXHllqiuLQDDG7TesPMAmeHoE+0lI7pwyYiaxxpqo2JJl6quGdsrkOOLpBMFl4QpuqTCf180mJ/N/4jx/dpWdks9evmwqP77W6cM4NYpR1+xbwYlh70L3GJ1N4lI8BrL/VzqTTq2XCZUGVhOB7efN4Dnv3PkQtLRvdvwt6tPrQws4M33j7xOosLfrj416nU4ZDxw8RC+UtyJvu2bH5VfRIKn4FLPbjqnf+DHvHJ092q3f+3kroG/Z9D++6LBUa8rLiQ7FkM65/ODs/pUvg6Z0bNtc+65cHBUcBKR5NF/Wj2r2ucfhJys6rt6qpnZ2mDkVOmuOlxWt3WarjqjB29cNwZIj/qLNDYKLgmqa69YRij4X3nVK4Crqu66idp47IrhzPYXnkxEIstMdIm4sG1Et5Z8aUhhwu8Xycwqx2NM0UWk3im4JKiuYy4ZSWi51BQ86vqOg+JcC9EkM7g/n8iprU9dOZK2zZtgdSx5C/8CtumnVd9tKCLB02yxBD23rG6LL4aT8C26pkPW9Zt7QW4W/TLyaJeXzee7j1zIWFOgLcjNPGpacCJ6tW3GxcO7MG1U0THtX90yKCKSXGq5JOi5pZvrtH8ybi3aooYlJhJ9y4uHH32BXW52Bm/dMD7qZF1dbOndrhnnn9ipmhw1C4WMn14wMGrRRhFJDwouCaprw2PSwOrHRxL10vdOr1z5NJ5EWy5VV7aNp7qlgyYP7FC5oF9NhsS4AlxE0puCSz2rze1+E9Ejzk3DIiVrPLu6dakMo6h1bq26pQb74y1dWzWle+vcGnKLSDpQcElQOs48SrRbrLZVnFhlltrXI66niTzG7y6tcY07AF77wZhAV60VkdTRgP5xIbHoUttZWtNHd+en/p0nK1oo2RkhfvfPtVFHiLfmVoU0XPRARGqglkuCkjAeH4jq7iKYrJZLrFbckWtLEntPEWlcFFwSFMRJM3Jpkup8f0LvmjP5qltWpmN+DsOKCpjsTyao6Y6DdaliRSukpu5DTREWadwUXBJU1wv7AK4e07PGcYi1P53M1WN61vm9ADLDIf404xQ+2b4fgP97+9Nq8zeNuG9IxX3CaysdF/YUkeApuKTImL5tmXF6/HuOm1lgkwcqDhN5J8d4npg2PGrZlupubhWL89susYrev0NeQscSkfSl4JKgoMZcwiFj5qS+wRysBokEqdN6tYl6nfBtsP3siaxnptaOSOOj4JKgoV0Ljnnff80cW6t8p/U6+h4lsVRdSTieioB4LKvYt0iw5TKiu3cL4RN1YaTIcU3BJUFDuxx7cCms5SrB/WrZfVTbRTArWi7xWgiRKxJXNevrJ9XqPSqM7duOxTdPYET3VgntJyKNi65zaWAeu2I4o2LcXTGWqqHlzZlj2XPwMBN//kZU+pGuvNjRpboerJqWlokl3lpn8RpOmrYs0vgouDQwp/duU3MmX9WxFG8g/ujWUV3v51JXVd/+m6fFvyZHRBqHlHSLmdlFZrbczMrNrLjKtuvNbJWZfWhmZ0WkT/TTVpnZzIj0bmb2lp/+lJklNkiQoIY09jy8W8uE8sfrFqvP0LPurrO58WzvmpyvFNdt1WQRabhSNeayDLgAeD0y0cz6A1OBE4CJwK/MLGxmYeBBYBLQH7jYzwtwN3C/c64nsBOYVj9VSK153xnNA1NPrFXeipZLQwqMACcUegtWaraYSOOTkm4x59xKiDlFdgrwpHOuBFhrZquA4f62Vc65Nf5+TwJTzGwlMBa4xM/zGHAL8FBSK9AA9Glf+3ucVPya400rjjVVeXTvNoysxaB8p4IcBnWKvzpybcolIo1PQxtz6QgsiHi9wU8DWF8lfQTQCvjCOVcaI7/4qmu5/MeILlx2ShET7o9qRPL4FcNj5D7aP39Yu+nVcAzXzIhI2kpacDGzF4FYd8a60Tn3TLLetzpmNh2YDtClS/Xra8WT6AmyW+tc1m7bd0zvVVfNm2Sw52Bp5ZhKrKLfcf7ApJejV9vmnNar9VFrqnXz793Sv1BX7os0NkkLLs658cew20Yg8h67nfw04qRvB/LNLMNvvUTmj1WmWcAsgOLi4kb/NfqvV53K6x9tJRSquM4lNVXOygjxxLQRR6Wf1qsNz3/nNPq0022MRRqbhnYR5Rxgqpllm1k3oBfwNrAQ6OXPDMvCG/Sf47yz5SvAhf7+lwEpaRU1RD3bNuOKiKX4G2I07ds+Ly1vwCYi1UvVVOTzzWwDMBL4h5nNA3DOLQeeBlYAzwNXO+fK/FbJNcA8YCXwtJ8X4IfAf/mD/62Ah+u3NulDQx4iUl9SNVvsr8Bf42y7A7gjRvpcYG6M9DUcmVHW6PRok8vqrcGM2Yzq2Zrnl2+mTfNstu6peYVkEZFj1dC6xaSKk+qwUGZVl4zwJjFojENEkk3BJUEbdh5IKH9dRxOCuDlZ5bE0tCEi9UTBJUH3zvswofzJGOY4e2CHJBxVRCQ4De0iSqnBo98YVutVk+NxDXLemIg0JgouDUhtuq3G9GlbY553bzqTck0NE5EUUrdYAxcZcE7uXrtVkFvmZtG6WfZR6a1yvbS+7XVFvIgkl1ouaeThy4bVaf/+hXnMnjGSwZ3zmTywAx9s3h1QyUREoim4NCA19YrlZtf94you8lo/J3UtCHSas4hIJHWLJVkis3+1DIqINBYKLklwrDFCoUVEGgt1iyWBEX19S0bIGFaU2C2JK4+liCMiaUjBpR6sunNyrfKlMpDMnNSXTgU5qSuAiDQqCi4BysoIcai03Bs7SbPrTGac3qPWeR+7Yjjb92rhSxGJT8ElCY6lAdIsO4MbJvcLvCzJcHrvNqkugog0cAouDcSyW89KdRFERAKj2WIBSs6QiUb0RST9KLgkQeTA/ENfOyl1BRERSREFlwDFmu3Vp71uzCUixx8FlyQI8gZfIiLpSMFFREQCp+ASoGS0WHSFvoikIwWXZFBAEJHjnIJLgNTKEBHxKLgkgWKMiBzvFFxERCRwCi4BqmixqHtMRI53Ci4NnOKUiKQjBRcREQmcgkuALhnRJdVFEBFpELTkfkBW3zmZktIyfvvG2kDvE5ZetxwTEfEouAQkHLKoK/S/O7434/q1TWGJRERSR8ElCczg2+N7pboYIiIpozGXJAiyW0xEJB0puDRwGSGvq+3Unq1SXBIRkdpLSXAxs3vN7AMzW2JmfzWz/Iht15vZKjP70MzOikif6KetMrOZEendzOwtP/0pM8uq7/rUhzP7tUt1EUREai1VLZf5wADn3CDgI+B6ADPrD0wFTgAmAr8ys7CZhYEHgUlAf+BiPy/A3cD9zrmewE5gWr3WJEIyr8w3XfYvImkkJcHFOfeCc67Uf7kA6OQ/nwI86Zwrcc6tBVYBw/3HKufcGufcIeBJYIp5Z9yxwGx//8eA8+qrHlVprEVExNMQxlyuAJ7zn3cE1kds2+CnxUtvBXwREagq0kVEJIWSNhXZzF4E2sfYdKNz7hk/z41AKfDHZJWjSpmmA9MBunQJ/mp69VyJiHiSFlycc+Or225mlwPnAOOcq+xQ2gh0jsjWyU8jTvp2IN/MMvzWS2T+WGWaBcwCKC4uVieWiEiSpGq22ETgOuBLzrn9EZvmAFPNLNvMugG9gLeBhUAvf2ZYFt6g/xw/KL0CXOjvfxnwTH3Voz5oHEdE0lGqrtD/HyAbmO/PglrgnJvhnFtuZk8DK/C6y652zpUBmNk1wDwgDDzinFvuH+uHwJNm9hPgPeDh+q1K/VCXm4ikk5QEF3/acLxtdwB3xEifC8yNkb4GbzZZo6YWjIikk4YwW0xERBoZBZc0oW4xEUknWhU5QNkZISb0b8elI4sCO6bTHV1EJA0puATIzJh1aXFyjp2Uo4qIJIe6xdKE2i8ikk5qDC5mNsDMHjezRf7jMTMbVB+FExGR9FRtcDGzKcBfgVfx1gC7AngN+LO/TeqJusVEJJ3UNOZyG3Cmc25dRNoSM3sZ70r4RnU1vIiIBKOmbrGMKoEFAD8tMxkFkmi6eFJE0lFNLZdSM+vinPs0MtHMuuItzyJ19PBlxazdtq/mjLrQRUTSSE3B5WbgRTO7E3jHTysGZuKt6SV1NE63LxaRRqja4OKc+5uZrQW+B1zrJ68AvuKcW5zswomISHqq8SJKP4hcWg9lERGRRqKmqcitzexmM/tPM2tmZg+Z2TIze8bM4q5sLMHReL6IpKOaZov9L959Vypu2rUW78ZczwK/S27RJJKG80UkndTULdbOOXeDeXf0+sQ5d4+f/oGZXZ3kskkEtWBEJJ3U1HIpA/BvJ7ytyrbypJRIRETSXk0tl+5mNgevV6biOf7rbkktmURRt5iIpJOagkvk+mH/XWVb1deSBLpCX0TSUU3XubwWb5uZPYW3iKXUA12gLyLppC73cxkZWCnSUF4T3WdNRCQe3SxMREQCV+3XbzMbGm8Tx/mqyBoKERGJr6a+nfuq2fZBkAUREZHGo6YB/TH1VRCJR20kEUk/Na0tdl3E84uqbLszWYWSo5mudBGRNFLTgP7UiOfXV9k2MeCyiIhII1FTcLE4z2O9Pm6dO7gw1UUQEWlQagouLs7zWK+PWz+ZMiDVRRARaVBqmi022Mx247VScvzn+K+bJLVkAmj5FxFJTzXNFgvXV0HSTuRJvx46CLX8i4ikE12hf4y6tm5a+VwnfhGRaAouxyikiCIiEpeCSwAUZkREoqUkuJjZ7Wa2xMzeN7MXzKzQTzcze8DMVvnbh0bsc5mZfew/LotIP8nMlvr7PODfkllERFIoVS2Xe51zg5xzQ4BngR/76ZOAXv5jOvAQgJm1BG4GRgDDgZvNrMDf5yHgmxH71fvFncmMZ5otJiLpKCXBxTm3O+JlLkfmXk0BHneeBUC+mXUAzgLmO+d2OOd2AvOBif62POfcAuecAx4HzqufOhx5Xh9NJTXHRCSdpOyOV2Z2B3ApsAuoWCCzI7A+ItsGP6269A0x0kVEJIWS1nIxsxfNbFmMxxQA59yNzrnOwB+Ba5JVjiplmm5mi8xs0datW+t4rNjPRUQkiS0X59z4Wmb9IzAXb0xlI9A5YlsnP20jcEaV9Ff99E4x8scr0yxgFkBxcbFGM0REkiRVs8V6RbycwpEbj80BLvVnjZ0M7HLObQLmARPMrMAfyJ8AzPO37Tazk/1ZYpcCz9RfTTzJXA7faQk3EUlDqRpzucvM+gDlwCfADD99LjAZWAXsB74B4JzbYWa3Awv9fLc553b4z68Cfg/kAM/5j0ZHXW8ikk5SElycc1+Ok+6Aq+NsewR4JEb6IqDelyWOmi1WDyd+TUkWkXSiK/RFRCRwCi7HqL67qdQtJiLpRMElAOGQrtAXEYmk4FJHPzlvAJnh5P8akzkjTUQkaAoudTSwY4tUF0FEpMFRcBERkcApuIiISOAUXEREJHAKLg2cJouJSDpScEkXmiwmImlEwUVERAKn4CIiIoFTcBERkcApuDRwWv5FRNKRgkua0Hi+iKQTBRcREQmcgouIiAROwUVERAKn4NLAOV2jLyJpSMElTZhuRSkiaUTBRUREAqfg0sB1KmgKQKvcrBSXRESk9jJSXQCp3rVjezKgMI8z+rRJdVFERGpNwaWBywyHmHBC+1QXQ0QkIeoWExGRwCm4iIhI4BRcREQkcAouIiISOAUXEREJnIKLiIgETsFFREQCp+AiIiKBU3AREZHAKbiIiEjgUhpczOx7ZubMrLX/2szsATNbZWZLzGxoRN7LzOxj/3FZRPpJZrbU3+cB09r0IiIpl7LgYmadgQnApxHJk4Be/mM68JCftyVwMzACGA7cbGYF/j4PAd+M2G9ifZT/F1NP5KvFnTmhMK8+3k5EJK2ksuVyP3AX8KN5AAAL6klEQVQdRN1qcQrwuPMsAPLNrANwFjDfObfDObcTmA9M9LflOecWOOcc8DhwXn0UvlvrXO6+cBAZYfUsiohUlZIzo5lNATY65xZX2dQRWB/xeoOfVl36hhjpIiKSQklbct/MXgRirRV/I3ADXpdYvTKz6XjdbXTp0qW+315E5LiRtODinBsfK93MBgLdgMX+2Hsn4F0zGw5sBDpHZO/kp20EzqiS/qqf3ilG/nhlmgXMAiguLnbx8omISN3Ue7eYc26pc66tc67IOVeE15U11Dm3GZgDXOrPGjsZ2OWc2wTMAyaYWYE/kD8BmOdv221mJ/uzxC4FnqnvOomISLSGdifKucBkYBWwH/gGgHNuh5ndDiz0893mnNvhP78K+D2QAzznP0REJIVSHlz81kvFcwdcHSffI8AjMdIXAQOSVT4REUmc5tGKiEjgFFxERCRwCi4iIhI4BRcREQmcgouIiAROwUVERAKn4CIiIoFTcBERkcApuIiISOAUXEREJHAKLiIiEjgFFxERCZyCi4iIBE7BRUREAqfgIiIigVNwERGRwCm4iIhI4BRcREQkcAouIiISOAUXEREJnIKLiIgETsFFREQCp+AiIiKBU3AREZHAKbiIiEjgFFxERCRwCi4iIhI4BRcREQlcRqoLkG4evqyYw2Uu1cUQEWnQFFwSNK5fu1QXQUSkwVO3mIiIBE7BRUREAqfgIiIigVNwERGRwKUkuJjZLWa20cze9x+TI7Zdb2arzOxDMzsrIn2in7bKzGZGpHczs7f89KfMLKu+6yMiItFS2XK53zk3xH/MBTCz/sBU4ARgIvArMwubWRh4EJgE9Acu9vMC3O0fqyewE5hW3xUREZFoDa1bbArwpHOuxDm3FlgFDPcfq5xza5xzh4AngSlmZsBYYLa//2PAeSkot4iIREhlcLnGzJaY2SNmVuCndQTWR+TZ4KfFS28FfOGcK62SHpOZTTezRWa2aOvWrUHVQ0REqkjaRZRm9iLQPsamG4GHgNsB5/+8D7giWWWp4JybBczyy7fVzD45xkO1BrYFVrDUaix1aSz1ANWloWosdalrPbrWJlPSgotzbnxt8pnZb4Fn/Zcbgc4Rmzv5acRJ3w7km1mG33qJzF9T+drUJl+cMi9yzhUf6/4NSWOpS2OpB6guDVVjqUt91SNVs8U6RLw8H1jmP58DTDWzbDPrBvQC3gYWAr38mWFZeIP+c5xzDngFuNDf/zLgmfqog4iIxJeqtcXuMbMheN1i64ArAZxzy83saWAFUApc7ZwrAzCza4B5QBh4xDm33D/WD4EnzewnwHvAw/VZEREROVpKgotz7uvVbLsDuCNG+lxgboz0NXizyerTrHp+v2RqLHVpLPUA1aWhaix1qZd6mNezJCIiEpyGdp2LiIg0AgouCYi3BE1DZmbrzGypv8zOIj+tpZnNN7OP/Z8FfrqZ2QN+/ZaY2dAUl/0RM9tiZssi0hIuu5ld5uf/2Mwua0B1CWwZpHqsR2cze8XMVpjZcjP7tp+edp9LNXVJx8+liZm9bWaL/brc6qd3sxjLY/mTpp7y098ys6Ka6pgw55wetXjgTSRYDXQHsoDFQP9Ul6sW5V4HtK6Sdg8w038+E7jbfz4ZeA4w4GTgrRSXfTQwFFh2rGUHWgJr/J8F/vOCBlKXW4Dvx8jb3//7yga6+X934YbwNwh0AIb6z5sDH/nlTbvPpZq6pOPnYkAz/3km8Jb/+34amOqn/xr4lv/8KuDX/vOpwFPV1fFYyqSWS+3FXIImxWU6VlPwlsqB6CVzpgCPO88CvGuIOsQ6QH1wzr0O7KiSnGjZzwLmO+d2OOd2AvPx1q2rV3HqEk9CyyAlpcBxOOc2Oefe9Z/vAVbirYqRdp9LNXWJpyF/Ls45t9d/mek/HPGXx4r8vGYD48zMiF/HhCm41F68JWgaOge8YGbvmNl0P62dc26T/3wzUHHv5nSoY6Jlb+h1CmIZpJTwu1JOxPuWnNafS5W6QBp+LuYt8vs+sAUvWK8m/vJYlWX2t+/CW04rsLoouDR+o5xzQ/FWlL7azEZHbnReWzgtpwymc9l9DwE9gCHAJrxlkNKCmTUD/gx8xzm3O3Jbun0uMeqSlp+Lc67MOTcEb6WS4UDfVJZHwaX2qluapsFyzm30f24B/or3R/d5RXeX/3OLnz0d6pho2RtsnZxzn/snhHLgtxzpfmjQdTGzTLyT8R+dc3/xk9Pyc4lVl3T9XCo4577AW7lkJP7yWDHKVVlmf3sLvOW0AquLgkvtxVyCJsVlqpaZ5ZpZ84rnwAS8pXbm4C2VA9FL5swBLvVn+JwM7Iro6mgoEi37PGCCmRX43RsT/LSUs4CWQarnMhveKhgrnXM/i9iUdp9LvLqk6efSxszy/ec5wJl4Y0jxlseK/LwuBF72W5zx6pi4+pzRkO4PvJkvH+H1Zd6Y6vLUorzd8WZ+LAaWV5QZr2/1JeBj4EWgpZ9ueDdlWw0sBYpTXP7/w+uWOIzX9zvtWMqOt+L2Kv/xjQZUlyf8si7x/6k7ROS/0a/Lh8CkhvI3CIzC6/JaArzvPyan4+dSTV3S8XMZhLf81RK8YPhjP707XnBYBfwJyPbTm/ivV/nbu9dUx0QfukJfREQCp24xEREJnIKLiIgETsFFREQCp+AiIiKBU3AREZHAKbhIo2Bmzszui3j9fTO7JaBj/97MLqw5Z53f5yIzW2lmr1RJLzSz2f7zIZGr9AbwnvlmdlWs9xKpCwUXaSxKgAvMrHWqCxIp4uro2pgGfNM5NyYy0Tn3mXOuIrgNwbumIqgy5OOtkBvrvUSOmYKLNBaleLdv/W7VDVVbHma21/95hpm9ZmbPmNkaM7vLzP7Dvy/GUjPrEXGY8Wa2yMw+MrNz/P3DZnavmS30Fzm8MuK4b5jZHGBFjPJc7B9/mZnd7af9GO+ivofN7N4q+Yv8vFnAbcBXzbvPyFf9VRge8cv8nplN8fe53MzmmNnLwEtm1szMXjKzd/33rli19y6gh3+8eyveyz9GEzN71M//npmNiTj2X8zsefPuxXJPxO/j935Zl5rZUZ+FHD8S+VYl0tA9CCypONnV0mCgH95y+GuA3znnhpt346hrge/4+Yrw1pjqAbxiZj2BS/GWMxlmZtnAm2b2gp9/KDDAecuWVzKzQuBu4CRgJ96K1ec5524zs7F49xFZFKugzrlDfhAqds5d4x/vTrylO67wl/9428xejCjDIOfcDr/1cr5zbrffulvgB7+ZfjmH+McrinjLq723dQPNrK9f1t7+tiF4qwiXAB+a2S+BtkBH59wA/1j5NfzupRFTy0UaDeetaPs48J8J7LbQeff1KMFb8qIiOCzFCygVnnbOlTvnPsYLQn3x1sO61Lxlzt/CWwKll5//7aqBxTcMeNU5t9V5S53/Ee9GYsdqAjDTL8OreMt6dPG3zXfOVdxDxoA7zWwJ3vIsHTmyLH48o4A/ADjnPgA+ASqCy0vOuV3OuYN4rbOueL+X7mb2SzObCOyOcUw5TqjlIo3Nz4F3gUcj0krxv0iZWQjvboEVSiKel0e8Lif6/6PqOkkO74R9rXMuasFFMzsD2HdsxU+YAV92zn1YpQwjqpThP4A2wEnOucNmtg4vEB2ryN9bGZDhnNtpZoPxbgQ2A/gK3vphchxSy0UaFf+b+tN4g+MV1uF1QwF8Ce8ufYm6yMxC/jhMd7xF/eYB3zJv2XbMrLd5q09X523gdDNrbWZh4GLgtQTKsQfvlrwV5gHXmpn5ZTgxzn4tgC1+YBmD19KIdbxIb+AFJfzusC549Y7J724LOef+DPwIr1tOjlMKLtIY3QdEzhr7Ld4JfTHePS6OpVXxKV5geA6Y4XcH/Q6vS+hdfxD8N9TQG+C85eZn4i2Fvhh4xzn3THX7VPEK0L9iQB+4HS9YLjGz5f7rWP4IFJvZUryxog/88mzHGytaVnUiAfArIOTv8xRwud99GE9H4FW/i+4PwPUJ1EsaGa2KLCIigVPLRUREAqfgIiIigVNwERGRwCm4iIhI4BRcREQkcAouIiISOAUXEREJnIKLiIgE7v8DczkENBjqMxMAAAAASUVORK5CYII=\n", 224 | "text/plain": [ 225 | "
" 226 | ] 227 | }, 228 | "metadata": { 229 | "tags": [] 230 | } 231 | } 232 | ] 233 | } 234 | ] 235 | } -------------------------------------------------------------------------------- /Day2-AfterLunch/notebooks/students_bayesian_logistic_regression.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "id": "view-in-github", 7 | "colab_type": "text" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": { 16 | "id": "wXcRh2TQfyhp" 17 | }, 18 | "source": [ 19 | "## Setup\n", 20 | "Let's begin by installing and importing the modules we'll need." 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": null, 26 | "metadata": { 27 | "id": "EggRgZ1gfyhq" 28 | }, 29 | "outputs": [], 30 | "source": [ 31 | "!pip install -q pyro-ppl torch\n", 32 | "\n", 33 | "import numpy as np\n", 34 | "import pandas as pd\n", 35 | "import seaborn as sns\n", 36 | "import torch\n", 37 | "import types\n", 38 | "import matplotlib.pyplot as plt\n", 39 | "from pyro.infer import Predictive\n", 40 | "import pyro\n", 41 | "from pyro.distributions import Normal, Uniform, Delta, Gamma, Binomial\n", 42 | "from pyro.infer import SVI, Trace_ELBO\n", 43 | "from pyro.optim import Adam\n", 44 | "import torch.distributions.constraints as constraints\n", 45 | "import pyro.optim as optim\n", 46 | "from pyro.contrib.autoguide import AutoNormal\n", 47 | "import matplotlib.pyplot as plt\n", 48 | "\n", 49 | "import warnings\n", 50 | "warnings.simplefilter(action='ignore', category=FutureWarning)\n", 51 | "\n", 52 | "import ssl\n", 53 | "ssl._create_default_https_context = ssl._create_unverified_context\n", 54 | "\n", 55 | "# for CI testing\n", 56 | "pyro.set_rng_seed(1)\n", 57 | "pyro.enable_validation(True)" 58 | ] 59 | }, 60 | { 61 | "cell_type": "markdown", 62 | "metadata": { 63 | "id": "KtC9nacRfyhq" 64 | }, 65 | "source": [ 66 | "# Dataset \n", 67 | "\n", 68 | "The following example is taken from \\[1\\]. We would like to explore the relationship between topographic heterogeneity of a nation as measured by the Terrain Ruggedness Index (variable *rugged* in the dataset) and its GDP per capita. In particular, it was noted by the authors in \\[1\\] that terrain ruggedness or bad geography is related to poorer economic performance outside of Africa, but rugged terrains have had a reverse effect on income for African nations. Let us look at the data \\[2\\] and investigate this relationship. We will be focusing on three features from the dataset:\n", 69 | " - `cont_africa`: whether the given nation is in Africa\n", 70 | " - `rugged`: quantifies the Terrain Ruggedness Index\n", 71 | " - `rgdppc_2000`: Real GDP per capita for the year 2000\n", 72 | " \n", 73 | " \n", 74 | "We will take the logarithm for the response variable GDP as it tends to vary exponentially. " 75 | ] 76 | }, 77 | { 78 | "cell_type": "code", 79 | "execution_count": null, 80 | "metadata": { 81 | "id": "akcHul9xfyhr" 82 | }, 83 | "outputs": [], 84 | "source": [ 85 | "DATA_URL = \"https://raw.githubusercontent.com/pyro-ppl/brmp/master/brmp/examples/rugged_data.csv\"\n", 86 | "data = pd.read_csv(DATA_URL, encoding=\"ISO-8859-1\")\n", 87 | "df = data[[\"cont_africa\", \"rugged\", \"rgdppc_2000\"]]\n", 88 | "df = df[np.isfinite(df.rgdppc_2000)]\n", 89 | "df[\"rgdppc_2000\"] = np.log(df[\"rgdppc_2000\"])\n", 90 | "\n", 91 | "data = torch.tensor(df.values, dtype=torch.float)\n", 92 | "x_data, y_data = data[:, (1,2)], data[:, 0]" 93 | ] 94 | }, 95 | { 96 | "cell_type": "code", 97 | "execution_count": null, 98 | "metadata": { 99 | "id": "EjOGg_Dafyhu" 100 | }, 101 | "outputs": [], 102 | "source": [ 103 | "# Display first 10 entries \n", 104 | "display(df[0:10])" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": { 111 | "id": "itLI29xgqkaV" 112 | }, 113 | "outputs": [], 114 | "source": [ 115 | "def prepare_figure(title='Scatter plot of data', x_data_ = None, y_data_ = None):\n", 116 | " \"\"\"\n", 117 | " Plot the data and return the figure axis for possible subsequent additional plotting.\n", 118 | " :param title: Title of the plot\n", 119 | " :param x_data_: Nx2 numpy array or torch tensor\n", 120 | " :param y_data_: Nx1 numpy array or torch tensor with the class labels.\n", 121 | " :return: Figure axis.\n", 122 | " \"\"\"\n", 123 | " if x_data_ is None and y_data_ is None:\n", 124 | " x_data_ = x_data\n", 125 | " y_data_ = y_data\n", 126 | "\n", 127 | " if type(x_data_) is torch.Tensor:\n", 128 | " x_data_ = x_data_.numpy()\n", 129 | " y_data_ = y_data_.numpy()\n", 130 | "\n", 131 | " xx, yy = np.mgrid[np.floor(np.min(x_data_[:, 0])):np.ceil(np.max(x_data_[:, 0])):.01,\n", 132 | " np.floor(np.min(x_data_[:, 1])):np.ceil(np.max(x_data_[:, 1])):.01]\n", 133 | "\n", 134 | " grid = torch.tensor(np.c_[xx.ravel(), yy.ravel()], dtype=torch.float32)\n", 135 | "\n", 136 | " f, ax = plt.subplots(figsize=(8, 6))\n", 137 | " f.suptitle(title, fontsize=16)\n", 138 | "\n", 139 | " ax.scatter(x_data[y_data_==0,0], x_data[y_data_==0, 1], c='g', s=50,\n", 140 | " cmap=\"RdBu\", vmin=-.2, vmax=1.2,\n", 141 | " edgecolor=\"white\", linewidth=1, label='Non-African')\n", 142 | "\n", 143 | " ax.scatter(x_data[y_data_==1,0], x_data[y_data_==1, 1], c='orange', s=50,\n", 144 | " cmap=\"RdBu\", vmin=-.2, vmax=1.2,\n", 145 | " edgecolor=\"white\", linewidth=1, label='African')\n", 146 | "\n", 147 | " ax.set(aspect=\"equal\",\n", 148 | " xlim=(0, 7), ylim=(6, 11),\n", 149 | " xlabel=\"Rugged\", ylabel=\"Log GDP\")\n", 150 | "\n", 151 | " ax.legend()\n", 152 | "\n", 153 | " return ax, grid, xx, yy" 154 | ] 155 | }, 156 | { 157 | "cell_type": "code", 158 | "execution_count": null, 159 | "metadata": { 160 | "id": "sgTWhdZIqkaW" 161 | }, 162 | "outputs": [], 163 | "source": [ 164 | "prepare_figure()\n", 165 | "plt.show()" 166 | ] 167 | }, 168 | { 169 | "cell_type": "markdown", 170 | "metadata": { 171 | "id": "vFJeNXiUfyhx" 172 | }, 173 | "source": [ 174 | "# 1. Logistic Regression\n", 175 | "\n", 176 | "Logistic Regression is one of the most commonly used supervised learning tasksin machine learning. Suppose we're given a dataset $\\mathcal{D}$ of the form\n", 177 | "\n", 178 | "$$ \\mathcal{D} = \\{ ({\\bf x_i}, y_i) \\} \\qquad \\text{for}\\qquad i=1,2,...,N$$\n", 179 | "\n", 180 | "where ${\\bf X_i}\\in {\\mathbb R}^m$ and $y_i\\in \\{0,1\\}$.\n", 181 | "\n", 182 | "The goal of logistic regression is to fit a model that correctly predicts the probabilities of the class labels:\n", 183 | "\n", 184 | "$$ p(y|x) = \\frac{1}{1+e^{-b -{\\bf w}^T {\\bf x} }}$$\n", 185 | "\n", 186 | "where ${\\bf w}$ and $b$ are learnable parameters. Specifically $w$ is a vector of weights and $b$ is a bias term.\n", 187 | "\n", 188 | "First we implement a logistic regression model in PyTorch and learn point estimates for the parameters ${\\bf w}$ and $b$. Afterwards we'll see how to incorporate uncertainty into our estimates by using Pyro to doing Bayesian logistic regression." 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "metadata": { 194 | "id": "hHG9QQYhfyhy" 195 | }, 196 | "source": [ 197 | "## 1.1 Model\n", 198 | "Using a logistic regresison model, we want to predict whether a nation is african or not as a function of the terrain rugedness index and log GDP per capita of a nation. \n", 199 | "\n", 200 | "Our input `x_data` is a tensor of size $N \\times 2$ and our output `y_data` is a tensor of size $N \\times 1$. The method `predict(self,x_data)` defines a sigmoid transformation of the form $\\mathit{sigmoid}({\\bf x}^T{\\bf w} + b)$, where ${\\bf w}$ is the weight vector and $b$ is the additive bias.\n", 201 | "\n", 202 | "The parameters of the model are defined using ``torch.nn.Parameter``, and will be learned during training. " 203 | ] 204 | }, 205 | { 206 | "cell_type": "code", 207 | "execution_count": null, 208 | "metadata": { 209 | "id": "NBQBgFkPfyhz" 210 | }, 211 | "outputs": [], 212 | "source": [ 213 | "class LogisticRegressionModel():\n", 214 | " def __init__(self):\n", 215 | " self.w = torch.nn.Parameter(torch.zeros(1, 2))\n", 216 | " self.b = torch.nn.Parameter(torch.zeros(1, 1))\n", 217 | "\n", 218 | " def params(self):\n", 219 | " return {\"b\":self.b, \"w\": self.w}\n", 220 | "\n", 221 | " def predict(self, x_data):\n", 222 | " return torch.sigmoid(-self.b - torch.mm(self.w, torch.t(x_data))).squeeze(0)\n", 223 | "\n", 224 | " def logits(self, x_data):\n", 225 | " return (self.b + torch.mm(self.w, torch.t(x_data))).squeeze(0)" 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": null, 231 | "metadata": { 232 | "id": "h80i4g8xqkaY" 233 | }, 234 | "outputs": [], 235 | "source": [ 236 | "logistic_regression_model = LogisticRegressionModel()" 237 | ] 238 | }, 239 | { 240 | "cell_type": "markdown", 241 | "metadata": { 242 | "id": "mlGU_7YPfyhz" 243 | }, 244 | "source": [ 245 | "## 1.2 Training\n", 246 | "For training we will use the cross entropy as our loss and Adam as our optimizer. We will use a somewhat large learning rate of `0.05` and run for 1000 iterations." 247 | ] 248 | }, 249 | { 250 | "cell_type": "code", 251 | "execution_count": null, 252 | "metadata": { 253 | "id": "_N6WPDJufyh0", 254 | "scrolled": true 255 | }, 256 | "outputs": [], 257 | "source": [ 258 | "def train(num_iterations = 1000):\n", 259 | " loss_fn = torch.nn.BCEWithLogitsLoss(reduction='sum')\n", 260 | " optim = torch.optim.Adam(logistic_regression_model.params().values(), lr=0.05)\n", 261 | "\n", 262 | " for j in range(num_iterations):\n", 263 | " # run the model forward on the data\n", 264 | " logits = logistic_regression_model.logits(x_data)\n", 265 | " # calculate the cross-entropy loss\n", 266 | " loss = loss_fn(logits,y_data)\n", 267 | " # initialize gradients to zero\n", 268 | " optim.zero_grad()\n", 269 | " # backpropagate\n", 270 | " loss.backward()\n", 271 | " # take a gradient step\n", 272 | " optim.step()\n", 273 | " if (j + 1) % 500 == 0:\n", 274 | " print(\"[iteration %04d] loss: %.4f\" % (j + 1, loss.item()))\n", 275 | " # Inspect learned parameters\n", 276 | " print(\"Learned parameters:\")\n", 277 | " for name, param in logistic_regression_model.params().items():\n", 278 | " print(name, param.data.numpy())" 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": null, 284 | "metadata": { 285 | "id": "g_F9KDFyqkaZ" 286 | }, 287 | "outputs": [], 288 | "source": [ 289 | "train()" 290 | ] 291 | }, 292 | { 293 | "cell_type": "markdown", 294 | "metadata": { 295 | "id": "LyfAY0h-fyh0" 296 | }, 297 | "source": [ 298 | "## 1.3 Evaluating the model" 299 | ] 300 | }, 301 | { 302 | "cell_type": "markdown", 303 | "metadata": { 304 | "id": "tmgazCZJfyh1" 305 | }, 306 | "source": [ 307 | "We now plot the decision line learned for african and non-afrian nations relating the rugeedness index with the GDP of the country." 308 | ] 309 | }, 310 | { 311 | "cell_type": "code", 312 | "execution_count": null, 313 | "metadata": { 314 | "id": "JWUs5dc1fyh1" 315 | }, 316 | "outputs": [], 317 | "source": [ 318 | "ax, grid, xx, yy = prepare_figure('Decision line')\n", 319 | "probs = logistic_regression_model.predict(grid).reshape(xx.shape).detach().numpy()\n", 320 | "ax.contour(xx, yy, probs, levels=[.5], cmap=\"Reds\", vmin=0, vmax=.6)\n", 321 | "plt.show()" 322 | ] 323 | }, 324 | { 325 | "cell_type": "markdown", 326 | "metadata": { 327 | "id": "2yrEaqT5fyh3" 328 | }, 329 | "source": [ 330 | "# 2. Bayesian Logistic Regression\n", 331 | "\n", 332 | "\n", 333 | "[Bayesian modeling](http://mlg.eng.cam.ac.uk/zoubin/papers/NatureReprint15.pdf) offers a systematic framework for reasoning about model uncertainty. Instead of just learning point estimates, we're going to learn a _distribution_ over variables that are consistent with the observed data.\n", 334 | "\n", 335 | "In order to make our linear regression Bayesian, we need to put priors on the parameters ${\\bf w}$ and $b$. These are distributions that represent our prior belief about reasonable values for $\\{bf w}$ and ${\\bf b}$ (before observing any data).\n", 336 | "\n", 337 | "A graphical representation would be as follows:\n", 338 | "\n", 339 | "\n" 340 | ] 341 | }, 342 | { 343 | "cell_type": "markdown", 344 | "metadata": { 345 | "id": "kltwl1J9fyh3" 346 | }, 347 | "source": [ 348 | "## 2.1 Model\n", 349 | "\n", 350 | "We now have all the ingredients needed to specify our model. First we define priors over weights and bias. The prior on the intercept parameter is very flat as we would like this to be learnt from the data. We are using a weakly regularizing prior on the regression coefficients to avoid overfitting to the data.\n", 351 | "\n", 352 | "We use the `obs` argument to the `pyro.sample` statement to condition on the observed data `y_data`." 353 | ] 354 | }, 355 | { 356 | "cell_type": "markdown", 357 | "metadata": { 358 | "id": "NUWfkBXUfyh3" 359 | }, 360 | "source": [ 361 | "### Exercise \n", 362 | " \n", 363 | "* Define a random variable \"b\" to model the intercept. \n", 364 | "* Define the class random variable \"african/non-african\" for the predicited labels.\n", 365 | "* This random variable is defined as Binomial distribution and is parametrized with the logits. \n", 366 | "* If time permits, explore and experiment with the notebook; e.g., specification of prior distributions, manually specified guides, and modifications to the model." 367 | ] 368 | }, 369 | { 370 | "cell_type": "code", 371 | "execution_count": null, 372 | "metadata": { 373 | "id": "_19buBJsfyh4" 374 | }, 375 | "outputs": [], 376 | "source": [ 377 | "def model(x_data, y_data):\n", 378 | " # weight and bias priors\n", 379 | " with pyro.plate(\"plate_w\", 2):\n", 380 | " w = pyro.sample(\"w\", Normal(torch.zeros(1,1), torch.ones(1,1)))\n", 381 | "\n", 382 | " # Define a random variable \"b\" to model the intercept.\n", 383 | " \n", 384 | "\n", 385 | " with pyro.plate(\"map\", len(x_data)):\n", 386 | " # Compute logits (i.e. log p(x=0)/p(x=1)) as a linear combination between data and weights.\n", 387 | " logits = (b + torch.mm(x_data,torch.t(w))).squeeze(-1)\n", 388 | " # Define a Binomial distribution as the observed value parameterized by the logits.\n", 389 | " " 390 | ] 391 | }, 392 | { 393 | "cell_type": "markdown", 394 | "metadata": { 395 | "id": "zcu6i1mYfyh6" 396 | }, 397 | "source": [ 398 | "## 2.2 Guide\n", 399 | "\n", 400 | "In order to do inference we're going to need a guide, i.e. a variational family of distributions. We will use Pyro's [autoguide library](https://docs.pyro.ai/en/stable/infer.autoguide.html). Under the hood, this defines a `guide` function, which in this case provides us with `Normal` variation distributions with learnable parameters, one for each sample `sample()` statement in the model." 401 | ] 402 | }, 403 | { 404 | "cell_type": "code", 405 | "execution_count": null, 406 | "metadata": { 407 | "id": "qtcC93Jkfyh7" 408 | }, 409 | "outputs": [], 410 | "source": [ 411 | "guide = AutoNormal(model)" 412 | ] 413 | }, 414 | { 415 | "cell_type": "markdown", 416 | "metadata": { 417 | "id": "ktwd6CCUfyh8" 418 | }, 419 | "source": [ 420 | "## 2.3 Inference\n", 421 | "\n", 422 | "To do inference we'll use stochastic variational inference (SVI). Just like in the non-Bayesian linear regression, each iteration of our training loop will take a gradient step, but now we will use the ELBO objective instead of binary cross entropy by constructing a `Trace_ELBO` object that we pass to `SVI`. " 423 | ] 424 | }, 425 | { 426 | "cell_type": "markdown", 427 | "metadata": { 428 | "id": "py-1QUeyfyh9" 429 | }, 430 | "source": [ 431 | "To take an ELBO gradient step we simply call the step method of SVI. Notice that the data argument we pass to step will be passed to both model() and guide(). " 432 | ] 433 | }, 434 | { 435 | "cell_type": "code", 436 | "execution_count": null, 437 | "metadata": { 438 | "id": "4Wh1Tyqjfyh9" 439 | }, 440 | "outputs": [], 441 | "source": [ 442 | "def train_vi(x_data, y_data, model, guide=None, num_iterations = 1000):\n", 443 | " optim = Adam({\"lr\": 0.1})\n", 444 | "\n", 445 | " # if no guide is provided, resort to an autoguide\n", 446 | " guide_ = guide if guide is not None else AutoNormal(model)\n", 447 | "\n", 448 | " svi = SVI(model, guide_, optim, loss=Trace_ELBO(), num_samples=10)\n", 449 | "\n", 450 | " pyro.clear_param_store()\n", 451 | " for j in range(num_iterations):\n", 452 | " # calculate the loss and take a gradient step\n", 453 | " loss = svi.step(x_data, y_data)\n", 454 | " if j % 500 == 0:\n", 455 | " print(\"[iteration %04d] loss: %.4f\" % (j + 1, loss / len(data)))" 456 | ] 457 | }, 458 | { 459 | "cell_type": "markdown", 460 | "metadata": { 461 | "id": "0_7bGZH8qkac" 462 | }, 463 | "source": [ 464 | "Learn the model" 465 | ] 466 | }, 467 | { 468 | "cell_type": "code", 469 | "execution_count": null, 470 | "metadata": { 471 | "id": "r11Qa4DSqkac" 472 | }, 473 | "outputs": [], 474 | "source": [ 475 | "guide = AutoNormal(model)\n", 476 | "train_vi(x_data, y_data, model, guide=guide)" 477 | ] 478 | }, 479 | { 480 | "cell_type": "markdown", 481 | "metadata": { 482 | "id": "b8GLwJV6qkac" 483 | }, 484 | "source": [ 485 | "Get the learned parameters" 486 | ] 487 | }, 488 | { 489 | "cell_type": "code", 490 | "execution_count": null, 491 | "metadata": { 492 | "id": "NfaPyhfTfyh9" 493 | }, 494 | "outputs": [], 495 | "source": [ 496 | "for name, value in pyro.get_param_store().items():\n", 497 | " print(name, pyro.param(name).data.numpy())" 498 | ] 499 | }, 500 | { 501 | "cell_type": "markdown", 502 | "metadata": { 503 | "id": "PKfYcpnYfyh-" 504 | }, 505 | "source": [ 506 | "As you can see, instead of just point estimates, we now have uncertainty estimates over our model parameters." 507 | ] 508 | }, 509 | { 510 | "cell_type": "markdown", 511 | "metadata": { 512 | "id": "pag7bEcmqkad" 513 | }, 514 | "source": [ 515 | "## 2.4 Model Evaluation: Model's Uncertainty\n", 516 | "We will sample different logistic regression lines to see how using a Bayesian approach can capture model undertainty.\n", 517 | "\n", 518 | "Here we again rely on Pyro's Predictive class, which allows for easy sampling of the model parameters." 519 | ] 520 | }, 521 | { 522 | "cell_type": "code", 523 | "execution_count": null, 524 | "metadata": { 525 | "id": "AgYRa4h9qkad" 526 | }, 527 | "outputs": [], 528 | "source": [ 529 | "ax, grid, xx, yy = prepare_figure('Model evaluation')\n", 530 | "num_samples=10\n", 531 | "predictive = pyro.infer.Predictive(model, guide=guide, num_samples=num_samples)\n", 532 | "svi_samples = predictive(grid, None)\n", 533 | "\n", 534 | "# Plot the mean decision surface \n", 535 | "logits = torch.mean(torch.mm(grid, torch.t(svi_samples['w'].squeeze())) + svi_samples['b'].squeeze(), axis=1).squeeze(-1)\n", 536 | "probs = Binomial(logits = logits).mean\n", 537 | "ax.contour(xx, yy, probs.reshape(xx.shape).detach().numpy(), levels=[.5], cmap=\"Reds\", vmin=0, vmax=1.5)\n", 538 | "\n", 539 | "# Sample and plot decision surfaces\n", 540 | "for i in range(num_samples):\n", 541 | " logits = (torch.mm(grid, torch.t(svi_samples['w'][i,:])) + svi_samples['b'][i,:]).squeeze(-1)\n", 542 | " probs = Binomial(logits = logits).mean\n", 543 | " ax.contour(xx, yy, probs.reshape(xx.shape).detach().numpy(), levels=[.5], cmap=\"Greys\", vmin=0, vmax=1.5)\n", 544 | "\n", 545 | "plt.show()" 546 | ] 547 | }, 548 | { 549 | "cell_type": "markdown", 550 | "metadata": { 551 | "id": "Pm7rm2Uhqkad" 552 | }, 553 | "source": [ 554 | "The above figure shows the uncertainty in our estimate of the logistic regression line. Note that for lower values of ruggedness there are many more data points, and as such, the regression lines are less uncertainty than for high ruggness values, where there is much more uncertainty. " 555 | ] 556 | }, 557 | { 558 | "cell_type": "markdown", 559 | "metadata": { 560 | "id": "CptrzXtXfyiG" 561 | }, 562 | "source": [ 563 | "## 2.5 The relationship between ruggedness and log GPD\n", 564 | "\n", 565 | "Finally, we can look about the uncertainty about the weights associated to Terrain Rugedness and logarithm of GDP. " 566 | ] 567 | }, 568 | { 569 | "cell_type": "markdown", 570 | "metadata": { 571 | "id": "EOvNBT14qkad" 572 | }, 573 | "source": [ 574 | "Recall the learned parameters:" 575 | ] 576 | }, 577 | { 578 | "cell_type": "code", 579 | "execution_count": null, 580 | "metadata": { 581 | "id": "maJ-Mxw6qkad" 582 | }, 583 | "outputs": [], 584 | "source": [ 585 | "for name, value in pyro.get_param_store().items():\n", 586 | " print(name, pyro.param(name).data.numpy())" 587 | ] 588 | }, 589 | { 590 | "cell_type": "code", 591 | "execution_count": null, 592 | "metadata": { 593 | "id": "hrGPEIGLqkad" 594 | }, 595 | "outputs": [], 596 | "source": [ 597 | "import scipy.stats as stats\n", 598 | "\n", 599 | "f, ax = plt.subplots(1, 2, figsize=(8, 6), sharex=True)\n", 600 | "for i in range(2):\n", 601 | " mu = pyro.param('AutoNormal.locs.w')[0,i].data.numpy().squeeze()\n", 602 | " std = pyro.param('AutoNormal.scales.w')[0,i].data.numpy().squeeze()\n", 603 | " #x = np.linspace(mu - 3*std, mu + 3*std, 100)\n", 604 | " x = np.linspace(-2,1, 100)\n", 605 | " ax[i].plot(x, stats.norm.pdf(x, mu, std))\n", 606 | "ax[0].set_xlabel('Weight for ruggedness')\n", 607 | "ax[1].set_xlabel('Weight for log GDP')\n", 608 | "plt.show()" 609 | ] 610 | }, 611 | { 612 | "cell_type": "markdown", 613 | "metadata": { 614 | "id": "hpo6kGPRfyiL" 615 | }, 616 | "source": [ 617 | "### References\n", 618 | " 1. McElreath, D., *Statistical Rethinking, Chapter 7*, 2016\n", 619 | " 2. Nunn, N. & Puga, D., *[Ruggedness: The blessing of bad geography in Africa\"](https://diegopuga.org/papers/rugged.pdf)*, Review of Economics and Statistics 94(1), Feb. 2012" 620 | ] 621 | } 622 | ], 623 | "metadata": { 624 | "anaconda-cloud": {}, 625 | "colab": { 626 | "name": "students_bayesian_logistic_regression.ipynb", 627 | "provenance": [], 628 | "include_colab_link": true 629 | }, 630 | "kernelspec": { 631 | "display_name": "Python 3", 632 | "language": "python", 633 | "name": "python3" 634 | }, 635 | "language_info": { 636 | "codemirror_mode": { 637 | "name": "ipython", 638 | "version": 3 639 | }, 640 | "file_extension": ".py", 641 | "mimetype": "text/x-python", 642 | "name": "python", 643 | "nbconvert_exporter": "python", 644 | "pygments_lexer": "ipython3", 645 | "version": "3.9.0" 646 | } 647 | }, 648 | "nbformat": 4, 649 | "nbformat_minor": 0 650 | } -------------------------------------------------------------------------------- /Day2-BeforeLunch/notebooks/solution_simple_model.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "id": "view-in-github", 7 | "colab_type": "text" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": { 16 | "id": "khKi5Kpyh3Po" 17 | }, 18 | "source": [ 19 | "# Exercise\n", 20 | "\n", 21 | "
\n", 22 | "\"Drawing\"\n", 23 | "
\n" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": { 29 | "id": "nIxiDUQfh3Pr" 30 | }, 31 | "source": [ 32 | "### Imports" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": 1, 38 | "metadata": { 39 | "id": "spxajQOGh3Ps" 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "import numpy as np\n", 44 | "from scipy import special, stats\n", 45 | "import matplotlib.pyplot as plt\n", 46 | "%matplotlib notebook" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": { 52 | "id": "L2gwpsEMh3Pt" 53 | }, 54 | "source": [ 55 | "### Startup: Define priors, and sample artificial training data" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": 2, 61 | "metadata": { 62 | "id": "opTUXGnIh3Pt" 63 | }, 64 | "outputs": [], 65 | "source": [ 66 | "# Define priors\n", 67 | "alpha_prior, beta_prior = 1E-2, 1E-2 # Parameters for the prior over gamma\n", 68 | "mu_prior = 0 # A priori mean for mu\n", 69 | "tau_prior = 1E-6 # A priori precision for mu\n", 70 | "\n", 71 | "# Sample data\n", 72 | "np.random.seed(123)\n", 73 | "N = 100\n", 74 | "correct_mean = 5\n", 75 | "correct_precision = 1\n", 76 | "x = np.random.normal(loc=correct_mean, scale=1./np.sqrt(correct_precision), size=N)" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": { 82 | "id": "mBHQ4YWoh3Pt" 83 | }, 84 | "source": [ 85 | "## Helper-routine: Make plot of density" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": 3, 91 | "metadata": { 92 | "id": "0WYMplwah3Pu" 93 | }, 94 | "outputs": [], 95 | "source": [ 96 | "#@title\n", 97 | "def plot_density(posterior_mean_mu, posterior_prec_mu,\n", 98 | " posterior_alpha_gamma, posterior_beta_gamma,\n", 99 | " correct_mean, correct_precision):\n", 100 | " mu_range = np.linspace(-15,15, 500).astype(np.float32)\n", 101 | " precision_range = np.linspace(1E-2, 3, 500).astype(np.float32)\n", 102 | " mu_mesh, precision_mesh = np.meshgrid(mu_range, precision_range)\n", 103 | " variational_log_pdf = \\\n", 104 | " stats.norm.logpdf(mu_mesh, loc=posterior_mean_mu, scale=1. / np.sqrt(posterior_prec_mu)) + \\\n", 105 | " stats.gamma.logpdf(x=precision_mesh,\n", 106 | " a=posterior_alpha_gamma,\n", 107 | " scale=1. / posterior_beta_gamma)\n", 108 | " plt.figure()\n", 109 | " plt.contour(mu_mesh, precision_mesh, variational_log_pdf, 25)\n", 110 | " plt.plot(correct_mean, correct_precision, \"bo\")\n", 111 | " plt.title('Density over $(\\mu, \\\\tau)$. Blue dot: True parameters')\n", 112 | " plt.xlabel(\"Mean $\\mu$\")\n", 113 | " plt.ylabel(\"Precision $\\\\tau$\")" 114 | ] 115 | }, 116 | { 117 | "cell_type": "markdown", 118 | "metadata": { 119 | "id": "pU5flZ_sh3Pu" 120 | }, 121 | "source": [ 122 | "## Helper-routine: Calculate ELBO" 123 | ] 124 | }, 125 | { 126 | "cell_type": "code", 127 | "execution_count": 5, 128 | "metadata": { 129 | "id": "gi8hKiW0h3Pv", 130 | "cellView": "form" 131 | }, 132 | "outputs": [], 133 | "source": [ 134 | "#@title\n", 135 | "def calculate_ELBO(data, tau, alpha, beta, nu_p, tau_p, alpha_p, beta_p):\n", 136 | " \"\"\"\n", 137 | " Helper routine: Calculate ELBO. Data is the sampled x-values, anything without a _p relates to the prior,\n", 138 | " everything _with_ a _p relates to the variational posterior.\n", 139 | " Note that we have no nu without a _p; we are simplifying by forcing this to be zero a priori\n", 140 | "\n", 141 | " Note: This function obviously only works when the model is as in this code challenge,\n", 142 | " and is not a general solution.\n", 143 | "\n", 144 | " :param data: The sampled data\n", 145 | " :param tau: prior precision for mu, the mean for the data generation\n", 146 | " :param alpha: prior shape of dist for gamma, the precision of the data generation\n", 147 | " :param beta: prior rate of dist for gamma, the precision of the data generation\n", 148 | " :param nu_p: VB posterior mean for the distribution of mu - the mean of the data generation\n", 149 | " :param tau_p: VB posterior precision for the distribution of mu - the mean of the data generation\n", 150 | " :param alpha_p: VB posterior shape of dist for gamma, the precision of the data generation\n", 151 | " :param beta_p: VB posterior shape of dist for gamma, the precision of the data generation\n", 152 | " :return: the ELBO\n", 153 | " \"\"\"\n", 154 | "\n", 155 | " # We calculate ELBO as E_q log p(x,z) - E_q log q(z)\n", 156 | " # log p(x,z) here is log p(mu) + log p(gamma) + \\sum_i log p(x_i | mu, gamma)\n", 157 | "\n", 158 | " # E_q log p(mu)\n", 159 | " log_p = -.5 * np.log(2 * np.pi) + .5 * np.log(tau) - .5 * tau * (1 / tau_p + nu_p * nu_p)\n", 160 | "\n", 161 | " # E_q log p(gamma)\n", 162 | " log_p = log_p + alpha * np.log(beta) + \\\n", 163 | " (alpha - 1) * (special.digamma(alpha_p) - np.log(beta_p)) - beta * alpha_p / beta_p\n", 164 | "\n", 165 | " # E_q log p(x_i|mu, gamma)\n", 166 | " for xi in data:\n", 167 | " log_p += -.5 * np.log(2 * np.pi) \\\n", 168 | " + .5 * (special.digamma(alpha_p) - np.log(beta_p)) \\\n", 169 | " - .5 * alpha_p / beta_p * (xi * xi - 2 * xi * nu_p + 1 / tau_p + nu_p * nu_p)\n", 170 | "\n", 171 | " # Entropy of mu (Gaussian)\n", 172 | " entropy = .5 * np.log(2 * np.pi * np.exp(1) / tau_p)\n", 173 | " entropy += alpha_p - np.log(beta_p) + special.gammaln(alpha_p) \\\n", 174 | " + (1 - alpha_p) * special.digamma(alpha_p)\n", 175 | "\n", 176 | " return log_p + entropy\n" 177 | ] 178 | }, 179 | { 180 | "cell_type": "markdown", 181 | "metadata": { 182 | "id": "U7xhZAEth3Pv" 183 | }, 184 | "source": [ 185 | "## Do the VB\n", 186 | "\n", 187 | "The task is to implemente the variational updating equations appearing below." 188 | ] 189 | }, 190 | { 191 | "cell_type": "markdown", 192 | "source": [ 193 | "
\n", 194 | "\"Drawing\"\n", 195 | "
" 196 | ], 197 | "metadata": { 198 | "id": "CAo2PB1bUqmz" 199 | } 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": 6, 204 | "metadata": { 205 | "id": "jG59YwICh3Px", 206 | "outputId": "76559bed-4cdf-417e-ba0d-81374a99035b", 207 | "colab": { 208 | "base_uri": "https://localhost:8080/" 209 | } 210 | }, 211 | "outputs": [ 212 | { 213 | "output_type": "stream", 214 | "name": "stdout", 215 | "text": [ 216 | "\n", 217 | "====================================================================================================\n", 218 | " VB iterations:\n", 219 | "====================================================================================================\n", 220 | " 1: ELBO: -786.1881435, alpha_q: 50.010, beta_q: 50001327.248, nu_q: 4.977, tau_q: 0.000\n", 221 | " 2: ELBO: -557.6915325, alpha_q: 50.010, beta_q: 495028.283, nu_q: 5.027, tau_q: 0.010\n", 222 | " 3: ELBO: -330.9361681, alpha_q: 50.010, beta_q: 5012.459, nu_q: 5.027, tau_q: 0.998\n", 223 | " 4: ELBO: -170.8624409, alpha_q: 50.010, beta_q: 113.771, nu_q: 5.027, tau_q: 43.957\n", 224 | " 5: ELBO: -164.1402693, alpha_q: 50.010, beta_q: 64.794, nu_q: 5.027, tau_q: 77.183\n", 225 | " 6: ELBO: -164.1388195, alpha_q: 50.010, beta_q: 64.304, nu_q: 5.027, tau_q: 77.771\n", 226 | " 7: ELBO: -164.1388193, alpha_q: 50.010, beta_q: 64.299, nu_q: 5.027, tau_q: 77.777\n", 227 | " 8: ELBO: -164.1388193, alpha_q: 50.010, beta_q: 64.299, nu_q: 5.027, tau_q: 77.777\n", 228 | " 9: ELBO: -164.1388193, alpha_q: 50.010, beta_q: 64.299, nu_q: 5.027, tau_q: 77.777\n", 229 | "\n", 230 | "====================================================================================================\n", 231 | " Result:\n", 232 | "====================================================================================================\n", 233 | "E[mu] = 5.027 with data average 5.027 and prior mean 0.000.\n", 234 | "E[gamma] = 0.778 with inverse of data covariance 0.778 and prior 1.000.\n" 235 | ] 236 | } 237 | ], 238 | "source": [ 239 | "# Initialization\n", 240 | "alpha_q = alpha_prior\n", 241 | "beta_q = beta_prior\n", 242 | "mu_q = 0\n", 243 | "tau_q = tau_prior\n", 244 | "previous_elbo = -np.inf\n", 245 | "\n", 246 | "# Start iterating\n", 247 | "print(\"\\n\" + 100 * \"=\" + \"\\n VB iterations:\\n\" + 100 * \"=\")\n", 248 | "for iteration in range(1000):\n", 249 | " # Update gamma distribution: q(\\gamma)=Gamma(\\alpha_q,\\beta_q)\n", 250 | " alpha_q = alpha_prior + .5 * N \n", 251 | " beta_q = beta_prior + .5 * np.sum(x * x) - mu_q * np.sum(x) + .5 * N * (1. / tau_q + mu_q * mu_q)\n", 252 | "\n", 253 | " # Update Gaussian distribution: q(\\mu)=N(\\mu_q,\\tau_q^{-1})\n", 254 | " expected_gamma = alpha_q / beta_q\n", 255 | " tau_q = tau_prior + N * expected_gamma\n", 256 | " mu_q = expected_gamma * np.sum(x) / tau_q\n", 257 | " \n", 258 | " # Calculate Lower-bound\n", 259 | " current_elbo = calculate_ELBO(data=x, tau=tau_prior, alpha=alpha_prior, beta=beta_prior,\n", 260 | " nu_p=mu_q, tau_p=tau_q, alpha_p=alpha_q, beta_p=beta_q)\n", 261 | " \n", 262 | " print(\"{:2d}: ELBO: {:12.7f}, alpha_q: {:6.3f}, beta_q: {:12.3f}, nu_q: {:6.3f}, tau_q: {:6.3f}\".format(\n", 263 | " iteration + 1, current_elbo, alpha_q, beta_q, mu_q, tau_q))\n", 264 | " \n", 265 | " if current_elbo < previous_elbo:\n", 266 | " raise ValueError(\"ELBO is decreasing. Something is wrong! Goodbye...\")\n", 267 | " \n", 268 | " if iteration > 0 and np.abs((current_elbo - previous_elbo) / previous_elbo) < 1E-20:\n", 269 | " # Very little improvement. We are done.\n", 270 | " break\n", 271 | " \n", 272 | " # If we didn't break we need to run again. Update the value for \"previous\"\n", 273 | " previous_elbo = current_elbo\n", 274 | " \n", 275 | "\n", 276 | "print(\"\\n\" + 100 * \"=\" + \"\\n Result:\\n\" + 100 * \"=\")\n", 277 | "print(\"E[mu] = {:5.3f} with data average {:5.3f} and prior mean {:5.3f}.\".format(mu_q, np.mean(x), 0.))\n", 278 | "print(\"E[gamma] = {:5.3f} with inverse of data covariance {:5.3f} and prior {:5.3f}.\".format(\n", 279 | " alpha_q / beta_q, 1. / np.cov(x), alpha_prior / beta_prior))" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": { 285 | "id": "f0pKpGZhh3Py" 286 | }, 287 | "source": [ 288 | "### Plot of the Prior density" 289 | ] 290 | }, 291 | { 292 | "cell_type": "code", 293 | "source": [ 294 | "plot_density(mu_prior, tau_prior, alpha_prior, beta_prior, correct_mean, correct_precision)\n", 295 | "plt.show()" 296 | ], 297 | "metadata": { 298 | "id": "Gpi5rPBJXCwc", 299 | "outputId": "ae69839d-8293-4251-c16f-3845c0cc6e58", 300 | "colab": { 301 | "base_uri": "https://localhost:8080/", 302 | "height": 301 303 | } 304 | }, 305 | "execution_count": 7, 306 | "outputs": [ 307 | { 308 | "output_type": "display_data", 309 | "data": { 310 | "text/plain": [ 311 | "
" 312 | ], 313 | "image/png": "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\n" 314 | }, 315 | "metadata": { 316 | "needs_background": "light" 317 | } 318 | } 319 | ] 320 | }, 321 | { 322 | "cell_type": "markdown", 323 | "source": [ 324 | "### Plot of the Variational Posterior density" 325 | ], 326 | "metadata": { 327 | "id": "Z8zn_7UFX2NZ" 328 | } 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": 8, 333 | "metadata": { 334 | "id": "kpCATABph3Pz", 335 | "outputId": "d25d955f-65c0-45b6-d019-fec22a99b6ab", 336 | "colab": { 337 | "base_uri": "https://localhost:8080/", 338 | "height": 301 339 | } 340 | }, 341 | "outputs": [ 342 | { 343 | "output_type": "display_data", 344 | "data": { 345 | "text/plain": [ 346 | "
" 347 | ], 348 | "image/png": "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\n" 349 | }, 350 | "metadata": { 351 | "needs_background": "light" 352 | } 353 | } 354 | ], 355 | "source": [ 356 | "plot_density(mu_q, tau_q, alpha_q, beta_q, correct_mean, correct_precision)\n", 357 | "plt.show()" 358 | ] 359 | } 360 | ], 361 | "metadata": { 362 | "colab": { 363 | "name": "solution_simple_model.ipynb", 364 | "provenance": [], 365 | "include_colab_link": true 366 | }, 367 | "kernelspec": { 368 | "display_name": "Python 3", 369 | "language": "python", 370 | "name": "python3" 371 | }, 372 | "language_info": { 373 | "codemirror_mode": { 374 | "name": "ipython", 375 | "version": 3 376 | }, 377 | "file_extension": ".py", 378 | "mimetype": "text/x-python", 379 | "name": "python", 380 | "nbconvert_exporter": "python", 381 | "pygments_lexer": "ipython3", 382 | "version": "3.6.6" 383 | } 384 | }, 385 | "nbformat": 4, 386 | "nbformat_minor": 0 387 | } -------------------------------------------------------------------------------- /Day2-BeforeLunch/notebooks/students_simple_model.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "id": "view-in-github", 7 | "colab_type": "text" 8 | }, 9 | "source": [ 10 | "\"Open" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "metadata": { 16 | "id": "khKi5Kpyh3Po" 17 | }, 18 | "source": [ 19 | "# Exercise\n", 20 | "\n", 21 | "
\n", 22 | "\"Drawing\"\n", 23 | "
\n" 24 | ] 25 | }, 26 | { 27 | "cell_type": "markdown", 28 | "metadata": { 29 | "id": "nIxiDUQfh3Pr" 30 | }, 31 | "source": [ 32 | "### Imports" 33 | ] 34 | }, 35 | { 36 | "cell_type": "code", 37 | "execution_count": null, 38 | "metadata": { 39 | "id": "spxajQOGh3Ps" 40 | }, 41 | "outputs": [], 42 | "source": [ 43 | "import numpy as np\n", 44 | "from scipy import special, stats\n", 45 | "import matplotlib.pyplot as plt\n", 46 | "%matplotlib notebook" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": { 52 | "id": "L2gwpsEMh3Pt" 53 | }, 54 | "source": [ 55 | "### Startup: Define priors, and sample artificial training data" 56 | ] 57 | }, 58 | { 59 | "cell_type": "code", 60 | "execution_count": null, 61 | "metadata": { 62 | "id": "opTUXGnIh3Pt" 63 | }, 64 | "outputs": [], 65 | "source": [ 66 | "# Define priors\n", 67 | "alpha_prior, beta_prior = 1E-2, 1E-2 # Parameters for the prior over gamma\n", 68 | "mu_prior = 0 # A priori mean for mu\n", 69 | "tau_prior = 1E-6 # A priori precision for mu\n", 70 | "\n", 71 | "# Sample data\n", 72 | "np.random.seed(123)\n", 73 | "N = 100\n", 74 | "correct_mean = 5\n", 75 | "correct_precision = 1\n", 76 | "x = np.random.normal(loc=correct_mean, scale=1./np.sqrt(correct_precision), size=N)" 77 | ] 78 | }, 79 | { 80 | "cell_type": "markdown", 81 | "metadata": { 82 | "id": "mBHQ4YWoh3Pt" 83 | }, 84 | "source": [ 85 | "## Helper-routine: Make plot of density" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": null, 91 | "metadata": { 92 | "id": "0WYMplwah3Pu", 93 | "cellView": "form" 94 | }, 95 | "outputs": [], 96 | "source": [ 97 | "#@title\n", 98 | "def plot_density(posterior_mean_mu, posterior_prec_mu,\n", 99 | " posterior_alpha_gamma, posterior_beta_gamma,\n", 100 | " correct_mean, correct_precision):\n", 101 | " mu_range = np.linspace(-15,15, 500).astype(np.float32)\n", 102 | " precision_range = np.linspace(1E-2, 3, 500).astype(np.float32)\n", 103 | " mu_mesh, precision_mesh = np.meshgrid(mu_range, precision_range)\n", 104 | " variational_log_pdf = \\\n", 105 | " stats.norm.logpdf(mu_mesh, loc=posterior_mean_mu, scale=1. / np.sqrt(posterior_prec_mu)) + \\\n", 106 | " stats.gamma.logpdf(x=precision_mesh,\n", 107 | " a=posterior_alpha_gamma,\n", 108 | " scale=1. / posterior_beta_gamma)\n", 109 | " plt.figure()\n", 110 | " plt.contour(mu_mesh, precision_mesh, variational_log_pdf, 25)\n", 111 | " plt.plot(correct_mean, correct_precision, \"bo\")\n", 112 | " plt.title('Density over $(\\mu, \\\\tau)$. Blue dot: True parameters')\n", 113 | " plt.xlabel(\"Mean $\\mu$\")\n", 114 | " plt.ylabel(\"Precision $\\\\tau$\")" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": { 120 | "id": "pU5flZ_sh3Pu" 121 | }, 122 | "source": [ 123 | "## Helper-routine: Calculate ELBO" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": { 130 | "id": "gi8hKiW0h3Pv", 131 | "cellView": "form" 132 | }, 133 | "outputs": [], 134 | "source": [ 135 | "#@title\n", 136 | "def calculate_ELBO(data, tau, alpha, beta, nu_p, tau_p, alpha_p, beta_p):\n", 137 | " \"\"\"\n", 138 | " Helper routine: Calculate ELBO. Data is the sampled x-values, anything without a _p relates to the prior,\n", 139 | " everything _with_ a _p relates to the variational posterior.\n", 140 | " Note that we have no nu without a _p; we are simplifying by forcing this to be zero a priori\n", 141 | "\n", 142 | " Note: This function obviously only works when the model is as in this code challenge,\n", 143 | " and is not a general solution.\n", 144 | "\n", 145 | " :param data: The sampled data\n", 146 | " :param tau: prior precision for mu, the mean for the data generation\n", 147 | " :param alpha: prior shape of dist for gamma, the precision of the data generation\n", 148 | " :param beta: prior rate of dist for gamma, the precision of the data generation\n", 149 | " :param nu_p: VB posterior mean for the distribution of mu - the mean of the data generation\n", 150 | " :param tau_p: VB posterior precision for the distribution of mu - the mean of the data generation\n", 151 | " :param alpha_p: VB posterior shape of dist for gamma, the precision of the data generation\n", 152 | " :param beta_p: VB posterior shape of dist for gamma, the precision of the data generation\n", 153 | " :return: the ELBO\n", 154 | " \"\"\"\n", 155 | "\n", 156 | " # We calculate ELBO as E_q log p(x,z) - E_q log q(z)\n", 157 | " # log p(x,z) here is log p(mu) + log p(gamma) + \\sum_i log p(x_i | mu, gamma)\n", 158 | "\n", 159 | " # E_q log p(mu)\n", 160 | " log_p = -.5 * np.log(2 * np.pi) + .5 * np.log(tau) - .5 * tau * (1 / tau_p + nu_p * nu_p)\n", 161 | "\n", 162 | " # E_q log p(gamma)\n", 163 | " log_p = log_p + alpha * np.log(beta) + \\\n", 164 | " (alpha - 1) * (special.digamma(alpha_p) - np.log(beta_p)) - beta * alpha_p / beta_p\n", 165 | "\n", 166 | " # E_q log p(x_i|mu, gamma)\n", 167 | " for xi in data:\n", 168 | " log_p += -.5 * np.log(2 * np.pi) \\\n", 169 | " + .5 * (special.digamma(alpha_p) - np.log(beta_p)) \\\n", 170 | " - .5 * alpha_p / beta_p * (xi * xi - 2 * xi * nu_p + 1 / tau_p + nu_p * nu_p)\n", 171 | "\n", 172 | " # Entropy of mu (Gaussian)\n", 173 | " entropy = .5 * np.log(2 * np.pi * np.exp(1) / tau_p)\n", 174 | " entropy += alpha_p - np.log(beta_p) + special.gammaln(alpha_p) \\\n", 175 | " + (1 - alpha_p) * special.digamma(alpha_p)\n", 176 | "\n", 177 | " return log_p + entropy\n" 178 | ] 179 | }, 180 | { 181 | "cell_type": "markdown", 182 | "metadata": { 183 | "id": "U7xhZAEth3Pv" 184 | }, 185 | "source": [ 186 | "## Do the VB\n", 187 | "\n", 188 | "The task is to implemente the variational updating equations appearing below." 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "source": [ 194 | "
\n", 195 | "\"Drawing\"\n", 196 | "
" 197 | ], 198 | "metadata": { 199 | "id": "CAo2PB1bUqmz" 200 | } 201 | }, 202 | { 203 | "cell_type": "code", 204 | "execution_count": null, 205 | "metadata": { 206 | "id": "jG59YwICh3Px", 207 | "outputId": "f69f7dcf-4c99-4738-a2a0-ea6586b0269d", 208 | "colab": { 209 | "base_uri": "https://localhost:8080/" 210 | } 211 | }, 212 | "outputs": [ 213 | { 214 | "output_type": "stream", 215 | "name": "stdout", 216 | "text": [ 217 | "\n", 218 | "====================================================================================================\n", 219 | " VB iterations:\n", 220 | "====================================================================================================\n", 221 | " 1: ELBO: -786.1881435, alpha_q: 50.010, beta_q: 50001327.248, nu_q: 4.977, tau_q: 0.000\n", 222 | " 2: ELBO: -557.6915325, alpha_q: 50.010, beta_q: 495028.283, nu_q: 5.027, tau_q: 0.010\n", 223 | " 3: ELBO: -330.9361681, alpha_q: 50.010, beta_q: 5012.459, nu_q: 5.027, tau_q: 0.998\n", 224 | " 4: ELBO: -170.8624409, alpha_q: 50.010, beta_q: 113.771, nu_q: 5.027, tau_q: 43.957\n", 225 | " 5: ELBO: -164.1402693, alpha_q: 50.010, beta_q: 64.794, nu_q: 5.027, tau_q: 77.183\n", 226 | " 6: ELBO: -164.1388195, alpha_q: 50.010, beta_q: 64.304, nu_q: 5.027, tau_q: 77.771\n", 227 | " 7: ELBO: -164.1388193, alpha_q: 50.010, beta_q: 64.299, nu_q: 5.027, tau_q: 77.777\n", 228 | " 8: ELBO: -164.1388193, alpha_q: 50.010, beta_q: 64.299, nu_q: 5.027, tau_q: 77.777\n", 229 | " 9: ELBO: -164.1388193, alpha_q: 50.010, beta_q: 64.299, nu_q: 5.027, tau_q: 77.777\n", 230 | "\n", 231 | "====================================================================================================\n", 232 | " Result:\n", 233 | "====================================================================================================\n", 234 | "E[mu] = 5.027 with data average 5.027 and prior mean 0.000.\n", 235 | "E[gamma] = 0.778 with inverse of data covariance 0.778 and prior 1.000.\n" 236 | ] 237 | } 238 | ], 239 | "source": [ 240 | "# Initialization\n", 241 | "alpha_q = alpha_prior\n", 242 | "beta_q = beta_prior\n", 243 | "mu_q = 0\n", 244 | "tau_q = tau_prior\n", 245 | "previous_elbo = -np.inf\n", 246 | "\n", 247 | "# Start iterating\n", 248 | "print(\"\\n\" + 100 * \"=\" + \"\\n VB iterations:\\n\" + 100 * \"=\")\n", 249 | "for iteration in range(1000):\n", 250 | " # Update gamma distribution\n", 251 | " alpha_q = 0 ## Code the updating equation\n", 252 | " beta_q = beta_prior + .5 * np.sum(x * x) - mu_q * np.sum(x) + .5 * N * (1. / tau_q + mu_q * mu_q)\n", 253 | "\n", 254 | " # Update Gaussian distribution\n", 255 | " expected_gamma = 0 ## Code the updating equation\n", 256 | " tau_q = 0 ## Code the updating equation\n", 257 | " mu_q = 0 ## Code the updating equation\n", 258 | " \n", 259 | " # Calculate Lower-bound\n", 260 | " current_elbo = calculate_ELBO(data=x, tau=tau_prior, alpha=alpha_prior, beta=beta_prior,\n", 261 | " nu_p=mu_q, tau_p=tau_q, alpha_p=alpha_q, beta_p=beta_q)\n", 262 | " \n", 263 | " print(\"{:2d}: ELBO: {:12.7f}, alpha_q: {:6.3f}, beta_q: {:12.3f}, nu_q: {:6.3f}, tau_q: {:6.3f}\".format(\n", 264 | " iteration + 1, current_elbo, alpha_q, beta_q, mu_q, tau_q))\n", 265 | " \n", 266 | " if current_elbo < previous_elbo:\n", 267 | " raise ValueError(\"ELBO is decreasing. Something is wrong! Goodbye...\")\n", 268 | " \n", 269 | " if iteration > 0 and np.abs((current_elbo - previous_elbo) / previous_elbo) < 1E-20:\n", 270 | " # Very little improvement. We are done.\n", 271 | " break\n", 272 | " \n", 273 | " # If we didn't break we need to run again. Update the value for \"previous\"\n", 274 | " previous_elbo = current_elbo\n", 275 | " \n", 276 | "\n", 277 | "print(\"\\n\" + 100 * \"=\" + \"\\n Result:\\n\" + 100 * \"=\")\n", 278 | "print(\"E[mu] = {:5.3f} with data average {:5.3f} and prior mean {:5.3f}.\".format(mu_q, np.mean(x), 0.))\n", 279 | "print(\"E[gamma] = {:5.3f} with inverse of data covariance {:5.3f} and prior {:5.3f}.\".format(\n", 280 | " alpha_q / beta_q, 1. / np.cov(x), alpha_prior / beta_prior))" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "metadata": { 286 | "id": "f0pKpGZhh3Py" 287 | }, 288 | "source": [ 289 | "### Plot of the Prior density" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "source": [ 295 | "plot_density(mu_prior, tau_prior, alpha_prior, beta_prior, correct_mean, correct_precision)\n", 296 | "plt.show()" 297 | ], 298 | "metadata": { 299 | "id": "Gpi5rPBJXCwc", 300 | "outputId": "34dba885-07ac-4af2-c949-4dfb9ba20ce5", 301 | "colab": { 302 | "base_uri": "https://localhost:8080/", 303 | "height": 301 304 | } 305 | }, 306 | "execution_count": null, 307 | "outputs": [ 308 | { 309 | "output_type": "display_data", 310 | "data": { 311 | "text/plain": [ 312 | "
" 313 | ], 314 | "image/png": "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\n" 315 | }, 316 | "metadata": { 317 | "needs_background": "light" 318 | } 319 | } 320 | ] 321 | }, 322 | { 323 | "cell_type": "markdown", 324 | "source": [ 325 | "### Plot of the Variational Posterior density" 326 | ], 327 | "metadata": { 328 | "id": "Z8zn_7UFX2NZ" 329 | } 330 | }, 331 | { 332 | "cell_type": "code", 333 | "execution_count": null, 334 | "metadata": { 335 | "id": "kpCATABph3Pz", 336 | "outputId": "3f6bac10-c7f7-4337-c2f1-35504c85bdfc", 337 | "colab": { 338 | "base_uri": "https://localhost:8080/", 339 | "height": 301 340 | } 341 | }, 342 | "outputs": [ 343 | { 344 | "output_type": "display_data", 345 | "data": { 346 | "text/plain": [ 347 | "
" 348 | ], 349 | "image/png": "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\n" 350 | }, 351 | "metadata": { 352 | "needs_background": "light" 353 | } 354 | } 355 | ], 356 | "source": [ 357 | "plot_density(mu_q, tau_q, alpha_q, beta_q, correct_mean, correct_precision)\n", 358 | "plt.show()" 359 | ] 360 | } 361 | ], 362 | "metadata": { 363 | "colab": { 364 | "name": "students_simple_model.ipynb", 365 | "provenance": [], 366 | "include_colab_link": true 367 | }, 368 | "kernelspec": { 369 | "display_name": "Python 3", 370 | "language": "python", 371 | "name": "python3" 372 | }, 373 | "language_info": { 374 | "codemirror_mode": { 375 | "name": "ipython", 376 | "version": 3 377 | }, 378 | "file_extension": ".py", 379 | "mimetype": "text/x-python", 380 | "name": "python", 381 | "nbconvert_exporter": "python", 382 | "pygments_lexer": "ipython3", 383 | "version": "3.6.6" 384 | } 385 | }, 386 | "nbformat": 4, 387 | "nbformat_minor": 0 388 | } --------------------------------------------------------------------------------