diff --git a/book/_toc.yml b/book/_toc.yml index e83a25e..f8118c4 100644 --- a/book/_toc.yml +++ b/book/_toc.yml @@ -6,8 +6,9 @@ parts: chapters: - file: simulation/overview.md sections: - - file: simulation/Simulating_Dice.ipynb - - file: simulation/Birth_Month_Simulation.ipynb + - file: simulation/simulating_dice.ipynb + - file: simulation/birth_month_simulation.ipynb + - file: simulation/simulating_other_variables.ipynb - caption: Miscallaneous chapters: - file: references.md diff --git a/book/simulation/Birth_Month_Simulation.ipynb b/book/simulation/birth_month_simulation.ipynb similarity index 100% rename from book/simulation/Birth_Month_Simulation.ipynb rename to book/simulation/birth_month_simulation.ipynb diff --git a/book/simulation/Simulating_Dice.ipynb b/book/simulation/simulating_dice.ipynb similarity index 100% rename from book/simulation/Simulating_Dice.ipynb rename to book/simulation/simulating_dice.ipynb diff --git a/book/simulation/simulating_other_variables.ipynb b/book/simulation/simulating_other_variables.ipynb new file mode 100644 index 0000000..8adb4bd --- /dev/null +++ b/book/simulation/simulating_other_variables.ipynb @@ -0,0 +1,194 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Simulating other Variables\n", + "Up until now we have simulated random variables either uniformly or based on a predefined set of probabilities. However, it is also possible to obtain other distributions by transforming uniformly distributed random variables. In fact, we already applied this approach earlier in our dice example. \n", + "\n", + "To start, let's consider a random variable U2 that is distributed like the square of a uniformly distributed random variable. In this example we use a kernel density estimate rather than a histogram in order to obtain a smoother plot. This is a technique to smoothen a histogram. The bandwidth adjust parameter determines the level of smoothing." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": { + "tags": [ + "thebe-remove-input-init" + ] + }, + "outputs": [], + "source": [ + "import micropip\n", + "\n", + "\n", + "\n", + "await micropip.install(\"seaborn\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import seaborn as sns\n", + "import matplotlib.pyplot as plt\n", + "import scipy as sp" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "U2 = np.random.uniform(size=10000) ** 2\n", + "\n", + "sns.kdeplot(U2, bw_adjust=0.25)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similarly, we can simulate random variables from other known distributions. For example, we know that if $U\\sim U(0,1)$ then $\\frac{-\\ln(1-U)}{\\lambda}$ follows an $\\text{Exp}(\\lambda)$ distribution. You can verify this by deriving the corresponding distribution function. Let's simulate an exponentially distributed random variable below. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "E3 = -np.log(1 - np.random.uniform(size=10000)) / 3\n", + "\n", + "sns.kdeplot(E3, bw_adjust=0.25)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Similary we can find that $(1-U)^{-\\frac{1}{\\alpha}}$ follows a $\\text{Par}(\\alpha, 1)$ distribution." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "Par4 = (1 - np.random.uniform(size=1000)) ** (-1 / 4)\n", + "\n", + "sns.kdeplot(Par4, bw_adjust=0.25)\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "For many commonly used distributions, it would be impractical to manually derive and apply transformations from the uniform distribution every time. Fortunately, libraries like NumPy provide built-in functions to sample directly from these distributions. \n", + "\n", + "Below, you will see examples using the exponential, binomial, and normal distributions. Make sure to check the documentation for details on how to specify parameters—some conventions might differ from standard mathematical notation.\n", + "\n", + "For instance:\n", + "- To get an $\\text{Exp}(3)$ distribution, NumPy expects the scale parameter, which is the inverse of the rate: $\\text{scale} = \\frac{1}{3}$.\n", + "- For the normal distribution, the standard deviation is passed as a parameter—not the variance.\n", + "\n" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# The distributions: exponential, binomial and normal.\n", + "E3 = np.random.exponential(1 / 3, 1000)\n", + "B_20_third = np.random.binomial(20, 1 / 3, 1000)\n", + "Nminus14 = np.random.normal(-1, 2, 1000)\n", + "\n", + "\n", + "plt.figure(figsize=(15, 5))\n", + "\n", + "plt.subplot(1, 3, 1)\n", + "sns.kdeplot(E3, bw_adjust=0.25)\n", + "\n", + "plt.subplot(1, 3, 2)\n", + "sns.histplot(B_20_third, stat=\"proportion\", binwidth=1)\n", + "\n", + "plt.subplot(1, 3, 3)\n", + "sns.kdeplot(Nminus14)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The pictures generated above show the simulated values. For reference, the plot below compares the simulated distributions to their relevant probability density functions and probability mass function. " + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "plt.figure(figsize=(15, 5))\n", + "\n", + "\n", + "plt.subplot(1, 3, 1)\n", + "sns.kdeplot(E3, bw_adjust=0.25)\n", + "x = np.linspace(0, 2, 500)\n", + "y = 3 * np.exp(-3 * x)\n", + "plt.plot(x, y)\n", + "\n", + "\n", + "plt.subplot(1, 3, 2)\n", + "sns.histplot(B_20_third, stat=\"proportion\", binwidth=1)\n", + "x = np.linspace(0, 20, 21)\n", + "y = sp.special.binom(20, x) * ((1 / 3) ** x) * (2 / 3) ** (20 - x)\n", + "plt.scatter(x, y)\n", + "\n", + "plt.subplot(1, 3, 3)\n", + "sns.kdeplot(Nminus14)\n", + "x = np.linspace(-8, 8, 500)\n", + "y = (1 / np.sqrt(2 * np.pi * 4)) * np.exp(-0.5 * (x + 1) * (x + 1) / 4)\n", + "plt.plot(x, y)\n", + "\n", + "plt.tight_layout()\n", + "plt.show()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.5" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +}