diff --git a/01_scientific_stack.ipynb b/01_scientific_stack.ipynb new file mode 100644 index 0000000..694376b --- /dev/null +++ b/01_scientific_stack.ipynb @@ -0,0 +1,662 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Chapter 1: Python's Scientific Stack" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Python itself does not come with any scientific algorithms. However, over time, many third-party libraries emerged that are useful to build machine learning applications. In this context, \"third-party\" means that the libraries are *not* part of Python's standard library.\n", + "\n", + "Among the popular ones are [numpy](https://numpy.org/) (numerical computations, linear algebra), [pandas](https://pandas.pydata.org/) (data processing), [matplotlib](https://matplotlib.org/) (visualisations), and [scikit-learn](https://scikit-learn.org/stable/index.html) (machine learning algorithms).\n", + "\n", + "Before we can import these libraries, we must ensure that they installed on our computers. If you installed Python via the Anaconda Distribution that should already be the case. Otherwise, we can use Python's **package manager** `pip` to install them manually.\n", + "\n", + "`pip` is a so-called command-line interface (CLI), meaning it is a program that is run within a terminal window. JupyterLab allows us to run such a CLI tool from within a notebook by starting a code cell with a single `%` symbol. Here, this does not mean Python's modulo operator but is just an instruction to JupyterLab that the following code is *not* Python." + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: numpy in ./.venv/lib/python3.8/site-packages (1.20.3)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: pandas in ./.venv/lib/python3.8/site-packages (1.2.4)\n", + "Requirement already satisfied: numpy>=1.16.5 in ./.venv/lib/python3.8/site-packages (from pandas) (1.20.3)\n", + "Requirement already satisfied: python-dateutil>=2.7.3 in ./.venv/lib/python3.8/site-packages (from pandas) (2.8.1)\n", + "Requirement already satisfied: pytz>=2017.3 in ./.venv/lib/python3.8/site-packages (from pandas) (2021.1)\n", + "Requirement already satisfied: six>=1.5 in ./.venv/lib/python3.8/site-packages (from python-dateutil>=2.7.3->pandas) (1.16.0)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install pandas" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: matplotlib in ./.venv/lib/python3.8/site-packages (3.4.2)\n", + "Requirement already satisfied: python-dateutil>=2.7 in ./.venv/lib/python3.8/site-packages (from matplotlib) (2.8.1)\n", + "Requirement already satisfied: pyparsing>=2.2.1 in ./.venv/lib/python3.8/site-packages (from matplotlib) (2.4.7)\n", + "Requirement already satisfied: pillow>=6.2.0 in ./.venv/lib/python3.8/site-packages (from matplotlib) (8.2.0)\n", + "Requirement already satisfied: kiwisolver>=1.0.1 in ./.venv/lib/python3.8/site-packages (from matplotlib) (1.3.1)\n", + "Requirement already satisfied: numpy>=1.16 in ./.venv/lib/python3.8/site-packages (from matplotlib) (1.20.3)\n", + "Requirement already satisfied: cycler>=0.10 in ./.venv/lib/python3.8/site-packages (from matplotlib) (0.10.0)\n", + "Requirement already satisfied: six in ./.venv/lib/python3.8/site-packages (from cycler>=0.10->matplotlib) (1.16.0)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install matplotlib" + ] + }, + { + "cell_type": "code", + "execution_count": 4, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Requirement already satisfied: scikit-learn in ./.venv/lib/python3.8/site-packages (0.24.2)\n", + "Requirement already satisfied: joblib>=0.11 in ./.venv/lib/python3.8/site-packages (from scikit-learn) (1.0.1)\n", + "Requirement already satisfied: threadpoolctl>=2.0.0 in ./.venv/lib/python3.8/site-packages (from scikit-learn) (2.1.0)\n", + "Requirement already satisfied: numpy>=1.13.3 in ./.venv/lib/python3.8/site-packages (from scikit-learn) (1.20.3)\n", + "Requirement already satisfied: scipy>=0.19.1 in ./.venv/lib/python3.8/site-packages (from scikit-learn) (1.6.1)\n", + "Note: you may need to restart the kernel to use updated packages.\n" + ] + } + ], + "source": [ + "%pip install scikit-learn" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "After we have ensured that the third-party libraries are installed locally, we can simply go ahead with the `import` statement. All the libraries are commonly imported with shorter prefixes for convenient use later on." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [], + "source": [ + "import numpy as np\n", + "import pandas as pd\n", + "import matplotlib.pyplot as plt" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let's see how the data type provided by these scientific libraries differ from Python's built-in ones.\n", + "\n", + "As an example, we create a `list` object similar to the one from Chapter 0." + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "vector = [1, 2, 3]\n", + "\n", + "vector" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "We call the `list` object by the name `vector` as that is what the data mean conceptually. As we remember from our linear algebra courses, vectors should implement scalar-multiplication. So, the following code cell should result in `[3, 6, 9]` as the answer. Surprisingly, the result is a new `list` with all the elements in `vector` repeated three times. That operation is called **concatenation** and is an example of a concept called **operator overloading**. That means that an operator, like `*` in the example, may exhibit a different behavior depending on the data type of its operands." + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[1, 2, 3, 1, 2, 3, 1, 2, 3]" + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "3 * vector" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`numpy`, among others, provides a data type called an **n-dimensional array**. This may sound fancy at first but when used with only 1 or 2 dimensions, it basically represents vectors and matrices as we know them from linear algebra. Additionally, arrays allow for much faster computations as they are implemented in the very efficient [C language](https://en.wikipedia.org/wiki/C_%28programming_language%29) and optimized for numerical operations." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To create an array, we use the [array()](https://docs.scipy.org/doc/numpy/reference/generated/numpy.array.html#numpy-array) constructor from the imported `np` module and provide it with a `list` of values." + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3])" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v1 = np.array([1, 2, 3])\n", + "\n", + "v1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The vector `v1` can now be multiplied with a scalar yielding a result meaningful in the context of linear algebra." + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([3, 6, 9])" + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v2 = 3 * v1\n", + "\n", + "v2" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To create a matrix, we just use a `list` of (row) `list`s of values." + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 2, 3],\n", + " [4, 5, 6]])" + ] + }, + "execution_count": 10, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1 = np.array([\n", + " [1, 2, 3],\n", + " [4, 5, 6],\n", + "])\n", + "\n", + "m1" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Now we can use `numpy`'s `dot()` function to multiply a matrix with a vector to obtain a new vector ..." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([14, 32])" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "v3 = np.dot(m1, v1)\n", + "\n", + "v3" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... or simply transpose it by accessing its `.T` attribute." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([[1, 4],\n", + " [2, 5],\n", + " [3, 6]])" + ] + }, + "execution_count": 12, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1.T" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The rules from maths still apply and it makes a difference if a vector is multiplied from the left or the right by a matrix. The following operation will fail." + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "ename": "ValueError", + "evalue": "shapes (3,) and (2,3) not aligned: 3 (dim 0) != 2 (dim 0)", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mv1\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mm1\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m<__array_function__ internals>\u001b[0m in \u001b[0;36mdot\u001b[0;34m(*args, **kwargs)\u001b[0m\n", + "\u001b[0;31mValueError\u001b[0m: shapes (3,) and (2,3) not aligned: 3 (dim 0) != 2 (dim 0)" + ] + } + ], + "source": [ + "np.dot(v1, m1)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "In order to retrieve only a **slice** (i.e., subset) of an array's data, we index into it. For example, the first row of the matrix is ..." + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([1, 2, 3])" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[0, :]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "... while the second column is:" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([2, 5])" + ] + }, + "execution_count": 15, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[:, 1]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To acces the lowest element in the right column, two indices can be used." + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "6" + ] + }, + "execution_count": 16, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "m1[1, 2]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "`numpy` also provides various other functions and constants, such as `linspace()` to create an array of equidistant numbers, `sin()` to calculate the sinus values for all numbers in an array, or simple an approximation for `pi`. To further illustrate the concept of **vectorization**, let us calculate the sinus curve over a range of 100 values, going from negative to positive $3\\pi$." + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-9.42477796, -9.23437841, -9.04397885, -8.8535793 , -8.66317974,\n", + " -8.47278019, -8.28238063, -8.09198108, -7.90158152, -7.71118197,\n", + " -7.52078241, -7.33038286, -7.1399833 , -6.94958375, -6.75918419,\n", + " -6.56878464, -6.37838508, -6.18798553, -5.99758598, -5.80718642,\n", + " -5.61678687, -5.42638731, -5.23598776, -5.0455882 , -4.85518865,\n", + " -4.66478909, -4.47438954, -4.28398998, -4.09359043, -3.90319087,\n", + " -3.71279132, -3.52239176, -3.33199221, -3.14159265, -2.9511931 ,\n", + " -2.76079354, -2.57039399, -2.37999443, -2.18959488, -1.99919533,\n", + " -1.80879577, -1.61839622, -1.42799666, -1.23759711, -1.04719755,\n", + " -0.856798 , -0.66639844, -0.47599889, -0.28559933, -0.09519978,\n", + " 0.09519978, 0.28559933, 0.47599889, 0.66639844, 0.856798 ,\n", + " 1.04719755, 1.23759711, 1.42799666, 1.61839622, 1.80879577,\n", + " 1.99919533, 2.18959488, 2.37999443, 2.57039399, 2.76079354,\n", + " 2.9511931 , 3.14159265, 3.33199221, 3.52239176, 3.71279132,\n", + " 3.90319087, 4.09359043, 4.28398998, 4.47438954, 4.66478909,\n", + " 4.85518865, 5.0455882 , 5.23598776, 5.42638731, 5.61678687,\n", + " 5.80718642, 5.99758598, 6.18798553, 6.37838508, 6.56878464,\n", + " 6.75918419, 6.94958375, 7.1399833 , 7.33038286, 7.52078241,\n", + " 7.71118197, 7.90158152, 8.09198108, 8.28238063, 8.47278019,\n", + " 8.66317974, 8.8535793 , 9.04397885, 9.23437841, 9.42477796])" + ] + }, + "execution_count": 17, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "x = np.linspace(-3 * np.pi, 3 * np.pi, 100)\n", + "\n", + "x" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "array([-3.67394040e-16, -1.89251244e-01, -3.71662456e-01, -5.40640817e-01,\n", + " -6.90079011e-01, -8.14575952e-01, -9.09631995e-01, -9.71811568e-01,\n", + " -9.98867339e-01, -9.89821442e-01, -9.45000819e-01, -8.66025404e-01,\n", + " -7.55749574e-01, -6.18158986e-01, -4.58226522e-01, -2.81732557e-01,\n", + " -9.50560433e-02, 9.50560433e-02, 2.81732557e-01, 4.58226522e-01,\n", + " 6.18158986e-01, 7.55749574e-01, 8.66025404e-01, 9.45000819e-01,\n", + " 9.89821442e-01, 9.98867339e-01, 9.71811568e-01, 9.09631995e-01,\n", + " 8.14575952e-01, 6.90079011e-01, 5.40640817e-01, 3.71662456e-01,\n", + " 1.89251244e-01, -1.22464680e-16, -1.89251244e-01, -3.71662456e-01,\n", + " -5.40640817e-01, -6.90079011e-01, -8.14575952e-01, -9.09631995e-01,\n", + " -9.71811568e-01, -9.98867339e-01, -9.89821442e-01, -9.45000819e-01,\n", + " -8.66025404e-01, -7.55749574e-01, -6.18158986e-01, -4.58226522e-01,\n", + " -2.81732557e-01, -9.50560433e-02, 9.50560433e-02, 2.81732557e-01,\n", + " 4.58226522e-01, 6.18158986e-01, 7.55749574e-01, 8.66025404e-01,\n", + " 9.45000819e-01, 9.89821442e-01, 9.98867339e-01, 9.71811568e-01,\n", + " 9.09631995e-01, 8.14575952e-01, 6.90079011e-01, 5.40640817e-01,\n", + " 3.71662456e-01, 1.89251244e-01, 1.22464680e-16, -1.89251244e-01,\n", + " -3.71662456e-01, -5.40640817e-01, -6.90079011e-01, -8.14575952e-01,\n", + " -9.09631995e-01, -9.71811568e-01, -9.98867339e-01, -9.89821442e-01,\n", + " -9.45000819e-01, -8.66025404e-01, -7.55749574e-01, -6.18158986e-01,\n", + " -4.58226522e-01, -2.81732557e-01, -9.50560433e-02, 9.50560433e-02,\n", + " 2.81732557e-01, 4.58226522e-01, 6.18158986e-01, 7.55749574e-01,\n", + " 8.66025404e-01, 9.45000819e-01, 9.89821442e-01, 9.98867339e-01,\n", + " 9.71811568e-01, 9.09631995e-01, 8.14575952e-01, 6.90079011e-01,\n", + " 5.40640817e-01, 3.71662456e-01, 1.89251244e-01, 3.67394040e-16])" + ] + }, + "execution_count": 18, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "y = np.sin(x)\n", + "\n", + "y" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "With `matplotlib`'s [plot()](https://matplotlib.org/api/pyplot_api.html#matplotlib.pyplot.plot) function we can visualize the sinus curve." + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 19, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "iVBORw0KGgoAAAANSUhEUgAAAYcAAAD4CAYAAAAHHSreAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjQuMiwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy8rg+JYAAAACXBIWXMAAAsTAAALEwEAmpwYAABCWUlEQVR4nO29d3hc13Xo+1sz6MCgVxJsIAGwk5Ioim6SLMmyaOdJ7pHy8iLH9tV1Esc3zk0c6fN7jj+nycmLnZdcO7biJjuOJFtx0XUoy5Is0UWmxGIWgERjAdEx6DPomNnvjzkHHIEACWBmTpnZv++bDzOnLpyy115lry1KKTQajUajicZjtwAajUajcR5aOWg0Go3mKrRy0Gg0Gs1VaOWg0Wg0mqvQykGj0Wg0V5FmtwCrobS0VG3cuNFuMTQajcZVHD9+fEApVbacbV2pHDZu3MixY8fsFkOj0WhchYi0L3db7VbSaDQazVVo5aDRaDSaq9DKQaPRaDRXoZWDRqPRaK5CKweNRqPRXEVclIOIfF1E+kWkYYn1IiL/LCJtInJaRG6MWvegiLQanwfjIY9Go9FoYiNelsM3gXuusf4gUGt8HgL+FUBEioG/BG4B9gN/KSJFcZJJo9FoNKskLspBKfVzYOgam9wHfEtFOAIUikgV8HbgeaXUkFJqGHieaysZjYVcHpzgP169zOnOEbtF0RhMzoR4qamfp45eZmYubLc4GkApRVt/gG8faaelL2C3OHHDqkFwa4GOqN+dxrKlll+FiDxExOpg/fr1iZFSA8BjPz/Pk0c7uOAfByDdK3zuvbt5z43VNkuWurT0Bfi7Q+d45fwg04ZS+NHJbv71d2+iIDvdZulSk3BY8YUXWvjhyS46hiYByE738r9+5wbu3FZhs3Sx45qAtFLqMaXUPqXUvrKyZY3+1qyC/32qm7891ERJbgaf/q3t/NfH38zNG4v50++e4p9fbEVPDmU9kzMhPvrt45zsGOGB/ev51of28/fv3c1rF4d4/5dfoWtk0m4RU5LHf32Jf/lZGxtLcvnrd+3kx3/8ZraU5/HfvnWMbx9Z9kBkx2KV5dAFrIv6XW0s6wJuX7D8ZYtk0iygd3SK//uHDexdV8gT/+0Aad5I3+Gbv7+fh//zNJ9/voXxmTkeObjNZklTi0efPceFgXH+4yO38MYtpfPLq4uy+e//fpx3f/FX/Pjjb6bcl2WjlKlFW3+AR59t4o6t5XztwX2ICABPPnSAjz/xG/6fHzYwPRviI2+psVnS1WOV5fAM8HtG1tIBYFQp1QM8B9wtIkVGIPpuY5nGYpRS/PnTp5ieC/H5D+yZVwwAGWke/vEDe3jfTdV87RcX6RiasFHS1OLnLX4e/3U7H3rTptcpBoA3binlyYcOMDg+w1cOX7BJwtRjNhTmE0+dIifDy6Pv3TWvGAByM9P4yv91E3dsLeefXmhlZGLGRkljI16prE8AvwbqRaRTRD4sIh8VkY8amxwCLgBtwL8BfwiglBoC/go4anw+ayzTWMy3j7Tzi9YBPvXO7dSU5V21XkT4s7vr8YjwpZfbbJAw9RiZmOHPnz5FbXken7ynftFtdqwp4N03rOXfj7TTH5iyWMLU5F9ebOVM1yh/955di1praV4Pf3HPVoLTc3ztlxdtkDA+xCtb6QGlVJVSKl0pVa2U+ppS6stKqS8b65VS6o+UUpuVUruUUsei9v26UmqL8flGPOTRrIzRiVn+7lATt9aV8bu3LB3sryzI4oH96/jesU5tPVjA//diK4PBGb7w23vJSvcuud3H3rqFubDS1oMFdAxN8MWXz/OeG9dyz86qJberr/Txzl1VfONXl1xrPbgmIK1JHD882cXkbIhPvr3+dSbyYvzB7Vu09WABU7Mh/vN4J+/YVcXOtQXX3HZjaa62Hiziu8c6CCvFn929uCUXzcfvrHW19aCVQ4qjlOKJ1y6zY03+dRsh0NaDVfykoZexqTnuv3nd9TdGWw9WMBcK871jndxWV8aawuzrbu9260ErhxTndOcoTb0B7t+//LEj2npIPE+8dpkNJTkcqClZ1vbaekg8h1v89I5Ncf/Ny39X3Gw9aOWQ4jx59DLZ6V7u27tm2ftUFmTxrhvW8MzJbqZmQwmULjW54A/y6sUhfvvmdXg813bzRfPR22qYngvz41M9CZQudXnitQ5K8zK5c1v5svepr/Rxx9Zynj7eSTjsrjFCWjmkMOPTczxzspt37q4iP2tlo2x/a/caxmdC/LzFnyDpUpenjnbg9QjvW+GI9C3lPrZW+ni2QSuHeNM3NsVLzf2876Zq0r0razZ/a3cVPaNTnHJZGRqtHFKYH5/uZnwmxAP7l+fXjuYNm0soyE7nJw29CZAsdZmZC/OfJzq5c2s55fkrH9R2cGcVx9qH6R/TrqV48vTxTkJhtewYUDR3bqsg3Suue1e0ckhhnnitgy3ledy4fuWFcNO9Ht62vYLnz/UxPaddS/HixXN9DARneGAFMaBoDu6qRCl4rtFdDZGTCYcVTx69zBtqSthYmrvi/Quy03nTllIONfS4qvyMVg4pyuXBCU52jPDb+9ZdN311Kd6xq5LA1ByvtA3GWbrU5Ucnu6nIz+TWutXVD6stz2NzWS6HzmjlEC9+0zFCx9AkH7h59YUn37Gzio6hSRq7x+IoWWLRyiFFOdzSD8Bd21dfPfJNW0rxZaZpH3ecmA2F+VXbAHdsLce7gkB0NCLCO3ZV8erFQQaD03GWMDU53NyPR+Ct9csPRC/kbdsr8HqEQ2fc865o5ZCiHG7xs744h40lOas+Rmaalzu3lfPTs33MhvTcArFyon2YwPQct9WtvhECuGdnJWEFPz3bFyfJUpvDLX72riukMCdj1ccoys3gDTUlPNvQ6xrXklYOKcj0XIhXzg9ye33Zql1KJgd3VTEyMcuRC9q1FCuHW/ykeYQ3blne2Ial2F6Vz4aSHFf1Up3KYHCa012j3B6D1WByz85KLg6M0+ySCYG0ckhBjl0aZmImxG2r9GtHc1tdGTkZXp51WSaGEznc4ufGDUUrTiteiIhwcGcVvz4/6MqRuU7il20DKEVc3pW376hEBNfEg7RySEEOt/jJ8HqWPfr2WmSle3nr1nKeP9vnGnPZifQHpmjsHotLIwRwcGclc2HFy816HEosHG72U5ybwa5llJa5HmW+TG7eWMzzLnH3aeWQghxu9nPzpiJyM+Mz19Obt5TiD0xzYWA8LsdLRX7RMgDEp4cKsHNtAflZadrdFwPhsOLnrX7eUlu6opHq1+LNW0pp6h1zhUWnlUOK0TM6SXNfIG6NEDBvgeiGaPW83OKnzJfJjjX5cTme1yPs31Si70kMNHaPMRCcifu7ohS8etH509Zo5ZBimOUuYs2IiWZjSQ4V+ZkcueD8B96JhMKKX7T6ubU29gSBaA7UFHNpcIKeUT3H9Gow073fUhs/5bBnXQGZaR5XKO14zQR3j4g0i0ibiDy8yPoviMhJ49MiIiNR60JR656JhzyapTnc4qcyP4u6iqtne1stIsKBmkgvVccdVs7pzhFGJma5rT5+jRBcsehe1Up7VRxu8bNzbT5lvsy4HTMzzctNG4pc0ZGKWTmIiBf4InAQ2A48ICLbo7dRSn1CKbVXKbUX+Bfg+1GrJ811Sql7Y5VHszRzoTC/aB3gtrr49lAh0hD5A9Nc1HGHFXO4xY9H4C0L5oiOlW1V+TrusEpGJ2c5cXkkri4lkwM1Ja6IO8TDctgPtCmlLiilZoAngfuusf0DwBNxOK9mhTR0jxGYmuMtdfFthCA67uD8HpHTeKVtkF1rCyjKXf0gq8XQcYfV89rFIUJhFVeXkokZd3jN4XGHeCiHtUBH1O9OY9lViMgGYBPws6jFWSJyTESOiMi7ljqJiDxkbHfM79fpeavhePswADdvLI77sTeW5FDuy9QN0QqZmQtzqnOEfQm4J6DjDqvlxOVh0jzC3nWFcT/2lbhD8iuHlXA/8LRSKrqM5wal1D7gd4B/EpHNi+2olHpMKbVPKbWvrCz+2jwVOHF5mLWF2VSsohT09dBxh9VxrmeM6bkwN21YeWXc5aDjDqvjePswO9YWkJXujfuxr8QdnN2Riody6AKii5xXG8sW434WuJSUUl3G3wvAy8ANcZBJswgn2ocT1ghBpCHq13GHFWFac4m6L9uq8vHpuMOKmA2FOdUxwk2rKGW/XA7UlHDO4XGHeCiHo0CtiGwSkQwiCuCqrCMR2QoUAb+OWlYkIpnG91LgTcDZOMikWUD3yCQ9o1PcuL4wYec4UBNxjTjdXHYSxxNozUEk7nDLpmJX5NU7hbPdEWvuxg2FCTuHG+IOMSsHpdQc8DHgOeAc8F2lVKOIfFZEorOP7geeVK/3OWwDjonIKeAl4FGllFYOCeBKDzUxvm2ATaW5Ou6wQk60D3NjAq05iDREFwfG6R3Vs8MthxOXE2vNgTviDnGpn6CUOgQcWrDs0wt+f2aR/V4BdsVDBs21Od4+THa6l61VvoSdw4w7vHoxEneId7pssmFaczcl0JqDqLjDxUHu27torogmiuPtw6wpyKKqIDth5zDjDq9edG5HSo+QThFOXB5mz7qCFU+OvlJu2lBE39g0vXoO4+tihTUHsLXSR3a6l99cHknoeZIFK6w5iLwrTb0BJmecOc2uVg4pwORMiLPdYwk1k012V0eqV57qGEn4udzOicuJt+YA0rwedq7N53TnSELPkwx0j0zSPTpl0btSSCisONszmvBzrQatHFKA050jzIUVNyYw+8JkW1U+aR7hVKczH3gncaJ9mN3VibfmINIQNXaP6Rn7roMZb7DiXdljdKROdjjzXdHKIQU4bjzwN1jwwGcZPWHdS702kzMhGi2y5iBi0U3PhWnudccsZHZxon2ErHQP2+NUHfdalOdnUZmf5dh3RSuHFOBE+zA1ZbkUx7k8w1LsqS7kdOco4bAeDLcUpjVnlXIwR/qe1hbdNTl+eZjd1YWWWHMQyVpy6j3RyiHJUUpx4nJiB/QsZE91IYGpOS4O6sFwS2GlNQewvjiHwpx0x/ZSncDUbIjGrlHLFDZE3H0XB8YZnZy17JzLRSuHJOfS4ARD4zPWPvDrIr5U3RAtzYn2EUutORFh19oCHQu6Bqc7RyPWnMUdKYAzDrwvWjkkOWYDvdt4CK1gS1ke2eleTjk00OYEznSNzDcMVrGnupCWPuemTtrNma7I82p2bqxgl5nd58COlFYOSU5j9xgZaR5q4zi5z/XQqZPXpj8wRd/YNDvjMGn9SthdXUAorGjs1kp7MRq7RqnIz6Tcl5hSJotRkJ3OptJcR6Z+a+WQ5DR0jbK10mdZgM1kj06dXJLG7jGAuM0XvVzMoLR2LS1OQ/coO9dYq7AhktLqxKC0Vg5JjFKKhq5RdtjwwO9eV6hTJ5eg0XBfWJEuGY3TUyftZHImRFt/0HKFDRGXb+/YFP0OqyqglUMS0zk8ydjUHDvXWv/AmwN8nNgjspvG7jE2luSQn5Vu+bl3O7SXajdNvWOEFeyw2NUHkXRWcJ5Fp5VDEmP6lu0wlXXq5NI0dI/a0ggB7FlnpE5OOC910k4aDFef1XEggO1VBXg94ri4g1YOSUxD1xhej1BfmdjaPYshIuyuLuSkwx54uxmdmKVjaNIW9wVcSZ083TViy/mdSmPXKEU56awpsC4YbZKd4aW+wue4jCWtHJKYhu5RasvzEjLV4XLYU11Aa39Qp05GYac1B1dSJ7Vr6fU0dEdic3aVmd+zroAzXaOOmmI3LspBRO4RkWYRaRORhxdZ/0ER8YvISePzkah1D4pIq/F5MB7yaCI0do/ZEow22V6VTyisaOnTQWkTuzKVTAqy06kuyuZsz5gt53ciM3NhWnqD7LAhNmeyvSqfkYlZehw0IVPMykFEvMAXgYPAduABEdm+yKZPKaX2Gp+vGvsWA38J3ALsB/5SRKwbnpjE9I9N4Q9M29YIQaRCK8A53RDN09A9SlVBFiV5mbbJsK0qX9+TKFr7A8yEwrZZc+DMdyUelsN+oE0pdUEpNQM8Cdy3zH3fDjyvlBpSSg0DzwP3xEGmlKfBdF/YFPiESFA6N8PrqAfebuxKLY5me1U+lwbGtbvPoLHLvmC0ydYkVQ5rgY6o353GsoW8V0ROi8jTIrJuhftqVkiD8cBbnUsfjccIhp/r0W4lgPHpOS4MjNuSWhzNtqp8wgqatbsPiHSk8jLT2FCcY5sMeZlprC/OcdS7YlVA+n8DG5VSu4lYB4+v9AAi8pCIHBORY36/P+4CJhuN3aPUlOaSlxmXacJXzbaqfM71jjkq0GYXTb1jKGVfMNpkuwN7qXbS2D3G9qp8PB575zzfVuVz1D2Jh3LoAtZF/a42ls2jlBpUSk0bP78K3LTcfaOO8ZhSap9Sal9ZWVkcxE5uGrrGbLUaTLavyScwNUfn8KTdotiOac3ZGfgEqC7KJi8zzVENkV2Ewoqz3WO23xOIjHe4ODjOxMyc3aIA8VEOR4FaEdkkIhnA/cAz0RuISFXUz3uBc8b354C7RaTICETfbSzTxMDw+AxdI5O2+lBNnBhos4uGrlFKcjOozLc+lz4aj0fYWumsXqpdXBwIMjkbst2ag4jloBSOKTkTs3JQSs0BHyPSqJ8DvquUahSRz4rIvcZmHxeRRhE5BXwc+KCx7xDwV0QUzFHgs8YyTQyYaYp2ZiqZbK30IYKjfKl20dgdsebsyqWPJpKxFEj52frmU4sdYDmYHSmnpBnHxSGtlDoEHFqw7NNR3x8BHlli368DX4+HHJoIZo/QfNjsJCcjjY0luSnfS50NhWnrD/KW2o12iwJEno1vH2mnc3iS9SX2BWLt5lxPgHSvsLnMupL2S1FdlI0vyznuPj1COglp7g1QmpdBqY259NFsq/JxrtcZD7xdXBoYZyYUtqWUyWJsq4rI4ZReql009Y6xuSzP8pL2iyEibKvMd4yVbf8V0cSdpt6AYxohgG2V+bQPThCcdkagzQ7OGX5kp9yX+nl3X2orh+beAFsdck8gorSbesYc4e7TyiHJMMtVbK2036VkYrq3mlPYemjujRRB3FJuv/sCIu6+TaWp7e4bNcpV1DvsXRmfCdExPGG3KFo5JBvtg+NMzznHfQGwbY0ZaHOGuWwHzb0BakpzyUyzpwjiYphjUFIVcxCgsywH52T3aeWQZJhpcE564NcUZJHvoECbHTjN1QeRwXAdQ5MEplJzbgfTknXSfamv9OERZ3SktHJIMpp6A4hAbblzHngRSelib8HpyCBAJylsuBKUbnJIXr3VNPUG8GWlUWXDHA5LkZXudYy7TyuHJKO5N8DGklyyM5zjvoCIudzcm5p59c3zwWjn+LbBWS4MOzCD0U4YdxKNUzpSWjkkGc19AeornNVDhYgLY2ImRPuQ/YE2q3Giqw+gMj+Lwpx0RzREVqOUirwrDrsnEFEOkfnf7XX3aeWQREzOhLg0OO7IB77OkCkVJ/5p7h0jN8PL2sJsu0V5HSJCXYWPlr6g3aJYTvfoFIGpOcdZc8B8567V5vuilUMS0dofQCnn9VABao0UztYUVA5NvQHqKn22V/1cjLqKPFr6AilXNdcMRm9z4LtSN68c7H1XtHJIIpocNtAqmtzMNKqLsmlOsV6q6b5wosKGSC81MDVH75hzpqe0AvNdqXPgfakuyiY73Wv7fBtaOSQRzb0BstI9bCjJtVuURamv8NGSYpkx/YFpRiZmHRkHAqitMN19qaW0m3oCrC3MJj8r3W5RrsLjEeoq8rRbSRM/mnsD1Jb78DrQfQGRhujCQJDZUNhuUSyjyaGZSiamCyPVlHazA8edRFNb4dOWgyZ+NDmsTsxC6ivzmA0pLg2M2y2KZZi+bafel+LcDMp8mSmVKDAzF+a8P+ho5VBf4cMfmGZ4fMY2GbRySBIGg9MMBKcd/cDXpaALo6k3QEV+JkW5GXaLsiRmUDpVuDAQZC6sHKuwwRnZfVo5JAlXcumd6b4A2FyWh0dSa2L7iPvCufcEmE9nTZUBis0OTtwwqauIZPe5XjmIyD0i0iwibSLy8CLr/1REzorIaRF5UUQ2RK0LichJ4/PMwn01y8NscOsqnVH1czGy0r1sLMlNGf92KKxo6w9SX+HcewIR5TA5G6JrJDXm+W7uDZDmEWpKnXtfKvOz8GWl2Wplx6wcRMQLfBE4CGwHHhCR7Qs2+w2wTym1G3ga+PuodZNKqb3G5140q6K1P0hhTjplDpngZylqK/Jo6U8N5dAxNMH0XHg+I8ipmO4+p8xdnGha+4NsLM0lI825jhNzgKKdVnY8rs5+oE0pdUEpNQM8CdwXvYFS6iWllFk34QhQHYfzaqJo7QtQV+68OjELqa/wcWlgnKnZkN2iJBzTJVDncOVQa7owUkRpt/YF5t02TqauwkerjQMU46Ec1gIdUb87jWVL8WHg2ajfWSJyTESOiMi7ltpJRB4ytjvm9/tjEjjZUErR0hdkixse+EofYQXn/ckflG7tj/yPTpngZynys9JZU5CVEu6+qdlIfa8tDqpavBT1FXkMT8ziD07bcn5L7SoR+V1gH/APUYs3KKX2Ab8D/JOIbF5sX6XUY0qpfUqpfWVlZRZI6x78wWlGJ2epc3gjBNGlAVJAOfRFBlrlZabZLcp1ieTVJ/89Oe8PohSusRwAWnrtuS/xUA5dwLqo39XGstchIncBnwLuVUrNq0KlVJfx9wLwMnBDHGRKKcyG1unuC4CNJbmkeyUlMpZa+oKOtxpM6it9nPcHmUvyAYpuelfsTmeNh3I4CtSKyCYRyQDuB16XdSQiNwBfIaIY+qOWF4lIpvG9FHgTcDYOMqUU5sPjBrdSRpqHTaXJn7EUCivO+4Ou6KFCpLGcmQsnfUn11v5IptJGh5aYiaY0L5Pi3Az3Kgel1BzwMeA54BzwXaVUo4h8VkTM7KN/APKA7y1IWd0GHBORU8BLwKNKKa0cVohbMpVM6ip8SR/8nM9UcoFvG664WeyuBJpoWvqcn6kUjZ0DFOPiDFVKHQIOLVj26ajvdy2x3yvArnjIkMq09gWoLc9zfKaSSX2Fjx+f7mF8eo5cF/jjV4P5Qte6xHLYUp6HCDT3Brlnp93SJI7WvsD8DHhuoL7Cx/dPdKGUsvz9dof61CyJmank9Fz6aExZzWyeZMT839xyX3Iy0lhXlJPUZTSmZkNcHppwzT2ByPMTmJ6je9T6kupaObgcN2UqmZi96bZkVg59AdYUZLkiU8mktjwvqe/JeX+QsEsylUzMSbLsuC9aObgcM/vCTb2hDcU5ZHg9tCZx3KG1313WHFwpqZ6sGUtmA+uWOBDYOyucVg4ux22+bYA0r4easlzakjSv3qypVOsiaw4ivdTZkErajKWWvgBej7Cp1PmZSiZFuRmU5mVoy0Gzclr7gxRkuydTyWRLeV7SxhzMTCU35NJHUzufsZSc96WlL8jGkhzXZCqZ2PWuuOsqaa7CrBPjlkwlk9pyHx3DE0zOJF+NpfmyGS6y5iBSUh2gLUndfW39QdcpbIi8K3bUWNLKwcW4MVPJpLYiD5WkNZbmXX0ucyvlZqaxtjA7KS26qdkQ7YPjrn1Xxqbm8AesrbGklYOLMTOV3NYIgb1ZGImmrT9IVUEWPgdOXn89ah0wsX0iuOAfJ6zcp7DhSuFGq5W2Vg4uxk11YhayoSSXNI8kZcZSS1/AlT1UiDSe5/1BQkk2K5z5nLnxXTGzq6zOWNLKwcW0utR9AZEaSxtLc5Oul2rWVHLjPYFIQzQ9F6ZzOLkyllr7gq7LVDIpzcugMCddWw6a5TOfqeRzV6aSSTIOuuoanmRqNuyqgVbRbEnSjKXW/oArM5UgMitcbbn17j73XSnNPK1GLr3bMpVMasvzuDQ4zvRc8mQsme4LN0wmsxh2+bcTTeRdcec9gcjz1NJvbcaSVg4upq3fPfMFLMaWisiscBcHxu0WJW64Zfa3pcjPSqcyPyupYkHTcyHaBydce08g0pEamZhlcHzGsnNq5eBSBoPTDI3PuP6Bh+RyYbT2BSn3ZVKQ7b5MJZPaiuRy910amCAUVq6qIrAQOwYoauXgUtxW9XMxNpXm4pHkcmG09Qdc3QhBxOpp6w8STpKMpSuuPvfeF9MlZuUARa0cXMqVImLufeCz0r1sKMlNmhG5Spk1ldyrsCHSEE3MhOgenbRblLjQ1h9E5MoIcDdSkZ+JLzPN0o5UXJSDiNwjIs0i0iYiDy+yPlNEnjLWvyoiG6PWPWIsbxaRt8dDnlSgrT9IboaXqoIsu0WJiS02ZGEkip7RKcZnQq7uoUKUCyNJLLrW/iDri3PISvfaLcqqERG2WDxAMWblICJe4IvAQWA78ICIbF+w2YeBYaXUFuALwOeMfbcTmXN6B3AP8CXjeJrr0NofYEuFz7WZSia15XlcHBhnNgnKRLcmgTUHsMWssZQkSrutz73jTqKptbgAXzwsh/1Am1LqglJqBngSuG/BNvcBjxvfnwbulEirdh/wpFJqWil1EWgzjpcQvvhSG48+25Sow1tKa7I88BV5zIUVl5IgY2l+UKKL40BglonOTIpZ4eZCYS4MBF2bWhxNbbmPgeA0wxZlLMVDOawFOqJ+dxrLFt1GKTUHjAIly9wXABF5SESOicgxv9+/KkGbegP815nuVe3rJEYnZukPTLvefQHRgTb391Lb+oMU52ZQnJthtygxU1ueR1sSFEVsH5pgNqSS4l3ZWuWjvsJnWTqrawLSSqnHlFL7lFL7ysrKVnWM2vI8OocnmZiZi7N01tLmd2/ZjIVsLotMbJ8M/u1Wl487iaa2Io+2vqDlZaLjzfxMiUlwX95SW8Zzn7jVsmcsHsqhC1gX9bvaWLboNiKSBhQAg8vcN27UlkfKRF/wu9uF4cbpDpciO8NLdZH7y0RfyVRyfyMEkXclMD1H35i1ZaLjjVkSfnOS3BcriYdyOArUisgmEckgEmB+ZsE2zwAPGt/fB/xMRbokzwD3G9lMm4Ba4LU4yLQoV7Iw3O1Lbe0LkpXuYW1Rtt2ixAVzMhM34+by6Yth+ujd/64EWFuYTV5mmt2iuI6YlYMRQ/gY8BxwDviuUqpRRD4rIvcam30NKBGRNuBPgYeNfRuB7wJngZ8Af6SUSlihnQ0luaR7xfWpk639QTaX5eH1uDtTyaS2PI8LA+OuntjezOxxezDaJFmmDE0mV5/VxEWdKqUOAYcWLPt01Pcp4P1L7Ps3wN/EQ47rke71sKk01/UujLb+IDdvLLJbjLixpTyPmbkwHcOTriypDMmTxmpSkptBkQ1louNJKBxx9b2hpsRuUVyJawLS8cLtLozg9BxdI5NJ1Rsye9tuvi+t/QF8WWmuLZ++kEiZaJ+rR693DU8yPRdOqnfFSlJOOWwpz+Py0ARTs+4sE31+vupncrgvIDnKRJvjTtw+KDGaLRV5tLg4Y8mMl7i91pVdpJxyqK3II+zijKX5TKUkeuDzMtNYU5DlasshMvtb8ihsiLjIRidn8QfdmbFkvitbypLrvlhF6ikHl2dhtPQHSPcKG4pz7BYlrmyp8LnWchgan2Eg6O7y6YsxP0DRpUHplr4gZb5MCnLcWz7dTlJOOWwszcHrEdeOyG3rC1JTmkeaN7lunTllqBsntr9SNiPJlIPLC/C19QdcO12rE0iuFmYZZKZ52VCS49oUvZYkmC9gMWrL85ieC9M17L4y0S1G41mXJGmsJuW+THxZaa60ssNh5fqpQe0m5ZQDmNUN3ffAT8zM0Tk8mZQPvJsHKLb1BcjLTHN9+fSF2DWxfTzoHp1kYiaUlB0pq0hR5eDj0uAEM3PuGnR1vn8cpUhKU9kMGrrRhdHSFxlolUyZSiaRdFb33RNToSWbNWclqakcKvIIhRWXBt2VsdSSJCWhF6MgJ51yX6Yre6mtSezbrq3IY3B8hkGXZSzNvytJliRgJSmpHObz6l3WELX2ByOZSiXJlalkEpnY3l1uJTNTKRldfXDlXXGb9dDaH8lUKsxxf/l0u0hJ5XClTLS7GqLWvgA1pXmkJ1mmkklteSSd1U2DrpI1U8lkfvS625RDX/Jac1aRnK3MdchK97K+OMd1D3xLf4AtSfzAbynPMya2n7JblGWTrJlKJmsKssjN8LrKctCZSvEhJZUDGBlLLhqRa2Yq1SXxA2/6h900PWWyZiqZiAhbyvNcdU90plJ8SF3lUOFz1cT2yZypZGL2vt00IjeZM5VMal02el1nKsWHlFUO9RU+ZkPumdg+FYqIFeVmUObLpNlFvdTW/mBSK2yIvCv+wDRDFs1dHCvz74rOVIqJlFUOZiPrloaopc/MVHLnfAfLpa7CPS6M4fEZBoLTSe/brquM/H9uuS9mTSWdqRQbMSkHESkWkedFpNX4e9UMNCKyV0R+LSKNInJaRH47at03ReSiiJw0PntjkWclbC7LwyORB8kNtPYF2FSam7SZSiZ1FT5a+4KEXVBjqSXJM5VM6uZnhXOHcmjtC2irIQ7E2tI8DLyolKoFXjR+L2QC+D2l1A7gHuCfRKQwav2fK6X2Gp+TMcqzbLLSvWwszaWl1yUPfH8wKQe/LaS+wsfkbIhOF9RYak3yTCWTyvwsfFlprrCylVKGqy+574kVxKoc7gMeN74/Drxr4QZKqRalVKvxvRvoB8piPG9cqCv30eKCsQ6TMyE6hieSOlPJxFSAbnBhtCZ5ppKJiFBX4XOFld01ojOV4kWsyqFCKdVjfO8FKq61sYjsBzKA81GL/8ZwN31BRJacY1FEHhKRYyJyzO/3xyh2hLpKH5cGxh0/K9x5fxClkt99AVdcGG7opZqT1ydzppJJRDkEHD9A8cpc3snfkUo011UOIvKCiDQs8rkvejsVeWqWfHJEpAr4NvD7Sikzf/QRYCtwM1AM/MVS+yulHlNK7VNK7Ssri4/hUWfMCnfe7+wekdmLTvasGABfVjprCrJcYTm09CV/ppJJfUUeIxOz+APOrrHUqmsqxY20622glLprqXUi0iciVUqpHqPx719iu3zgv4BPKaWORB3btDqmReQbwJ+tSPoYqZ+f2D7IjjUFVp56RaRKppJJXaXzXRipkqlkUjfv7gtSnu9cN1pLX5DSvEyKcnWmUqzE6lZ6BnjQ+P4g8KOFG4hIBvAD4FtKqacXrKsy/gqReEVDjPKsiI2luaR7xfEujJYkr6m0kLoKH+f7g8w5eICi+cyYaZ7Jjvl/uuFdqa/UVkM8iLW1eRR4m4i0AncZvxGRfSLyVWObDwC3Ah9cJGX1OyJyBjgDlAJ/HaM8KyLd66Gm1PllNJp7A9SnSCMEEeUwEwrTPjRhtyhL0mxkuW1NkftSmpdJSW6Go9+VUFhFlENFvt2iJAXXdStdC6XUIHDnIsuPAR8xvv878O9L7H9HLOePB3WVPk52DNstxpKMTc3SNTLJ79yy3m5RLMN097X0Bthc5sxeYFNvgEJjDopUobYiz9GWw+WhCaZmwymjsBNNavgprkFdeR4dQ5OMT8/ZLcqitKRYDxUwMoCc7cJo7h2jvsKXEplKJvXGAEWnZiw1944BpJSVnUi0cjAeJKeWJG4ylEMqPfDZGUZJdYcGpcNhRUtfMKUUNkTeleD0nGNLqjf1BhBJ/kGJVqGVQ4WzA23NvQF8mWmsLcy2WxRLqS33OfaedI1MEpyeo74ytXzbdVHuPifS3BtgQ3EO2Rleu0VJClJeOawvziEzzePoB76uMrXcFwD1lXlcHBhnes55AxRT0ZoD5kfoO1Vpp1riRqJJeeXg9Qi1FXnzM3o5CaUUTb1jKee+gEgvNRRWXHRgSfVU9W0X5KRTme/MAYpTsyEuDY6zNcWsuUSS8soBIj0i84V3Er1jU4xNzaWscoArKaNOoqk3QHVRNnmZMSX7uZLaijxH3pPWviBhlVqJG4lGKwciPcC+sWmGHTaZyRX3Rer1hmrKcknzyPw1cBLNvYGUbYS2VkZmhXPaAMWmFLXmEolWDsC2qkjje67HWdaD2UOrT8Hsi8w0L1vK8xx3T6bnQlwYGE/ZRmhbVT4zc2HHufuaewNkpXtSpsSMFWjlwBXlcNZhDVFzb4CqgiwKctLtFsUWtlflO045nO8fJxRWKWnNgYPflb4AteU+vJ7UStxIJFo5AGW+TMp8mZzrcZYLoynFsy+2VeXTNzbNYNA5lUCb+yKNYqq6lTaX5ZHuFccph1R/VxKBVg4G2xzWS50NhWnrT+0H/oq7zzlKu6k3QLpX2FSamu6LjDQPW8p9jrong8Fp/IHplFXYiUIrB4NtVT7a+oPMOiTQdnFgnNmQSukHfltV5H93ktJuNuo9pUqF3MXYVuVz3D0BHYyON6n7hC9ge1U+M6GwYyb+mc9USuEKkyV5mZT7Mh3XEKWywobIu+IPTDPgEHdfqg5KTDRaORg4LWOpuXcMr0fYXJ6a7guTbVX5jvFvj07M0jM6lbLBaBPnvSsBinMzKMtLnQq5VqCVg0FNaS4ZaR7H+FKbegLUlOaSmZbadWK2VeVz3h9kZs5+d9+53tQORps4TTk0pWCFXCuISTmISLGIPC8ircbfoiW2C0VN9PNM1PJNIvKqiLSJyFPGrHG2kOb1UFfhnLz6xu4xdq517tSlVrGtysdsSDmiam5jd+TZ2LE2tS2H4twMKvOzHNGRmg2FOdcbYGeK35NEEKvl8DDwolKqFnjR+L0Yk0qpvcbn3qjlnwO+oJTaAgwDH45RnpjYVpnP2e4x2+vV+wPT9I5NsWONfuC3O6iX2tg1Srkvk3Kfc+dQtgqnBKVNq1J3pOJPrMrhPuBx4/vjROaBXhbGvNF3AOa80ivaPxFsq8pncHwGf8DeQFtj9ygAO9boB37TvLvP/oaooXtUN0IG26ryaesP2l41t6HLsOb0uxJ3YlUOFUqpHuN7L1CxxHZZInJMRI6IyLuMZSXAiFLKnIKtE1gbozwx4ZTRn6b7Yru2HEjzeqiv8M37++1iciZEW39QW3MG26rymQvb7+5r7B4lO92bsuNOEsl1lYOIvCAiDYt87oveTkV8MUv5YzYopfYBvwP8k4hsXqmgIvKQoWCO+f3+le6+LLY7ZNBVY/coG0pyKMhOzbIZC4m4MAK2uvuaescIK91DNXHKAMXGrjG2r8nXZTMSwHWVg1LqLqXUzkU+PwL6RKQKwPjbv8Qxuoy/F4CXgRuAQaBQRMy6x9VA1zXkeEwptU8pta+srGwF/+LyKchJZ21htu0ujIauMXbqRmie7VX5DI3P0G+ju6/BsOZ04DPCptJcstLtdfeFw4rG7lF2amsuIcTqVnoGeND4/iDwo4UbiEiRiGQa30uBNwFnDUvjJeB919rfauwOtI1OznJ5aEK7lKJwgrvvbPcohUbnQROZJKu+wt535dLgOOMzIXboOFBCiFU5PAq8TURagbuM34jIPhH5qrHNNuCYiJwiogweVUqdNdb9BfCnItJGJAbxtRjliZltVflcGBhncsaeQNvZ+R6qfuBNtprKodu+hqiha4wda/J1Ln0U5gBFu9x9pjWn40CJIaaprJRSg8Cdiyw/BnzE+P4KsGuJ/S8A+2ORId7sWltAKKw42zPKTRuKLT//lUwl/cCbFGSns7Ekh9OdI7acf2YuTHNvgN9/00Zbzu9UdlUX8OTRDjqGJllfkmP5+Ru7R8nweqgtT+1BiYlCj5BewJ51hQCc6hi15fwNXaNU5mdRqksBvI7d1YWc7rTnnrT2B5gJhbX7YgF7qgsBOGWT0m7sGqO+0kdGmm7GEoG+qguoyM+iIj/Ttl5qZGS0thoWsru6gJ7RKfrHpiw/t5larAOfr8dsmO14V5RSxrgTfU8ShVYOi2BXL3ViZo7z/qBOl1yEeYvOhvvS2DVKboaXjXoKyteR7vWwY02+LVZ218gkIxOzbNfvSsLQymER9lQXcGFgnNHJWUvPe64nYOTS697QQnasyccj2NJLbeiO5NJ7dC79VeypLqShe5RQ2NqgtDkyWltziUMrh0Uwe6lnLO6lmsFonal0NTkZadRV+Cy3HEJhxdnuMW3NLcHu6gImjNHjVnK2exSvR+bTnDXxRyuHRdi9thCwPtDW2DVGcW4GVQW6sNti7Kku5HTniKWpkxcHxpmcDWmFvQS7bQpKN3SPsaUsj6z01C5pn0i0cliEghx7UidPdY7oXPprsHtdASMTs3QMTVp2TvMZ0IHPxakpzcWXmWbpu6KU4nTnSMqXTk80WjksgdVB6cDULM19AW7asOiUGBqupE6etLAhOt4+jC8zTefSL4HHI+yqLrA0KH15aIKB4Ix+VxKMVg5LMJ86GbAmdfJkxwhKoR/4azCfOtkxYtk5j7cPs3d9oS7sdg12VxfS1DtmWfnu4+3DgH5XEo1WDkuw1whKn7aoR3S8fRiRK+fVXI2ZOmmVRaetueWxp7qA2ZCyrEKrtuasQSuHJdixpgCvRywLtB1vH6a+wocvS5fpvhZ7qgs50zXKXCjxc0qf6hjV1twyMLP7rIo7nLg8oq05C9DKYQmyM7zUludZkjoZDitOXh7hRt0IXZfd1QVMzoZo8yc+dVJbc8ujqiBS7uWkBe6+wNQszb1j3LhevyuJRiuHa2BV6mRrf5DA9Bw36Qf+upipk1a4+45f1tbcchAR9lQXWOLuO9UxSlhbc5aglcM12Lu+kJGJWS4OjCf0PDrAtnxqSnPxZaVx4vJwQs8TDit+0z6srbllsnddIef9QUYnEltVYN6aW1+Y0PNotHK4Jvs3RUp2v3pxKKHnOd4+TEluBhtsKHvsNjweYf/G4oTfE23NrYz9m4pRCl67lOB3xbDm8rU1l3C0crgGNaW5lPkyOXJhMKHnOXE50kPVg9+Wx4GaEi4OjNM7mrg0Y9My0dbc8tizrpDMNE9C35VwWPGby9qas4qYlIOIFIvI8yLSavy96q6JyFtF5GTUZ0pE3mWs+6aIXIxatzcWeeKNiHCgpoQjFwYTFncYDE5zcWBcN0Ir4EBNCQCvXkxcQ6StuZWRle7lxvVFCVUObf4ggSltzVlFrJbDw8CLSqla4EXj9+tQSr2klNqrlNoL3AFMAD+N2uTPzfVKqZMxyhN3DtQU0zc2zaXBiYQc/8TlEQCdfbECtq/Jx5eZxpELiXNhnGgf5ob12ppbCQdqSjjbM5awuIMZm9OWgzXEqhzuAx43vj8OvOs6278PeFYplZiWNgGYvdRE9YiOtw+T5hF2V+vCbsvF6xH2byrm1QTdk6HxGS5oa27FHKhJbNzhePswxbkZbNTWnCXEqhwqlFI9xvdeoOI6298PPLFg2d+IyGkR+YKILDk3pog8JCLHROSY3++PQeSVkei4w4n2YXasLdDVJVfIgZoSLgyM05eAmeFO6OyxVZHouMOJ9mFu1NacZVxXOYjICyLSsMjnvujtVMQpv6RjXkSqgF3Ac1GLHwG2AjcDxcBfLLW/UuoxpdQ+pdS+srKy64kdNxIZdwhOz3Hi8jAHaorjetxUIJEW3S/bBshK92hrboVkpXu5YX1hQu5J5/AEFwbG9btiIddVDkqpu5RSOxf5/AjoMxp9s/Hvv8ahPgD8QCk175BUSvWoCNPAN4D9sf07iSFRcYdX2gaYCyturyuP63FTgUTGHQ63+HlDTYm25lZBouIOP28ZAOD2eus6hqlOrG6lZ4AHje8PAj+6xrYPsMClFKVYhEi8oiFGeRLCfHZMnHtEh1v85GZ4tftiFSQq7tA+OM7FgXFur9cKezUcqClBKTga57jD4ZZ+1hZms7ksL67H1SxNrMrhUeBtItIK3GX8RkT2ichXzY1EZCOwDji8YP/viMgZ4AxQCvx1jPIkhETEHZRSHG7x88YtpWSk6eEmq8GMO/THMe7w85ZIPOu2Ot1DXQ171xWSEee4w2wozK/aBrmtvkzHGywkLZadlVKDwJ2LLD8GfCTq9yVg7SLb3RHL+a3iStxhCKVUXB7Q8/5xOocn+ehtm+MgYWoyH3e4OMS9e9bE5ZgvN/vZUJLDxtLcuBwv1YiMdyjkSBzHoBxvHyY4PacVtsXoLusyOVBTTO/YFOf98amzdFj3UGNm+5p8fFlp/Kp1IC7Hm54L8cr5QX1PYuRATQmN3WMMjc/E5XiHW/ykeYQ3bi6Jy/E0y0Mrh2XyVsMH/Vxjb1yOd7jFT01ZLuuKdc72avF6hNvry3nhXB+hcOyZZMcuDTM5G9LKIUbu3FqBUvDC2b64HO9ws5+bNhTp6rgWo5XDMllTmM3edYX8pCF25TA1G+LVC4M6SykOHNxZyeD4DK/FoRDf4RY/GV7PvLtKszp2rs2nuiibZxt6rr/xdegfm+Jszxi36Swly9HKYQW8Y1clZ7pG6RiKLaX1yIVBpufC+oGPA7fXl5GV7olLQ3S42c/Nm4rIzYwpFJfyiAgHd1byy7YBRidjS2n9ueEy1Nac9WjlsAIO7qwCiNl6ONziJzPNwy2b9ICeWMnJSOOt9eU829BLOAbXUs/oJM19Ad0IxYmDu6qYDSl+1hSba+lwi58yXybbq/LjJJlmuWjlsALWFeewc20+h2LopSqleKmpn1v0IKu4cc/OSvyBaY7HMAHQz5oi4zdv1cohLuytLqSqIItDZ1bfkZqZC/OLVj9vqS3VKaw2oJXDCjm4s4rfXB6hZ3RyVfsfax/m0uAEv7W7Ks6SpS53bC0nI83DszE0RN871smW8jzqK3xxlCx18XiEt++o5HCLn+D03KqO8eK5PkYmZvk/dscnTVmzMrRyWCEHd1YCq3ctPfHaZfIy07RyiCO+rHRurS3l2YaeVbmWmnrHONkxwv03r9M91Djyjl1VzMyFeanpWlV1luaJox1UFWRpa84mtHJYITVleWyt9K2qlzo6OcuhMz3cu3cNORk66BlPDu6somd0ilOdIyve98nXOsjwenjPjdXxFyyFuWlDEWW+zFUlC3QMTfCLVj/v37cOr0crbDvQymEVHNxZxdH2oRWXi37mZBdTs2EeuHl9giRLXe7aVkG6Vzh0ZmUN0dRsiB/8pou7d1RQnJuRIOlSE69HuGdHJS81+ZmYWZlr6XvHOwH4wD6tsO1CK4dVcO/eiA/0G7+6tOx9lFI88VoHO9bks0uXgo47BTnp3LG1nKeOdjA2tfz0yZ809DI6OcsD+7XCTgTvumEtk7Mh/uPVy8veJxRWfO9YB7fWllFdpAeJ2oVWDqtgU2ku9+5Zw7d+fYnB4PSy9jnTNcrZnjHuv3ldgqVLXf74jlrGpub45gqU9pNHL7OuOJs36IFvCeGmDUW8cXMJXz58gcmZ0LL2OdzST8/olH5XbEYrh1Xyx3fUMjkb4t9+cXFZ2z95tIOsdA/33XBV/UFNnNi5toC7tlXw1V9cWJb1cHFgnCMXhrj/5vV4tF87YfyPO2sZCE7znVfbl7X9k691UJqXwZ3brjexpCaRaOWwSraU5y3beugYmuCHv+ninbvWkK/rwySUP7krYj08vgzr4X/9rA2vR3jfTdqvnUhuqSlZtvVwtnuMF5v6ee9N1bqUvc3oqx8Dy7EeQmHF//zuKTwifOJttRZKl5rMWw+/vHhN6+Gnjb3854lO/vutNVTkZ1koYWqyHOthajbEJ546SXFuBh+9VZeytxutHGIg2npYasKZr/7iAq9dGuIz9+7QwTWL+JO7ahmdnOWrSyhtf2CaR75/hh1r8vmTu+osli41ibYeAkso7X/8aTPNfQH+/n27KdKZY7YTk3IQkfeLSKOIhEVk3zW2u0dEmkWkTUQejlq+SUReNZY/JSKueyI+fmctobDi/V/5NRf8wdetO9czxj/+tIW376jgvTfqWINV7FxbwDt3V/HPL7byry+fR6krA+OUUjzy/dMEpuf4wm/v1a4LC/mfd9cxPDHDB75yhN7R13emfn1+kK/+8iL/5y3r58vja+wl1jejAXgP8POlNhARL/BF4CCwHXhARLYbqz8HfEEptQUYBj4cozyWs7ksjyceOkBgao73/OsrHLs0ROfwBN8+0s4ffucE+dnp/O27d+mRtxbz+Q/s4d49a/jcT5r41A8bmJiZ43CLn08+fZoXzvXzybfXU6dLZVjKTRuK+foHb+by4Djv/tKvaOod4+LAOF/75UU+8dRJNhTn8Kl3brNbTI2BRPeqVn0QkZeBPzOmB1247g3AZ5RSbzd+P2KsehTwA5VKqbmF212Lffv2qWPHrjqVrbQPjvPBbxylfXAcs4LD+uIcHn3PLt64pdRe4VKUcFjx//60mS+9fB6PQFhBZpqHd9+wlr999y6doWQTZ7vH+NA3j9IfmJp/V2rL8/j8B/bqMUAJRkSOK6WW9PJEY0UNh7VAR9TvTuAWoAQYUUrNRS1f0vciIg8BDwGsX++8AUsbSnL5/h+8kS+93EZFfha315ezuSxXWww24vEIn7xnK1ur8jnVMcKba0t5g66Gazvb1+Tzgz96I185fIGaslxurytnfYmOxzmN6yoHEXkBqFxk1aeUUj+Kv0iLo5R6DHgMIpaDVeddCUW5GXzqnduvv6HGUu7ds4Z79+jKnk6iqiCbz9y7w24xNNfguspBKXVXjOfoAqKHOlYbywaBQhFJM6wHc7lGo9FobMaKVI2jQK2RmZQB3A88oyLBjpeA9xnbPQhYZoloNBqNZmliTWV9t4h0Am8A/ktEnjOWrxGRQwCGVfAx4DngHPBdpVSjcYi/AP5URNqIxCC+Fos8Go1Go4kPcclWshonZitpNBqN01lJtpIeAaTRaDSaq9DKQaPRaDRXoZWDRqPRaK5CKweNRqPRXIUrA9Ii4gcWq/1bCgxYLM5K0PLFjtNldLp84HwZtXyxs5SMG5RSZcs5gCuVw1KIyLHlRuLtQMsXO06X0enygfNl1PLFTjxk1G4ljUaj0VyFVg4ajUajuYpkUw6P2S3AddDyxY7TZXS6fOB8GbV8sROzjEkVc9BoNBpNfEg2y0Gj0Wg0cUArB41Go9FcheuUg4i8X0QaRSQsIvsWrHtERNpEpFlEFp1u1Cgd/qqx3VNGGfFEyfqUiJw0PpdE5OQS210SkTPGdpZVFBSRz4hIV5SM71hiu3uMa9omIg9bJZ9x7n8QkSYROS0iPxCRwiW2s/QaXu+aiEimcf/bjOdtY6Jlijr3OhF5SUTOGu/K/1hkm9tFZDTq3n/aKvmiZLjmPZMI/2xcw9MicqOFstVHXZuTIjImIn+yYBvLr6GIfF1E+kWkIWpZsYg8LyKtxt+iJfZ90NimVUQevO7JlFKu+gDbgHrgZWBf1PLtwCkgE9gEnAe8i+z/XeB+4/uXgT+wSO5/BD69xLpLQKkN1/IzROb+vtY2XuNa1gAZxjXebqGMdwNpxvfPAZ+z+xou55oAfwh82fh+P/CUhdesCrjR+O4DWhaR73bgx1Y/cyu5Z8A7gGcBAQ4Ar9okpxfoJTKAzNZrCNwK3Ag0RC37e+Bh4/vDi70jQDFwwfhbZHwvuta5XGc5KKXOKaWaF1l1H/CkUmpaKXURaAP2R28gkQmd7wCeNhY9DrwrgeJGn/cDwBOJPlcC2A+0KaUuKKVmgCeJXGtLUEr9VF2ZZ/wIkRkD7WY51+Q+Is8XRJ63O8WiCcWVUj1KqRPG9wCReVSWnJ/dwdwHfEtFOEJk5sgqG+S4EzivlFqsKoOlKKV+DgwtWBz9rC3Vpr0deF4pNaSUGgaeB+651rlcpxyuwVqgI+p3J1e/ECXASFRjs9g2ieAtQJ9SqnWJ9Qr4qYgcF5GHLJAnmo8ZJvvXlzBHl3NdreJDRHqSi2HlNVzONZnfxnjeRok8f5ZiuLNuAF5dZPUbROSUiDwrInZM6Hy9e+aUZ+9+lu7Y2X0NASqUUj3G916gYpFtVnwtrzuHtB2IyAtA5SKrPqWUctRUosuU9QGubTW8WSnVJSLlwPMi0mT0EBIqH/CvwF8ReUn/iojr60PxOO9KWM41FJFPAXPAd5Y4TMKuoVsRkTzgP4E/UUqNLVh9goibJGjEmn4I1FosouPvmRGTvBd4ZJHVTriGr0MppUQkLuMTHKkclFJ3rWK3LmBd1O9qY1k0g0RM0zSjN7fYNivierKKSBrwHuCmaxyjy/jbLyI/IOK2iMtLstxrKSL/Bvx4kVXLua4xsYxr+EHgt4A7leFAXeQYCbuGi7Cca2Ju02k8AwVEnj9LEJF0IorhO0qp7y9cH60slFKHRORLIlKqlLKsoNwy7lnCn71lcBA4oZTqW7jCCdfQoE9EqpRSPYbbrX+RbbqIxEhMqonEbZckmdxKzwD3G1kim4ho8NeiNzAalpeA9xmLHgQSbYncBTQppToXWykiuSLiM78TCcA2LLZtvFngv333Euc9CtRKJMsrg4iJ/YwV8kEkKwj4JHCvUmpiiW2svobLuSbPEHm+IPK8/WwpxRZvjNjG14BzSqnPL7FNpRkDEZH9RNoCK5XXcu7ZM8DvGVlLB4DRKPeJVSxp9dt9DaOIftaWatOeA+4WkSLDfXy3sWxprIy0x+NDpBHrBKaBPuC5qHWfIpJF0gwcjFp+CFhjfK8hojTagO8BmQmW95vARxcsWwMcipLnlPFpJOJKsepafhs4A5w2HrCqhfIZv99BJOPlvJXyGeduI+IrPWl8vrxQRjuu4WLXBPgsESUGkGU8X23G81Zj4TV7MxFX4emo6/YO4KPmswh8zLhWp4gE+t9o8X1d9J4tkFGALxrX+AxR2YkWyZhLpLEviFpm6zUkoqh6gFmjHfwwkVjWi0Ar8AJQbGy7D/hq1L4fMp7HNuD3r3cuXT5Do9FoNFeRTG4ljUaj0cQJrRw0Go1GcxVaOWg0Go3mKrRy0Gg0Gs1VaOWg0Wg0mqvQykGj0Wg0V6GVg0aj0Wiu4v8Hg5zqbaUp4PoAAAAASUVORK5CYII=\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "plt.plot(x, y)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Let us quickly generate some random data and draw a scatter plot with `numpy`'s `random` module." + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 20, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
" + ] + }, + "metadata": { + "needs_background": "light" + }, + "output_type": "display_data" + } + ], + "source": [ + "x = np.random.normal(42, 3, 100)\n", + "y = np.random.gamma(7, 1, 100)\n", + "\n", + "plt.scatter(x, y)" + ] + } + ], + "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.8.9" + }, + "toc": { + "base_numbering": 1, + "nav_menu": {}, + "number_sections": false, + "sideBar": true, + "skip_h1_title": false, + "title_cell": "Table of Contents", + "title_sidebar": "Contents", + "toc_cell": false, + "toc_position": {}, + "toc_section_display": true, + "toc_window_display": false + } + }, + "nbformat": 4, + "nbformat_minor": 4 +} diff --git a/README.md b/README.md index 49dd930..fdd6a87 100644 --- a/README.md +++ b/README.md @@ -10,7 +10,7 @@ To learn about Python and programming in detail, ### Table of Contents - *Chapter 0*: [Python in a Nutshell](00_python_in_a_nutshell.ipynb) -- *Chapter 1*: Python's Scientific Stack +- *Chapter 1*: [Python's Scientific Stack](01_scientific_stack.ipynb) - *Chapter 2*: [A first Example: Classifying Flowers](02_a_first_example.ipynb) - *Chapter 3*: [Case Study: House Prices in Ames, Iowa ](https://github.com/webartifex/ames-housing)