├── .gitignore ├── README.md ├── environment.yaml ├── ha ├── AirPassengers.csv ├── ha-1.ipynb ├── ha-2-data.json ├── ha-2.ipynb └── ha-3.ipynb ├── lectures ├── .gitattributes ├── practical_bayes_1_intro.pdf ├── practical_bayes_2_priors.pdf ├── practical_bayes_3_AB.pdf ├── practical_bayes_4_GP.pdf ├── practical_bayes_5_GP.pdf └── practical_bayes_6_linear_msu_2023.pdf └── seminars ├── 1-api_quickstart.ipynb ├── 2-hierarchy.ipynb ├── 3-ab.ipynb ├── 4-gp.ipynb ├── 5-gp-ts.ipynb ├── 6-r2d2.ipynb └── solved ├── 1-api_quickstart.ipynb ├── 2-hierarchy.ipynb ├── 3-ab.ipynb └── 6-lr-solved.ipynb /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | share/python-wheels/ 24 | *.egg-info/ 25 | .installed.cfg 26 | *.egg 27 | MANIFEST 28 | 29 | # PyInstaller 30 | # Usually these files are written by a python script from a template 31 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 32 | *.manifest 33 | *.spec 34 | 35 | # Installer logs 36 | pip-log.txt 37 | pip-delete-this-directory.txt 38 | 39 | # Unit test / coverage reports 40 | htmlcov/ 41 | .tox/ 42 | .nox/ 43 | .coverage 44 | .coverage.* 45 | .cache 46 | nosetests.xml 47 | coverage.xml 48 | *.cover 49 | *.py,cover 50 | .hypothesis/ 51 | .pytest_cache/ 52 | cover/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | .pybuilder/ 76 | target/ 77 | 78 | # Jupyter Notebook 79 | .ipynb_checkpoints 80 | 81 | # IPython 82 | profile_default/ 83 | ipython_config.py 84 | 85 | # pyenv 86 | # For a library or package, you might want to ignore these files since the code is 87 | # intended to run in multiple environments; otherwise, check them in: 88 | # .python-version 89 | 90 | # pipenv 91 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 92 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 93 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 94 | # install all needed dependencies. 95 | #Pipfile.lock 96 | 97 | # poetry 98 | # Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. 99 | # This is especially recommended for binary packages to ensure reproducibility, and is more 100 | # commonly ignored for libraries. 101 | # https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control 102 | #poetry.lock 103 | 104 | # pdm 105 | # Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control. 106 | #pdm.lock 107 | # pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it 108 | # in version control. 109 | # https://pdm.fming.dev/#use-with-ide 110 | .pdm.toml 111 | 112 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm 113 | __pypackages__/ 114 | 115 | # Celery stuff 116 | celerybeat-schedule 117 | celerybeat.pid 118 | 119 | # SageMath parsed files 120 | *.sage.py 121 | 122 | # Environments 123 | .env 124 | .venv 125 | env/ 126 | venv/ 127 | ENV/ 128 | env.bak/ 129 | venv.bak/ 130 | 131 | # Spyder project settings 132 | .spyderproject 133 | .spyproject 134 | 135 | # Rope project settings 136 | .ropeproject 137 | 138 | # mkdocs documentation 139 | /site 140 | 141 | # mypy 142 | .mypy_cache/ 143 | .dmypy.json 144 | dmypy.json 145 | 146 | # Pyre type checker 147 | .pyre/ 148 | 149 | # pytype static type analyzer 150 | .pytype/ 151 | 152 | # Cython debug symbols 153 | cython_debug/ 154 | 155 | # PyCharm 156 | # JetBrains specific template is maintained in a separate JetBrains.gitignore that can 157 | # be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore 158 | # and can be added to the global gitignore or merged into this file. For a more nuclear 159 | # option (not recommended) you can uncomment the following to ignore the entire idea folder. 160 | #.idea/ 161 | .DS_Store 162 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Practical Bayes 2 | =============== 3 | -------------------------------------------------------------------------------- /environment.yaml: -------------------------------------------------------------------------------- 1 | name: practical-bayes-env 2 | channels: 3 | - conda-forge 4 | dependencies: 5 | - pytensor 6 | - arviz 7 | - jupyter 8 | - jupyterlab 9 | - matplotlib 10 | - numpy 11 | - pandas<2.0 12 | - pip 13 | - pymc>=5.8 14 | - python-graphviz 15 | - scikit-learn 16 | - scipy 17 | - seaborn 18 | - watermark 19 | -------------------------------------------------------------------------------- /ha/AirPassengers.csv: -------------------------------------------------------------------------------- 1 | Month,#Passengers 2 | 1949-01,112 3 | 1949-02,118 4 | 1949-03,132 5 | 1949-04,129 6 | 1949-05,121 7 | 1949-06,135 8 | 1949-07,148 9 | 1949-08,148 10 | 1949-09,136 11 | 1949-10,119 12 | 1949-11,104 13 | 1949-12,118 14 | 1950-01,115 15 | 1950-02,126 16 | 1950-03,141 17 | 1950-04,135 18 | 1950-05,125 19 | 1950-06,149 20 | 1950-07,170 21 | 1950-08,170 22 | 1950-09,158 23 | 1950-10,133 24 | 1950-11,114 25 | 1950-12,140 26 | 1951-01,145 27 | 1951-02,150 28 | 1951-03,178 29 | 1951-04,163 30 | 1951-05,172 31 | 1951-06,178 32 | 1951-07,199 33 | 1951-08,199 34 | 1951-09,184 35 | 1951-10,162 36 | 1951-11,146 37 | 1951-12,166 38 | 1952-01,171 39 | 1952-02,180 40 | 1952-03,193 41 | 1952-04,181 42 | 1952-05,183 43 | 1952-06,218 44 | 1952-07,230 45 | 1952-08,242 46 | 1952-09,209 47 | 1952-10,191 48 | 1952-11,172 49 | 1952-12,194 50 | 1953-01,196 51 | 1953-02,196 52 | 1953-03,236 53 | 1953-04,235 54 | 1953-05,229 55 | 1953-06,243 56 | 1953-07,264 57 | 1953-08,272 58 | 1953-09,237 59 | 1953-10,211 60 | 1953-11,180 61 | 1953-12,201 62 | 1954-01,204 63 | 1954-02,188 64 | 1954-03,235 65 | 1954-04,227 66 | 1954-05,234 67 | 1954-06,264 68 | 1954-07,302 69 | 1954-08,293 70 | 1954-09,259 71 | 1954-10,229 72 | 1954-11,203 73 | 1954-12,229 74 | 1955-01,242 75 | 1955-02,233 76 | 1955-03,267 77 | 1955-04,269 78 | 1955-05,270 79 | 1955-06,315 80 | 1955-07,364 81 | 1955-08,347 82 | 1955-09,312 83 | 1955-10,274 84 | 1955-11,237 85 | 1955-12,278 86 | 1956-01,284 87 | 1956-02,277 88 | 1956-03,317 89 | 1956-04,313 90 | 1956-05,318 91 | 1956-06,374 92 | 1956-07,413 93 | 1956-08,405 94 | 1956-09,355 95 | 1956-10,306 96 | 1956-11,271 97 | 1956-12,306 98 | 1957-01,315 99 | 1957-02,301 100 | 1957-03,356 101 | 1957-04,348 102 | 1957-05,355 103 | 1957-06,422 104 | 1957-07,465 105 | 1957-08,467 106 | 1957-09,404 107 | 1957-10,347 108 | 1957-11,305 109 | 1957-12,336 110 | 1958-01,340 111 | 1958-02,318 112 | 1958-03,362 113 | 1958-04,348 114 | 1958-05,363 115 | 1958-06,435 116 | 1958-07,491 117 | 1958-08,505 118 | 1958-09,404 119 | 1958-10,359 120 | 1958-11,310 121 | 1958-12,337 122 | 1959-01,360 123 | 1959-02,342 124 | 1959-03,406 125 | 1959-04,396 126 | 1959-05,420 127 | 1959-06,472 128 | 1959-07,548 129 | 1959-08,559 130 | 1959-09,463 131 | 1959-10,407 132 | 1959-11,362 133 | 1959-12,405 134 | 1960-01,417 135 | 1960-02,391 136 | 1960-03,419 137 | 1960-04,461 138 | 1960-05,472 139 | 1960-06,535 140 | 1960-07,622 141 | 1960-08,606 142 | 1960-09,508 143 | 1960-10,461 144 | 1960-11,390 145 | 1960-12,432 146 | -------------------------------------------------------------------------------- /ha/ha-1.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "caee71ac", 6 | "metadata": { 7 | "cellId": "lg5qmvxbktqdc8j797spb" 8 | }, 9 | "source": [ 10 | "## Homework 1" 11 | ] 12 | }, 13 | { 14 | "cell_type": "markdown", 15 | "id": "e730cdf8", 16 | "metadata": { 17 | "cellId": "vbom82owyi5b6w892zgz3", 18 | "execution_id": "cac453ed-0853-4f32-93b7-e569c8132627" 19 | }, 20 | "source": [ 21 | "## Installing dependencies\n", 22 | "\n", 23 | "> **The submission (zip file) consists of the notebook.ipynb + trace1 ... traceN.nc files** (file, export project as ZIP)" 24 | ] 25 | }, 26 | { 27 | "cell_type": "code", 28 | "execution_count": null, 29 | "id": "b2cfb29c", 30 | "metadata": { 31 | "cellId": "a60gs6jzmbm9s9czym9gh" 32 | }, 33 | "outputs": [], 34 | "source": [ 35 | "%pip install -U pymc numpy scipy" 36 | ] 37 | }, 38 | { 39 | "cell_type": "markdown", 40 | "id": "23099f8b", 41 | "metadata": { 42 | "cellId": "0zmwx33jq12nwghz16hmta" 43 | }, 44 | "source": [ 45 | "## Estimating Purchases" 46 | ] 47 | }, 48 | { 49 | "cell_type": "code", 50 | "execution_count": null, 51 | "id": "d1077f78", 52 | "metadata": { 53 | "cellId": "ituo2hhdt3qtp3p9mkvm" 54 | }, 55 | "outputs": [], 56 | "source": [ 57 | "import pymc as pm\n", 58 | "import pandas as pd\n", 59 | "import io\n", 60 | "import pytensor.tensor as pt\n", 61 | "import matplotlib.pyplot as plt\n", 62 | "import arviz as az\n", 63 | "%matplotlib inline" 64 | ] 65 | }, 66 | { 67 | "cell_type": "markdown", 68 | "id": "9edae16b", 69 | "metadata": { 70 | "cellId": "27k3qf4xagdjns6fjvq1yl", 71 | "execution_id": "73cd509a-13f1-4b9d-9a54-ea850484243f" 72 | }, 73 | "source": [ 74 | "You have raw purchase data (**obs**) from three grocery stores (**store**) for the same product (zero means a customer did not buy the product). Groceries are of different size so number of observations are different. You need to compare which grocery is more efficient in sales.\n", 75 | "\n", 76 | "\n", 77 | "1. (5 pt) Propose and motivate a likelihood for the problem\n", 78 | " * likelihood with negative support = -5 points\n", 79 | "2. (10 pt) Propose and motivate a probabilistic model (non-hierarchical) for the problem. Some parameters may be shared, some independent if you want.\n", 80 | " 0. (2.5 pt) Write LaTeX equation for the model (displaying model is ok)\n", 81 | " 1. (2.5 pt) Motivate priors, under the only assumption that purchases are at orders of 100s and no more than 500\n", 82 | " 2. (2.5 pt) Make a prior predictive check to confirm your choice\n", 83 | " 3. (2.5 pt) Sample from the model, plot traces compare it with prior, comment on it (e.g. infulence of data size).\n", 84 | " 4. **total score for the section is multiplied by (1 - divergent samples / total samples)**\n", 85 | " 5. Save trace into traceN.nc\n", 86 | "3. (10 pt) Propose a hierarchical model for the problem. Put hierarchy on only one model parameter (you choose which one, prefer mean)\n", 87 | " \n", 88 | " same as 2.\n", 89 | " \n", 90 | "4. (10 pt) Propose a hierarchical model for the problem. Put hierarchy on 2 model parameters (you choose which additional one, prefer p)\n", 91 | " \n", 92 | " same as 2\n", 93 | "\n", 94 | "5. (5 pt) Perform a model comparison study (look into [`az.compare`](https://arviz-devs.github.io/arviz/api/generated/arviz.compare.html)), you can use the models you have (at least 2)\n", 95 | " 1. Interpret the result and choose the model, elaborate on warnings\n", 96 | "6. (5 pt) Business Metric (bonus)\n", 97 | " 1. Propose and motivate a comparison metric between groceries to say (A is better than B)\n", 98 | " 2. Evaluate the metric on the the best model you have\n", 99 | "7. (5 pt) Make a prediction for a new store, you need model from (4) (bonus)\n", 100 | "\n", 101 | "(max 40 pt)\n", 102 | "\n", 103 | "**Important**\n", 104 | "> Use quoting for the main points of your solution" 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "id": "63011392", 111 | "metadata": { 112 | "cellId": "4pihpmkf3yhdshzwkm9j3f", 113 | "tags": [] 114 | }, 115 | "outputs": [], 116 | "source": [ 117 | "raw_data = io.StringIO('obs,store\\n117,0\\n0,0\\n0,0\\n134,0\\n0,0\\n0,0\\n0,0\\n0,0\\n122,0\\n0,0\\n108,0\\n0,0\\n0,0\\n0,0\\n0,0\\n124,0\\n0,0\\n0,0\\n113,0\\n118,0\\n0,0\\n105,0\\n114,0\\n0,0\\n118,0\\n106,0\\n0,0\\n100,0\\n0,0\\n0,0\\n123,0\\n0,0\\n0,0\\n0,0\\n0,0\\n129,0\\n0,0\\n117,0\\n0,0\\n0,0\\n0,0\\n0,0\\n0,0\\n115,0\\n123,0\\n0,0\\n0,0\\n0,0\\n137,0\\n0,0\\n0,0\\n0,0\\n0,0\\n0,0\\n136,0\\n0,0\\n107,0\\n0,0\\n0,0\\n0,0\\n0,0\\n115,0\\n118,0\\n0,0\\n105,0\\n105,0\\n97,0\\n121,0\\n0,0\\n0,0\\n0,0\\n124,0\\n114,0\\n0,0\\n101,0\\n0,0\\n0,0\\n0,0\\n121,0\\n0,0\\n0,0\\n0,0\\n119,0\\n0,0\\n108,0\\n121,0\\n0,0\\n0,0\\n116,0\\n0,0\\n0,0\\n0,0\\n0,0\\n0,0\\n0,0\\n0,0\\n127,0\\n0,0\\n0,0\\n106,0\\n0,0\\n0,0\\n0,0\\n131,0\\n0,0\\n0,0\\n128,0\\n122,0\\n0,0\\n0,0\\n0,0\\n0,0\\n0,0\\n0,0\\n102,0\\n119,0\\n0,0\\n0,0\\n0,0\\n123,0\\n0,0\\n0,0\\n0,0\\n120,0\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n121,1\\n0,1\\n0,1\\n0,1\\n123,1\\n0,1\\n106,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n142,1\\n0,1\\n0,1\\n0,1\\n131,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,1\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n81,2\\n0,2\\n0,2\\n73,2\\n0,2\\n0,2\\n0,2\\n69,2\\n0,2\\n94,2\\n0,2\\n91,2\\n0,2\\n0,2\\n98,2\\n0,2\\n79,2\\n90,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n102,2\\n0,2\\n87,2\\n0,2\\n81,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n86,2\\n97,2\\n0,2\\n0,2\\n0,2\\n76,2\\n0,2\\n83,2\\n0,2\\n0,2\\n88,2\\n0,2\\n86,2\\n0,2\\n0,2\\n99,2\\n0,2\\n0,2\\n86,2\\n86,2\\n0,2\\n93,2\\n0,2\\n0,2\\n0,2\\n90,2\\n0,2\\n81,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n91,2\\n0,2\\n0,2\\n67,2\\n107,2\\n0,2\\n0,2\\n0,2\\n0,2\\n101,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n75,2\\n112,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n91,2\\n0,2\\n0,2\\n0,2\\n81,2\\n108,2\\n92,2\\n0,2\\n0,2\\n0,2\\n90,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n93,2\\n0,2\\n0,2\\n0,2\\n96,2\\n0,2\\n0,2\\n0,2\\n0,2\\n94,2\\n0,2\\n90,2\\n0,2\\n0,2\\n0,2\\n0,2\\n94,2\\n0,2\\n0,2\\n0,2\\n0,2\\n72,2\\n0,2\\n97,2\\n0,2\\n82,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n105,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n99,2\\n90,2\\n0,2\\n76,2\\n92,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n100,2\\n113,2\\n0,2\\n0,2\\n0,2\\n100,2\\n0,2\\n91,2\\n0,2\\n88,2\\n0,2\\n0,2\\n0,2\\n83,2\\n0,2\\n0,2\\n82,2\\n0,2\\n84,2\\n101,2\\n0,2\\n0,2\\n0,2\\n0,2\\n102,2\\n0,2\\n0,2\\n0,2\\n99,2\\n91,2\\n0,2\\n95,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n73,2\\n0,2\\n80,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n90,2\\n0,2\\n0,2\\n0,2\\n0,2\\n95,2\\n0,2\\n91,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n92,2\\n0,2\\n0,2\\n97,2\\n70,2\\n102,2\\n0,2\\n0,2\\n0,2\\n87,2\\n111,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n73,2\\n79,2\\n99,2\\n0,2\\n0,2\\n88,2\\n88,2\\n0,2\\n0,2\\n94,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n94,2\\n0,2\\n88,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n80,2\\n90,2\\n0,2\\n0,2\\n0,2\\n87,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n105,2\\n0,2\\n0,2\\n88,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n71,2\\n0,2\\n103,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n96,2\\n0,2\\n0,2\\n0,2\\n94,2\\n0,2\\n79,2\\n110,2\\n0,2\\n0,2\\n0,2\\n90,2\\n0,2\\n0,2\\n0,2\\n101,2\\n0,2\\n95,2\\n94,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n85,2\\n0,2\\n100,2\\n92,2\\n0,2\\n0,2\\n0,2\\n110,2\\n0,2\\n0,2\\n0,2\\n0,2\\n78,2\\n0,2\\n74,2\\n0,2\\n103,2\\n0,2\\n0,2\\n0,2\\n0,2\\n90,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n90,2\\n105,2\\n0,2\\n0,2\\n0,2\\n103,2\\n0,2\\n0,2\\n0,2\\n0,2\\n98,2\\n89,2\\n105,2\\n0,2\\n0,2\\n93,2\\n0,2\\n93,2\\n0,2\\n0,2\\n0,2\\n0,2\\n88,2\\n88,2\\n0,2\\n0,2\\n91,2\\n0,2\\n89,2\\n0,2\\n0,2\\n100,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n75,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n85,2\\n0,2\\n83,2\\n0,2\\n0,2\\n80,2\\n0,2\\n0,2\\n0,2\\n0,2\\n89,2\\n0,2\\n0,2\\n76,2\\n0,2\\n89,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n88,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n101,2\\n0,2\\n112,2\\n92,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n93,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n95,2\\n0,2\\n0,2\\n94,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n104,2\\n0,2\\n89,2\\n0,2\\n88,2\\n0,2\\n0,2\\n0,2\\n0,2\\n86,2\\n82,2\\n0,2\\n0,2\\n0,2\\n0,2\\n0,2\\n91,2\\n0,2\\n83,2\\n0,2\\n81,2\\n0,2\\n0,2\\n87,2\\n0,2\\n0,2\\n0,2\\n83,2\\n0,2\\n94,2\\n0,2\\n0,2\\n81,2\\n0,2\\n0,2\\n0,2\\n87,2\\n0,2\\n0,2\\n108,2\\n')\n", 118 | "data = pd.read_csv(raw_data)" 119 | ] 120 | }, 121 | { 122 | "cell_type": "code", 123 | "execution_count": null, 124 | "id": "d9bc723e", 125 | "metadata": { 126 | "cellId": "29cps4v99v3xz81q1jyp7r" 127 | }, 128 | "outputs": [], 129 | "source": [ 130 | "data" 131 | ] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "id": "dddff295", 136 | "metadata": { 137 | "cellId": "rb954e09q2sg3mw7yerf14", 138 | "execution_id": "915bef67-5a53-4c70-939c-fb33540b951c" 139 | }, 140 | "source": [ 141 | "## 1. Data description\n", 142 | "1. Propose and motivate a likelihood for the problem" 143 | ] 144 | }, 145 | { 146 | "cell_type": "markdown", 147 | "id": "e754534a", 148 | "metadata": { 149 | "cellId": "fsz5fepepbqy2z11thdtnd", 150 | "execution_id": "a7388583-90ad-4af5-b3fd-1d1b205d4935" 151 | }, 152 | "source": [ 153 | "## 2. Probabilistic model" 154 | ] 155 | }, 156 | { 157 | "cell_type": "markdown", 158 | "id": "207b7cf2", 159 | "metadata": { 160 | "cellId": "wv2vr0mdgurhs9lrlhlqwj", 161 | "execution_id": "dd8e2a2c-6bc3-4dc7-829d-116a278d8252" 162 | }, 163 | "source": [ 164 | "2. Propose and motivate a probabilistic model (non-hierarchical) for the problem. Some parameters may be shared, some independent if you want.\n", 165 | " \n", 166 | " 0. Write LaTeX equation for the model (displaying latex model is ok)\n", 167 | " 1. Motivate priors, under the only assumption that purchases are at orders of 100s and no more than 500\n", 168 | " 2. Make a prior predictive check to confirm your choice\n", 169 | " 3. Sample from the model, plot traces compare it with prior, comment on it (e.g. infulence of data size)." 170 | ] 171 | }, 172 | { 173 | "cell_type": "markdown", 174 | "id": "f6622d45", 175 | "metadata": { 176 | "cellId": "fy51crzn2cwirdd8bmlokm", 177 | "execution_id": "aa51a99f-198e-4240-9896-08fe4dd53aff" 178 | }, 179 | "source": [ 180 | "**hints:**\n", 181 | "\n", 182 | "1. explore `pt.stack` to fix shape issues with mixture probability, (if you use mixtures)\n", 183 | "2. visit 2d seminar" 184 | ] 185 | }, 186 | { 187 | "cell_type": "code", 188 | "execution_count": null, 189 | "id": "ef595724", 190 | "metadata": { 191 | "cellId": "2uoj0mwz91xe52lqz3ia5u" 192 | }, 193 | "outputs": [], 194 | "source": [ 195 | "with pm.Model(coords=dict(store=range(3))) as model:\n", 196 | " ..." 197 | ] 198 | }, 199 | { 200 | "cell_type": "code", 201 | "execution_count": null, 202 | "id": "46ecc77e", 203 | "metadata": { 204 | "cellId": "619w58t2d9m1hd9f91wbtc" 205 | }, 206 | "outputs": [], 207 | "source": [ 208 | "with model:\n", 209 | " prior = pm.sample_prior_predictive()" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": null, 215 | "id": "539e77e0", 216 | "metadata": { 217 | "cellId": "wu4qyqit7xp3eurqkamt" 218 | }, 219 | "outputs": [], 220 | "source": [ 221 | "with model:\n", 222 | " trace = pm.sample()\n", 223 | " trace.extend(prior)" 224 | ] 225 | }, 226 | { 227 | "cell_type": "markdown", 228 | "id": "41105bd8", 229 | "metadata": { 230 | "cellId": "4oqatf6ob9pm6z3icui9xn", 231 | "execution_id": "4786ed0a-7ba9-41a7-bd52-3d0d63e53867" 232 | }, 233 | "source": [ 234 | "## 3. Hierarchical Model (1 parameter)\n", 235 | "3. Propose a hierarchical model for the problem. Put hierarchy on only one model parameter (you choose which one, prefer mean)\n", 236 | "\n", 237 | "**hints:**\n", 238 | "\n", 239 | "1. Use non centered parametrization\n", 240 | "2. Use pm.Deterministic to track reparametrized parameters" 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "id": "5dd46b33", 247 | "metadata": { 248 | "cellId": "cnrc8dhdraapgdgsdwkfk" 249 | }, 250 | "outputs": [], 251 | "source": [ 252 | "with pm.Model(coords=dict(store=range(3))) as model1:\n", 253 | " ..." 254 | ] 255 | }, 256 | { 257 | "cell_type": "code", 258 | "execution_count": null, 259 | "id": "640d3ab2", 260 | "metadata": { 261 | "cellId": "xju91tyb1w48hj4ohn84f" 262 | }, 263 | "outputs": [], 264 | "source": [ 265 | "with model1:\n", 266 | " prior1 = pm.sample_prior_predictive()" 267 | ] 268 | }, 269 | { 270 | "cell_type": "code", 271 | "execution_count": null, 272 | "id": "f30904c0", 273 | "metadata": { 274 | "cellId": "xcagfxukjj7hqfvp5evifa" 275 | }, 276 | "outputs": [], 277 | "source": [ 278 | "with model1:\n", 279 | " trace1 = pm.sample()\n", 280 | " trace1.extend(prior1)" 281 | ] 282 | }, 283 | { 284 | "cell_type": "markdown", 285 | "id": "496c5fa4", 286 | "metadata": { 287 | "cellId": "kgwyfhhluy9ogpss0sw35", 288 | "execution_id": "b2d0036e-557f-4b72-9692-f689f9df0de5" 289 | }, 290 | "source": [ 291 | "## 4. Hierarchical Model (2 parameters)\n", 292 | "4. Propose a hierarchical model for the problem. Put hierarchy on 2 model parameters (you choose which additional one, prefer p)\n", 293 | "\n", 294 | "**hint:**\n", 295 | "\n", 296 | "For Hierarchical probs:\n", 297 | "\n", 298 | "Use LogitNormal distribution (preferred)\n", 299 | "\n", 300 | "1. simple to interpret\n", 301 | "2. easier to parametrize (same you do normal dist but with a transform)" 302 | ] 303 | }, 304 | { 305 | "cell_type": "code", 306 | "execution_count": null, 307 | "id": "1b4a310e", 308 | "metadata": { 309 | "cellId": "ktxax4rbcvnytar4p6zxd" 310 | }, 311 | "outputs": [], 312 | "source": [ 313 | "with pm.Model(coords=dict(store=range(3))) as model2:\n", 314 | " ..." 315 | ] 316 | }, 317 | { 318 | "cell_type": "code", 319 | "execution_count": null, 320 | "id": "24a8918c", 321 | "metadata": { 322 | "cellId": "eb0l343zofthhug48a8tbs" 323 | }, 324 | "outputs": [], 325 | "source": [ 326 | "with model2:\n", 327 | " prior2 = pm.sample_prior_predictive()" 328 | ] 329 | }, 330 | { 331 | "cell_type": "code", 332 | "execution_count": null, 333 | "id": "45db68c5", 334 | "metadata": { 335 | "cellId": "rbxtr9zjw3d202hjsev9ja" 336 | }, 337 | "outputs": [], 338 | "source": [ 339 | "with model2:\n", 340 | " trace2 = pm.sample()\n", 341 | " trace2.extend(prior2)" 342 | ] 343 | }, 344 | { 345 | "cell_type": "markdown", 346 | "id": "ccfda2e6", 347 | "metadata": { 348 | "cellId": "8ne1s0vew8asivh62i6w3g", 349 | "execution_id": "f55cc839-a021-4390-b384-c0e4d0084409" 350 | }, 351 | "source": [ 352 | "## 5. Model Comparison study\n", 353 | "\n", 354 | "5. Perform a model comparison study (look into az.compare)\n", 355 | "\n", 356 | " 1. Interpret the result and choose the best model\n", 357 | " 2. Elaborate on Warnings, if there are any" 358 | ] 359 | }, 360 | { 361 | "cell_type": "code", 362 | "execution_count": null, 363 | "id": "72698fa4", 364 | "metadata": { 365 | "cellId": "wdx8tbpk1cazck2yb8174" 366 | }, 367 | "outputs": [], 368 | "source": [ 369 | "res = az.compare(dict(simple=trace, hierarchy1=trace1, hierarchy2=trace2))" 370 | ] 371 | }, 372 | { 373 | "cell_type": "code", 374 | "execution_count": null, 375 | "id": "5b9eb5dc", 376 | "metadata": { 377 | "cellId": "c5h5tig9frm4ovhcznv6xg" 378 | }, 379 | "outputs": [], 380 | "source": [ 381 | "res" 382 | ] 383 | } 384 | ], 385 | "metadata": { 386 | "kernelspec": { 387 | "display_name": "bayes-workshop", 388 | "language": "python", 389 | "name": "bayes-workshop" 390 | }, 391 | "language_info": { 392 | "codemirror_mode": { 393 | "name": "ipython", 394 | "version": 3 395 | }, 396 | "file_extension": ".py", 397 | "mimetype": "text/x-python", 398 | "name": "python", 399 | "nbconvert_exporter": "python", 400 | "pygments_lexer": "ipython3", 401 | "version": "3.11.3" 402 | }, 403 | "notebookId": "19564aff-7147-40f2-b6a2-cd74f22f7a92", 404 | "notebookPath": "ha-1-pre.ipynb" 405 | }, 406 | "nbformat": 4, 407 | "nbformat_minor": 5 408 | } 409 | -------------------------------------------------------------------------------- /ha/ha-2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "id": "f1589859", 6 | "metadata": { 7 | "cellId": "9qrbvrkxgyea5csyshw3la", 8 | "execution_id": "a6d62ba5-9e5d-4269-a627-8ab23c08239b" 9 | }, 10 | "source": [ 11 | "# HA 2 - Birds" 12 | ] 13 | }, 14 | { 15 | "cell_type": "code", 16 | "execution_count": 213, 17 | "id": "33e2fa16", 18 | "metadata": { 19 | "cellId": "yz96t9t3ci2tom9bxr36p" 20 | }, 21 | "outputs": [], 22 | "source": [ 23 | "import pymc as pm\n", 24 | "import arviz as az\n", 25 | "import numpy as np\n", 26 | "import seaborn as sns\n", 27 | "import xarray as xa\n", 28 | "import matplotlib.pyplot as plt\n", 29 | "import json" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "id": "891835f1", 35 | "metadata": { 36 | "cellId": "aihyn73l4bgugvgtwg4sv", 37 | "execution_id": "5af6e434-db1d-4e1d-a246-0e6c54805c14" 38 | }, 39 | "source": [ 40 | "You run some bird platform and experiment with recommender and censorship systems.\n", 41 | "\n", 42 | "Improving recommendations or censorship leads to \n", 43 | "\n", 44 | "* higher/lower recommendation engagement (**people follow the thread**)\n", 45 | "* higher/lower **reading time** (the spend more time reading threads)\n", 46 | "* There are **like buttons** people tap to further engage\n", 47 | "\n", 48 | "Some historical background stuff\n", 49 | "\n", 50 | "* Historical recommendation engagement **5%**\n", 51 | "* Historical reading time is **Exponential** with historical average reading time 1m (60s)\n", 52 | "* **40%** topicstarters are liked" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "id": "e50ee3c5", 58 | "metadata": { 59 | "cellId": "uv5i4q8ruq9mhno2ljnq", 60 | "execution_id": "da68259f-9734-4873-baf8-6b184f205577" 61 | }, 62 | "source": [ 63 | "```\n", 64 | "impression -> 5% -> read thread ~ Exponential(1/60) -> 40% -> like\n", 65 | " \\-> 95% -> scrolls \\-> 60% did not like\n", 66 | "```" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "id": "4d3f7a40", 72 | "metadata": { 73 | "cellId": "44s7wr0ywchfqrh0dh2ee", 74 | "execution_id": "4e38f351-26b7-4c19-a86e-9900836f26b5" 75 | }, 76 | "source": [ 77 | "You've discussed the possble intervals of the outcomes long time ago and they are the following:\n", 78 | "\n", 79 | "* **+/- 3.5%** change for thread read for the experiments, **except for the D**. For D you considered **+/- 5%**, because it touched sensible censorship topic\n", 80 | "* **+/- 3%** for the reading time which was similar across the experiments\n", 81 | "* **+/- 1.5%** for all the likes related metrics.\n", 82 | "\n", 83 | "**All are RELATIVE**\n", 84 | "\n", 85 | "* **+/- 3%** relative change is considered significant enough\n", 86 | "\n", 87 | "Grading (total 40)\n", 88 | "1. Model: 8pt\n", 89 | " 1. Implement the model (2pt)\n", 90 | " 2. Display the model structure (2pt)\n", 91 | " 3. Sample from it, should have 0 divergences (2pt)\n", 92 | " 4. Plot az.forest_plot with rope (2pt)\n", 93 | "2. Decision Making: \n", 94 | " * 8 cases, 4pt each\n", 95 | " * Each plot has to be commented\n", 96 | "3. No bonus points this time" 97 | ] 98 | }, 99 | { 100 | "cell_type": "code", 101 | "execution_count": 229, 102 | "id": "637fa3bd", 103 | "metadata": { 104 | "cellId": "rj9gewq4i4b2kznz1tp0f6" 105 | }, 106 | "outputs": [], 107 | "source": [ 108 | "data = json.load(open(\"data.json\", \"r\"))" 109 | ] 110 | }, 111 | { 112 | "cell_type": "markdown", 113 | "id": "c81cd885", 114 | "metadata": { 115 | "cellId": "eutigcrc2irko9teb4wn8i", 116 | "execution_id": "99a6ef6a-24af-4cb6-9b4a-9334cdc7114e" 117 | }, 118 | "source": [ 119 | "**What is the best experiment?**\n", 120 | "\n", 121 | "1. Try to answer just looking onto the rope plot..." 122 | ] 123 | }, 124 | { 125 | "cell_type": "markdown", 126 | "id": "ce9be009", 127 | "metadata": { 128 | "cellId": "suau146fnrnd188vl3r6mm", 129 | "execution_id": "30bacd6b-76fe-4c4c-8b0c-d1711eebfd90" 130 | }, 131 | "source": [ 132 | "2. Experiment that maximizes likes *after a recommendation*" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "id": "3c67d75e", 138 | "metadata": { 139 | "cellId": "3pt2syzejrnsmbzmhucslo", 140 | "execution_id": "d8a63521-44c1-46f1-b6d6-519b422b46b9" 141 | }, 142 | "source": [ 143 | "3. Experiment that maximized read time *after a recommendation*" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "id": "b6cc1d5a", 149 | "metadata": { 150 | "cellId": "4mz7fow0gdtft57vnw2av", 151 | "execution_id": "f1b4bdd0-9694-4995-9094-d13e7f64ee33" 152 | }, 153 | "source": [ 154 | "4. Consider valuing (all at once)\n", 155 | " 1. each thread follow up with \\$0.005\n", 156 | " 2. each read second with \\$0.0005\n", 157 | " 3. each like with \\$0.0015\n", 158 | " 4. N users = 100000000" 159 | ] 160 | }, 161 | { 162 | "cell_type": "markdown", 163 | "id": "47f62b8a", 164 | "metadata": { 165 | "cellId": "01pzxrpnxicf953hsdfebdw", 166 | "execution_id": "3dfdca5b-6489-4af6-80a2-bcb98935b19b" 167 | }, 168 | "source": [ 169 | "5. Consider implementation costs for projects and the previous information\n", 170 | " 1. 30000\n", 171 | " 2. 20000\n", 172 | " 3. 15000\n", 173 | " 4. 10000" 174 | ] 175 | }, 176 | { 177 | "cell_type": "markdown", 178 | "id": "653f237b", 179 | "metadata": { 180 | "cellId": "jxbgonhzlbhobt2v9cmqo8", 181 | "execution_id": "b82547cf-d870-41ed-9a57-a046f9e2fd88" 182 | }, 183 | "source": [ 184 | "6. You are going to face people transitioning to another platform. Overall future engagement is quite unsure. Here are scenarios you consider:\n", 185 | " 1. Optimistic: there will be bright future, people will visit the app 5\\% more frequently\n", 186 | " 2. Conservative: nothing will change\n", 187 | " 3. Pessimistic: thought leaders will move to the new platform and take 5\\% of the audience implementation costs are 50% more\n", 188 | " 4. Depression: thought leaders will move to the new platform and take 15\\% of the audience implementation costs are 7 times more" 189 | ] 190 | }, 191 | { 192 | "cell_type": "markdown", 193 | "id": "42acf297", 194 | "metadata": { 195 | "cellId": "c5fipmn6kma0r37itqwdim", 196 | "execution_id": "c36c705f-d776-462a-b8d0-460dc6a7b993" 197 | }, 198 | "source": [ 199 | "7. Among the scenarios, find the probability of being the best among the experiments. Show the heatmap; **Mind the x/y ticks, make sure it is not messed up**\n" 200 | ] 201 | }, 202 | { 203 | "cell_type": "markdown", 204 | "id": "2d6b5474", 205 | "metadata": { 206 | "cellId": "pvccrdzzzsm6e8usjg1lb", 207 | "execution_id": "27735a71-4cf3-4390-b1cd-c8e256e7b647" 208 | }, 209 | "source": [ 210 | "8. You have to be conservative in the decision, find the 5% lower quantile for each experiment and scenario, show it on the heatmap, center it around zero. **Mind the x/y ticks, make sure it is not messed up**" 211 | ] 212 | } 213 | ], 214 | "metadata": { 215 | "language_info": { 216 | "codemirror_mode": { 217 | "name": "ipython", 218 | "version": 3 219 | }, 220 | "file_extension": ".py", 221 | "mimetype": "text/x-python", 222 | "name": "python", 223 | "nbconvert_exporter": "python", 224 | "pygments_lexer": "ipython3", 225 | "version": "3.7.7" 226 | }, 227 | "notebookId": "0bc9f3eb-ca0f-40b0-b7b1-0827ca798f86", 228 | "notebookPath": "ha-2-Copy1.ipynb" 229 | }, 230 | "nbformat": 4, 231 | "nbformat_minor": 5 232 | } 233 | -------------------------------------------------------------------------------- /lectures/.gitattributes: -------------------------------------------------------------------------------- 1 | *.pdf filter=lfs diff=lfs merge=lfs -text 2 | -------------------------------------------------------------------------------- /lectures/practical_bayes_1_intro.pdf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7f40c64cd0113dc90fb6602678ac6f2eef69bd07bb812ece51ebae01fbc2446b 3 | size 6442358 4 | -------------------------------------------------------------------------------- /lectures/practical_bayes_2_priors.pdf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:b104c77b4243cffd8ee1f3fde990c49ad37f10fcd20be8994b581578bdc6c84f 3 | size 4105046 4 | -------------------------------------------------------------------------------- /lectures/practical_bayes_3_AB.pdf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:510a277ef5209c8c18d057b8e9d8ce01d0940d705474c2d08dc57baef846dbad 3 | size 1165950 4 | -------------------------------------------------------------------------------- /lectures/practical_bayes_4_GP.pdf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:63cf614e1f1061ba5a8ef9c7a3c33d9589b6363461f4e8f8ad2b7be999f2960e 3 | size 1208993 4 | -------------------------------------------------------------------------------- /lectures/practical_bayes_5_GP.pdf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:7cff3bdcb8c6704660bce19a598300d7463c256de58a5c22674a42b23b8debd8 3 | size 2506282 4 | -------------------------------------------------------------------------------- /lectures/practical_bayes_6_linear_msu_2023.pdf: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:40928afe42724e4e560651393658b8002b6c15be9ecf7ea9336c026683ee91b4 3 | size 1254490 4 | -------------------------------------------------------------------------------- /seminars/6-r2d2.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": 11, 6 | "id": "ba5250ea", 7 | "metadata": { 8 | "cellId": "jxyc8u48z7dam9titumeww" 9 | }, 10 | "outputs": [], 11 | "source": [ 12 | "import warnings\n", 13 | "\n", 14 | "import arviz as az\n", 15 | "import matplotlib.pyplot as plt\n", 16 | "import numpy as np\n", 17 | "import nutpie\n", 18 | "import pymc as pm\n", 19 | "import scipy.special as sp\n", 20 | "import scipy.stats as st\n", 21 | "from sklearn.datasets import fetch_california_housing\n", 22 | "from sklearn.preprocessing import StandardScaler\n", 23 | "\n", 24 | "warnings.filterwarnings(\"ignore\")" 25 | ] 26 | }, 27 | { 28 | "cell_type": "code", 29 | "execution_count": 12, 30 | "id": "79f0cca5", 31 | "metadata": { 32 | "cellId": "03yrex4k4o1bxn1lgol08nq" 33 | }, 34 | "outputs": [], 35 | "source": [ 36 | "housing = fetch_california_housing(as_frame=True)" 37 | ] 38 | }, 39 | { 40 | "cell_type": "code", 41 | "execution_count": 13, 42 | "id": "45632243", 43 | "metadata": { 44 | "cellId": "wywflocs2hj17u9gj94z" 45 | }, 46 | "outputs": [], 47 | "source": [ 48 | "data = housing[\"data\"].copy()\n", 49 | "target = housing[\"target\"]\n", 50 | "non_negative_variables = [\n", 51 | " \"MedInc\",\n", 52 | " \"HouseAge\",\n", 53 | " \"AveRooms\",\n", 54 | " \"AveBedrms\",\n", 55 | " \"Population\",\n", 56 | " \"AveOccup\",\n", 57 | "]\n", 58 | "data[non_negative_variables] = np.log1p(data[non_negative_variables])\n", 59 | "target = np.log(target)" 60 | ] 61 | }, 62 | { 63 | "cell_type": "code", 64 | "execution_count": 16, 65 | "id": "bb67de46", 66 | "metadata": { 67 | "cellId": "nuysce52mqm104i9jf1" 68 | }, 69 | "outputs": [], 70 | "source": [ 71 | "Xscaler = StandardScaler()\n", 72 | "Yscaler = StandardScaler()\n", 73 | "X = Xscaler.fit_transform(data)\n", 74 | "Y = Xscaler.fit_transform(target.values[:, None])" 75 | ] 76 | } 77 | ], 78 | "metadata": { 79 | "language_info": { 80 | "codemirror_mode": { 81 | "name": "ipython", 82 | "version": 3 83 | }, 84 | "file_extension": ".py", 85 | "mimetype": "text/x-python", 86 | "name": "python", 87 | "nbconvert_exporter": "python", 88 | "pygments_lexer": "ipython3", 89 | "version": "3.7.7" 90 | }, 91 | "notebookId": "ad369ff6-4357-42fd-8149-66553821e949", 92 | "notebookPath": "Untitled.ipynb" 93 | }, 94 | "nbformat": 4, 95 | "nbformat_minor": 5 96 | } 97 | --------------------------------------------------------------------------------