├── .gitignore ├── README.md ├── custom_plotting.py ├── numpyro_examples.ipynb ├── requirements.txt ├── slides.pdf └── thumbnail.png /.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 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 98 | __pypackages__/ 99 | 100 | # Celery stuff 101 | celerybeat-schedule 102 | celerybeat.pid 103 | 104 | # SageMath parsed files 105 | *.sage.py 106 | 107 | # Environments 108 | .env 109 | .venv 110 | env/ 111 | venv/ 112 | ENV/ 113 | env.bak/ 114 | venv.bak/ 115 | 116 | # Spyder project settings 117 | .spyderproject 118 | .spyproject 119 | 120 | # Rope project settings 121 | .ropeproject 122 | 123 | # mkdocs documentation 124 | /site 125 | 126 | # mypy 127 | .mypy_cache/ 128 | .dmypy.json 129 | dmypy.json 130 | 131 | # Pyre type checker 132 | .pyre/ 133 | 134 | # pytype static type analyzer 135 | .pytype/ 136 | 137 | # Cython debug symbols 138 | cython_debug/ -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # A practical introduction to Bayesian hierarchical modelling 2 | This is the supporting material for a talk (webinar?) I gave on June 2021 about hierarchical models. A recording of the talk can be found in this link: https://www.youtube.com/watch?v=38yOWMMCeMk 3 | 4 | ![partial pooling plot](thumbnail.png) 5 | 6 | If you find any mistakes in the material or have any recommendations, I am open to suggestions/comments. 7 | -------------------------------------------------------------------------------- /custom_plotting.py: -------------------------------------------------------------------------------- 1 | import matplotlib.pyplot as plt 2 | import numpy as np 3 | 4 | def spaghetti_plot(x, y, n_samples=20, indices=None, ax=None, plot_kwargs=None): 5 | """ 6 | Plots x against a few picked examples of y. 7 | 8 | Parameters 9 | ---------- 10 | x: 1d array 11 | The values for the x axis 12 | y: 2d array. 13 | First axis (0) is the samples axis. 14 | Second axis (1) are the values for the y axis. 15 | n_samples: int (default 20) 16 | How many sampled values to plot. `n_samples` are 17 | selected uniformly at random. 18 | indices: 1d array 19 | Indices of the specific samples that will be selected 20 | for plotting. 21 | ax: matplotlib.Axes 22 | The axes where the figure will be plotted. 23 | plot_kwargs: dict 24 | Extra arguments passed to `plt.plot` 25 | 26 | Returns 27 | ------- 28 | matplotlib.Axes 29 | 30 | """ 31 | has_indices = indices is not None 32 | has_samples = bool(n_samples) 33 | if has_indices == has_samples: 34 | _msg = "Exactly one of `n_samples` or `indices` must be specified" 35 | raise ValueError(_msg) 36 | 37 | if has_samples: 38 | indices = np.random.choice(range(y.shape[1]), n_samples) 39 | 40 | ax = ax or plt.gca() 41 | for idx in indices: 42 | ax.plot(x, y[idx], **(plot_kwargs or {})) 43 | 44 | return ax 45 | 46 | 47 | def ribbon_plot(x, y, n_ribbons=10, percentile_min=1, percentile_max=99, ribbon_color='r', plot_median=True, line_color='k', ax=None, fill_kwargs=None, line_kwargs=None): 48 | """ 49 | Make a ribbon plot that shows the different quantiles of the 50 | distribution of y against x. 51 | 52 | Parameters 53 | ---------- 54 | x: 1d array 55 | The values for the x axis 56 | y: 2d array 57 | n_ribbons: int (default 10) 58 | How many quantiles to show 59 | percentile_min: float, between 0 and 50 60 | The lowest percentile to be shown 61 | percentile_max: float between 50 and 100 62 | The highest percentile to show. 63 | ribbon_color: str (default 'r') 64 | Color for the ribbons. Must be a valid expression for 65 | matplotlib colors. 66 | plot_median: bool (default True) 67 | Whether or not to plot a line for the 50% percentile 68 | line_color: str (default 'k') 69 | Color to use for the median. 70 | ax: matplotlib.Axes 71 | Where to plot the figure. 72 | fill_kwargs: dict 73 | Extra arguments passed to `plt.fill_between`. 74 | Controls the aspect of the ribbons. 75 | line_kwargs: dict 76 | Extra arguments to be passed to `plt.plot`. 77 | Controls the aspect of the median line. 78 | 79 | Returns 80 | ------- 81 | matplotlib.Axes 82 | """ 83 | perc1 = np.percentile(y, np.linspace( 84 | percentile_min, 50, num=n_ribbons, endpoint=False), axis=0) 85 | perc2 = np.percentile(y, np.linspace( 86 | 50, percentile_max, num=n_ribbons + 1)[1:], axis=0) 87 | fill_kwargs = fill_kwargs or {} 88 | line_kwargs = line_kwargs or {} 89 | alpha = fill_kwargs.pop('alpha', 1 / n_ribbons) 90 | ax = ax or plt.gca() 91 | plt.sca(ax) 92 | 93 | # fill ribbons 94 | for p1, p2 in zip(perc1, perc2): 95 | plt.fill_between(x, p1, p2, alpha=alpha, 96 | color=ribbon_color, **(fill_kwargs or {})) 97 | 98 | if plot_median: 99 | plot_func = plt.step if fill_kwargs.pop("step", None) else plt.plot 100 | plot_func(x, np.median(y, axis=0), 101 | color=line_color, **(line_kwargs or {})) 102 | 103 | return plt.gca() -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | absl-py==0.12.0 2 | anyio==3.1.0 3 | appdirs==1.4.4 4 | appnope==0.1.2 5 | argon2-cffi==20.1.0 6 | arviz==0.11.2 7 | async-generator==1.10 8 | attrs==21.2.0 9 | Babel==2.9.1 10 | backcall==0.2.0 11 | black==21.5b2 12 | bleach==3.3.0 13 | certifi==2021.5.30 14 | cffi==1.14.5 15 | cftime==1.5.0 16 | chardet==4.0.0 17 | click==8.0.1 18 | cycler==0.10.0 19 | decorator==5.0.9 20 | defusedxml==0.7.1 21 | entrypoints==0.3 22 | flake8==3.9.2 23 | flatbuffers==2.0 24 | idna==2.10 25 | ipykernel==5.5.5 26 | ipython==7.24.1 27 | ipython-genutils==0.2.0 28 | ipywidgets==7.6.3 29 | jax==0.2.10 30 | jaxlib==0.1.62 31 | jedi==0.18.0 32 | Jinja2==3.0.1 33 | joblib==1.0.1 34 | json5==0.9.5 35 | jsonschema==3.2.0 36 | jupyter-client==6.1.12 37 | jupyter-core==4.7.1 38 | jupyter-server==1.8.0 39 | jupyterlab==3.0.16 40 | jupyterlab-pygments==0.1.2 41 | jupyterlab-server==2.6.0 42 | jupyterlab-widgets==1.0.0 43 | kiwisolver==1.3.1 44 | MarkupSafe==2.0.1 45 | matplotlib==3.4.2 46 | matplotlib-inline==0.1.2 47 | mccabe==0.6.1 48 | mistune==0.8.4 49 | mypy-extensions==0.4.3 50 | nb-clean==2.0.2 51 | nbclassic==0.3.1 52 | nbclient==0.5.3 53 | nbconvert==6.0.7 54 | nbformat==5.1.3 55 | nbqa==0.10.0 56 | nest-asyncio==1.5.1 57 | netCDF4==1.5.6 58 | notebook==6.4.0 59 | numpy==1.20.3 60 | numpyro==0.6.0 61 | opt-einsum==3.3.0 62 | packaging==20.9 63 | pandas==1.2.4 64 | pandocfilters==1.4.3 65 | parso==0.8.2 66 | pathspec==0.8.1 67 | pexpect==4.8.0 68 | pickleshare==0.7.5 69 | Pillow==8.2.0 70 | prometheus-client==0.11.0 71 | prompt-toolkit==3.0.18 72 | ptyprocess==0.7.0 73 | pycodestyle==2.7.0 74 | pycparser==2.20 75 | pyflakes==2.3.1 76 | Pygments==2.9.0 77 | pyparsing==2.4.7 78 | pyrsistent==0.17.3 79 | python-dateutil==2.8.1 80 | pytz==2021.1 81 | pyzmq==22.1.0 82 | regex==2021.4.4 83 | requests==2.25.1 84 | scikit-learn==0.24.2 85 | scipy==1.6.3 86 | Send2Trash==1.5.0 87 | six==1.16.0 88 | sniffio==1.2.0 89 | terminado==0.10.0 90 | testpath==0.5.0 91 | threadpoolctl==2.1.0 92 | tokenize-rt==4.1.0 93 | toml==0.10.2 94 | tornado==6.1 95 | tqdm==4.61.0 96 | traitlets==5.0.5 97 | typing-extensions==3.10.0.0 98 | urllib3==1.26.5 99 | # Editable install with no version control (watermark==2.2.0) 100 | -e /Users/omarfsosa/anaconda3/envs/numpyro/lib/python3.8/site-packages 101 | wcwidth==0.2.5 102 | webencodings==0.5.1 103 | websocket-client==1.0.1 104 | widgetsnbextension==3.5.1 105 | xarray==0.18.2 106 | -------------------------------------------------------------------------------- /slides.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omarfsosa/tech-talk-hierarchical-models/a85f0bcf56a039a10c4592b9c33362ce98212d45/slides.pdf -------------------------------------------------------------------------------- /thumbnail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/omarfsosa/tech-talk-hierarchical-models/a85f0bcf56a039a10c4592b9c33362ce98212d45/thumbnail.png --------------------------------------------------------------------------------