├── Basics Of Algebra by Hiren ├── 01-01-Introduction to Equations.ipynb ├── 01-02-Linear Equations.ipynb ├── 01-03-Systems of Equations.ipynb ├── 01-04-Exponentials Radicals and Logarithms.ipynb ├── 01-05-Polynomials.ipynb ├── 01-06-Factorization.ipynb ├── 01-07-Quadratic Equations.ipynb └── 01-08-Functions.ipynb ├── Basics of Calculus by Hiren ├── 02-01-Rate of Change.ipynb ├── 02-02-Limits.ipynb ├── 02-03-Differentiation and Derivatives.ipynb ├── 02-04-Critical Points and Optimization.ipynb ├── 02-05-Multivariate Functions and Partial Derivatives.ipynb └── 02-06-Integration.ipynb ├── Cheat Sheet Suggested by Siraj Raval ├── Calculus Cheat Sheet.pdf ├── Linear Algebra CheatSheet.pdf └── Statistics Cheat Sheet.pdf ├── LICENSE ├── Other Cheat Sheets ├── Probability │ ├── probability_cheatsheet (1).pdf │ └── probability_cheatsheet.pdf ├── Statistics │ └── 427513-Statistics-Reference-Cheatsheet.pdf ├── calculus │ ├── Calculus_Cheat_Sheet_All.pdf │ └── Final Notes for AB and BC.pdf └── linear Algebra │ ├── A-linalg.pdf │ └── linear-algebra.pdf ├── README.md ├── Statistics and Probability by Hiren ├── 04-01-Data and Visualization.ipynb ├── 04-02-Statistics Fundamentals.ipynb ├── 04-03-Comparing Data.ipynb ├── 04-04-Probability.ipynb ├── 04-05-Sampling Distributions.ipynb └── 04-06-Hypothesis Testing.ipynb └── Vector and Matrices by Hiren ├── 03-01-Vectors.ipynb ├── 03-02-Vector Multiplication.ipynb ├── 03-03-Matrices.ipynb ├── 03-04-More Matrices.ipynb └── 03-05-Transformations Eigenvectors and Eigenvalues.ipynb /Basics Of Algebra by Hiren/01-01-Introduction to Equations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": { 6 | "collapsed": true 7 | }, 8 | "source": [ 9 | "# Getting Started with Equations\n", 10 | "Equations are calculations in which one or more variables represent unknown values. In this notebook, you'll learn some fundamental techniques for solving simple equations.\n", 11 | "\n", 12 | "## One Step Equations\n", 13 | "Consider the following equation:\n", 14 | "\n", 15 | "\\begin{equation}x + 16 = -25\\end{equation}\n", 16 | "\n", 17 | "The challenge here is to find the value for **x**, and to do this we need to *isolate the variable*. In this case, we need to get **x** onto one side of the \"=\" sign, and all of the other values onto the other side. To accomplish this we'll follow these rules:\n", 18 | "1. Use opposite operations to cancel out the values we don't want on one side. In this case, the left side of the equation includes an addition of 16, so we'll cancel that out by subtracting 16 and the left side of the equation becomes **x + 16 - 16**.\n", 19 | "2. Whatever you do to one side, you must also do to the other side. In this case, we subtracted 16 from the left side, so we must also subtract 16 from the right side of the equation, which becomes **-25 - 16**.\n", 20 | "Our equation now looks like this:\n", 21 | "\n", 22 | "\\begin{equation}x + 16 - 16 = -25 - 16\\end{equation}\n", 23 | "\n", 24 | "Now we can calculate the values on both side. On the left side, 16 - 16 is 0, so we're left with:\n", 25 | "\n", 26 | "\\begin{equation}x = -25 - 16\\end{equation}\n", 27 | "\n", 28 | "Which yields the result **-41**. Our equation is now solved, as you can see here:\n", 29 | "\n", 30 | "\\begin{equation}x = -41\\end{equation}\n", 31 | "\n", 32 | "It's always good practice to verify your result by plugging the variable value you've calculated into the original equation and ensuring that it holds true. We can easily do that by using some simple Python code.\n", 33 | "\n", 34 | "To verify the equation using Python code, place the cursor in the following cell and then click the ►| button in the toolbar." 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": { 41 | "collapsed": true 42 | }, 43 | "outputs": [], 44 | "source": [ 45 | "x = -41\n", 46 | "x + 16 == -25" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "## Two-Step Equations\n", 54 | "The previous example was fairly simple - you could probably work it out in your head. So what about something a little more complex?\n", 55 | "\n", 56 | "\\begin{equation}3x - 2 = 10 \\end{equation}\n", 57 | "\n", 58 | "As before, we need to isolate the variable **x**, but this time we'll do it in two steps. The first thing we'll do is to cancel out the *constants*. A constant is any number that stands on its own, so in this case the 2 that we're subtracting on the left side is a constant. We'll use an opposite operation to cancel it out on the left side, so since the current operation is to subtract 2, we'll add 2; and of course whatever we do on the left side we also need to do on the right side, so after the first step, our equation looks like this:\n", 59 | "\n", 60 | "\\begin{equation}3x - 2 + 2 = 10 + 2 \\end{equation}\n", 61 | "\n", 62 | "Now the -2 and +2 on the left cancel one another out, and on the right side, 10 + 2 is 12; so the equation is now:\n", 63 | "\n", 64 | "\\begin{equation}3x = 12 \\end{equation}\n", 65 | "\n", 66 | "OK, time for step two - we need to deal with the *coefficients* - a coefficient is a number that is applied to a variable. In this case, our expression on the left is 3x, which means x multiplied by 3; so we can apply the opposite operation to cancel it out as long as we do the same to the other side, like this:\n", 67 | "\n", 68 | "\\begin{equation}\\frac{3x}{3} = \\frac{12}{3} \\end{equation}\n", 69 | "\n", 70 | "3x ÷ 3 is x, so we've now isolated the variable\n", 71 | "\n", 72 | "\\begin{equation}x = \\frac{12}{3} \\end{equation}\n", 73 | "\n", 74 | "And we can calculate the result as 12/3 which is **4**:\n", 75 | "\n", 76 | "\\begin{equation}x = 4 \\end{equation}\n", 77 | "\n", 78 | "Let's verify that result using Python:" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": { 85 | "collapsed": true 86 | }, 87 | "outputs": [], 88 | "source": [ 89 | "x = 4\n", 90 | "3*x - 2 == 10" 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "## Combining Like Terms\n", 98 | "Like terms are elements of an expression that relate to the same variable or constant (with the same *order* or *exponential*, which we'll discuss later). For example, consider the following equation:\n", 99 | "\n", 100 | "\\begin{equation}\\textbf{5x} + 1 \\textbf{- 2x} = 22 \\end{equation}\n", 101 | "\n", 102 | "In this equation, the left side includes the terms **5x** and **- 2x**, both of which represent the variable **x** multiplied by a coefficent. Note that we include the sign (+ or -) in front of the value.\n", 103 | "\n", 104 | "We can rewrite the equation to combine these like terms:\n", 105 | "\n", 106 | "\\begin{equation}\\textbf{5x - 2x} + 1 = 22 \\end{equation}\n", 107 | "\n", 108 | "We can then simply perform the necessary operations on the like terms to consolidate them into a single term:\n", 109 | "\n", 110 | "\\begin{equation}\\textbf{3x} + 1 = 22 \\end{equation}\n", 111 | "\n", 112 | "Now, we can solve this like any other two-step equation. First we'll remove the constants from the left side - in this case, there's a constant expression that adds 1, so we'll use the opposite operation to remove it and do the same on the other side:\n", 113 | "\n", 114 | "\\begin{equation}3x + 1 - 1 = 22 - 1 \\end{equation}\n", 115 | "\n", 116 | "That gives us:\n", 117 | "\n", 118 | "\\begin{equation}3x = 21 \\end{equation}\n", 119 | "\n", 120 | "Then we'll deal with the coefficients - in this case x is multiplied by 3, so we'll divide by 3 on boths sides to remove that:\n", 121 | "\n", 122 | "\\begin{equation}\\frac{3x}{3} = \\frac{21}{3} \\end{equation}\n", 123 | "\n", 124 | "This give us our answer:\n", 125 | "\n", 126 | "\\begin{equation}x = 7 \\end{equation}" 127 | ] 128 | }, 129 | { 130 | "cell_type": "code", 131 | "execution_count": null, 132 | "metadata": { 133 | "collapsed": true 134 | }, 135 | "outputs": [], 136 | "source": [ 137 | "x = 7\n", 138 | "5*x + 1 - 2*x == 22" 139 | ] 140 | }, 141 | { 142 | "cell_type": "markdown", 143 | "metadata": {}, 144 | "source": [ 145 | "## Working with Fractions\n", 146 | "Some of the steps in solving the equations above have involved working wth fractions - which in themselves are actually just division operations. Let's take a look at an example of an equation in which our variable is defined as a fraction:\n", 147 | "\n", 148 | "\\begin{equation}\\frac{x}{3} + 1 = 16 \\end{equation}\n", 149 | "\n", 150 | "We follow the same approach as before, first removing the constants from the left side - so we'll subtract 1 from both sides.\n", 151 | "\n", 152 | "\\begin{equation}\\frac{x}{3} = 15 \\end{equation}\n", 153 | "\n", 154 | "Now we need to deal with the fraction on the left so that we're left with just **x**. The fraction is x/3 which is another way of saying *x divided by 3*, so we can apply the opposite operation to both sides. In this case, we need to multiply both sides by the denominator under our variable, which is 3. To make it easier to work with a term that contains fractions, we can express whole numbers as fractions with a denominator of 1; so on the left, we can express 3 as 3/1 and multiply it with x/3. Note that the notation for mutiplication is a **•** symbol rather than the standard *x* multiplication operator (which would cause confusion with the variable **x**) or the asterisk symbol used by most programming languages.\n", 155 | "\n", 156 | "\\begin{equation}\\frac{3}{1} \\cdot \\frac{x}{3} = 15 \\cdot 3 \\end{equation}\n", 157 | "\n", 158 | "This gives us the following result:\n", 159 | "\n", 160 | "\\begin{equation}x = 45 \\end{equation}\n", 161 | "\n", 162 | "Let's verify that with some Python code:" 163 | ] 164 | }, 165 | { 166 | "cell_type": "code", 167 | "execution_count": null, 168 | "metadata": { 169 | "collapsed": true 170 | }, 171 | "outputs": [], 172 | "source": [ 173 | "x = 45\n", 174 | "x/3 + 1 == 16" 175 | ] 176 | }, 177 | { 178 | "cell_type": "markdown", 179 | "metadata": {}, 180 | "source": [ 181 | "Let's look at another example, in which the variable is a whole number, but its coefficient is a fraction:\n", 182 | "\n", 183 | "\\begin{equation}\\frac{2}{5}x + 1 = 11 \\end{equation}\n", 184 | "\n", 185 | "As usual, we'll start by removing the constants from the variable expression; so in this case we need to subtract 1 from both sides:\n", 186 | "\n", 187 | "\\begin{equation}\\frac{2}{5}x = 10 \\end{equation}\n", 188 | "\n", 189 | "Now we need to cancel out the fraction. The expression equates to two-fifths times x, so the opposite operation is to divide by 2/5; but a simpler way to do this with a fraction is to multiply it by its *reciprocal*, which is just the inverse of the fraction, in this case 5/2. Of course, we need to do this to both sides:\n", 190 | "\n", 191 | "\\begin{equation}\\frac{5}{2} \\cdot \\frac{2}{5}x = \\frac{10}{1} \\cdot \\frac{5}{2} \\end{equation}\n", 192 | "\n", 193 | "That gives us the following result:\n", 194 | "\n", 195 | "\\begin{equation}x = \\frac{50}{2} \\end{equation}\n", 196 | "\n", 197 | "Which we can simplify to:\n", 198 | "\n", 199 | "\\begin{equation}x = 25 \\end{equation}\n", 200 | "\n", 201 | "We can confirm that with Python:" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": null, 207 | "metadata": { 208 | "collapsed": true 209 | }, 210 | "outputs": [], 211 | "source": [ 212 | "x = 25\n", 213 | "2/5 * x + 1 ==11" 214 | ] 215 | }, 216 | { 217 | "cell_type": "markdown", 218 | "metadata": {}, 219 | "source": [ 220 | "## Equations with Variables on Both Sides\n", 221 | "So far, all of our equations have had a variable term on only one side. However, variable terms can exist on both sides. \n", 222 | "\n", 223 | "Consider this equation:\n", 224 | "\n", 225 | "\\begin{equation}3x + 2 = 5x - 1 \\end{equation}\n", 226 | "\n", 227 | "This time, we have terms that include **x** on both sides. Let's take exactly the same approach to solving this kind of equation as we did for the previous examples. First, let's deal with the constants by adding 1 to both sides. That gets rid of the -1 on the right:\n", 228 | "\n", 229 | "\\begin{equation}3x + 3 = 5x \\end{equation}\n", 230 | "\n", 231 | "Now we can eliminate the variable expression from one side by subtracting 3x from both sides. That gets rid of the 3x on the left:\n", 232 | "\n", 233 | "\\begin{equation}3 = 2x \\end{equation}\n", 234 | "\n", 235 | "Next, we can deal with the coefficient by dividing both sides by 2:\n", 236 | "\n", 237 | "\\begin{equation}\\frac{3}{2} = x \\end{equation}\n", 238 | "\n", 239 | "Now we've isolated x. It looks a little strange because we usually have the variable on the left side, so if it makes you more comfortable you can simply reverse the equation:\n", 240 | "\n", 241 | "\\begin{equation}x = \\frac{3}{2} \\end{equation}\n", 242 | "\n", 243 | "Finally, this answer is correct as it is; but 3/2 is an improper fraction. We can simplify it to:\n", 244 | "\n", 245 | "\\begin{equation}x = 1\\frac{1}{2} \\end{equation}\n", 246 | "\n", 247 | "So x is 11/2 (which is of course 1.5 in decimal notation).\n", 248 | "Let's check it in Python:" 249 | ] 250 | }, 251 | { 252 | "cell_type": "code", 253 | "execution_count": null, 254 | "metadata": { 255 | "collapsed": true 256 | }, 257 | "outputs": [], 258 | "source": [ 259 | "x = 1.5\n", 260 | "3*x + 2 == 5*x -1" 261 | ] 262 | }, 263 | { 264 | "cell_type": "markdown", 265 | "metadata": {}, 266 | "source": [ 267 | "## Using the Distributive Property\n", 268 | "The distributive property is a mathematical law that enables us to distribute the same operation to terms within parenthesis. For example, consider the following equation:\n", 269 | "\n", 270 | "\\begin{equation}\\textbf{4(x + 2)} + \\textbf{3(x - 2)} = 16 \\end{equation}\n", 271 | "\n", 272 | "The equation includes two operations in parenthesis: **4(*x* + 2)** and **3(*x* - 2)**. Each of these operations consists of a constant by which the contents of the parenthesis must be multipled: for example, 4 times (*x* + 2). The distributive property means that we can achieve the same result by multiplying each term in the parenthesis and adding the results, so for the first parenthetical operation, we can multiply 4 by *x* and add it to 4 times +2; and for the second parenthetical operation, we can calculate 3 times *x* + 3 times -2). Note that the constants in the parenthesis include the sign (+ or -) that preceed them:\n", 273 | "\n", 274 | "\\begin{equation}4x + 8 + 3x - 6 = 16 \\end{equation}\n", 275 | "\n", 276 | "Now we can group our like terms:\n", 277 | "\n", 278 | "\\begin{equation}7x + 2 = 16 \\end{equation}\n", 279 | "\n", 280 | "Then we move the constant to the other side:\n", 281 | "\n", 282 | "\\begin{equation}7x = 14 \\end{equation}\n", 283 | "\n", 284 | "And now we can deal with the coefficient:\n", 285 | "\n", 286 | "\\begin{equation}\\frac{7x}{7} = \\frac{14}{7} \\end{equation}\n", 287 | "\n", 288 | "Which gives us our anwer:\n", 289 | "\n", 290 | "\\begin{equation}x = 2 \\end{equation}\n", 291 | "\n", 292 | "Here's the original equation with the calculated value for *x* in Python:" 293 | ] 294 | }, 295 | { 296 | "cell_type": "code", 297 | "execution_count": null, 298 | "metadata": { 299 | "collapsed": true 300 | }, 301 | "outputs": [], 302 | "source": [ 303 | "x = 2\n", 304 | "4*(x + 2) + 3*(x - 2) == 16" 305 | ] 306 | } 307 | ], 308 | "metadata": { 309 | "kernelspec": { 310 | "display_name": "Python 3.6", 311 | "language": "python", 312 | "name": "python36" 313 | }, 314 | "language_info": { 315 | "codemirror_mode": { 316 | "name": "ipython", 317 | "version": 3 318 | }, 319 | "file_extension": ".py", 320 | "mimetype": "text/x-python", 321 | "name": "python", 322 | "nbconvert_exporter": "python", 323 | "pygments_lexer": "ipython3", 324 | "version": "3.6.3" 325 | } 326 | }, 327 | "nbformat": 4, 328 | "nbformat_minor": 2 329 | } 330 | -------------------------------------------------------------------------------- /Basics Of Algebra by Hiren/01-02-Linear Equations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Linear Equations\n", 8 | "The equations in the previous lab included one variable, for which you solved the equation to find its value. Now let's look at equations with multiple variables. For reasons that will become apparent, equations with two variables are known as linear equations.\n", 9 | "\n", 10 | "## Solving a Linear Equation\n", 11 | "Consider the following equation:\n", 12 | "\n", 13 | "\\begin{equation}2y + 3 = 3x - 1 \\end{equation}\n", 14 | "\n", 15 | "This equation includes two different variables, **x** and **y**. These variables depend on one another; the value of x is determined in part by the value of y and vice-versa; so we can't solve the equation and find absolute values for both x and y. However, we *can* solve the equation for one of the variables and obtain a result that describes a relative relationship between the variables.\n", 16 | "\n", 17 | "For example, let's solve this equation for y. First, we'll get rid of the constant on the right by adding 1 to both sides:\n", 18 | "\n", 19 | "\\begin{equation}2y + 4 = 3x \\end{equation}\n", 20 | "\n", 21 | "Then we'll use the same technique to move the constant on the left to the right to isolate the y term by subtracting 4 from both sides:\n", 22 | "\n", 23 | "\\begin{equation}2y = 3x - 4 \\end{equation}\n", 24 | "\n", 25 | "Now we can deal with the coefficient for y by dividing both sides by 2:\n", 26 | "\n", 27 | "\\begin{equation}y = \\frac{3x - 4}{2} \\end{equation}\n", 28 | "\n", 29 | "Our equation is now solved. We've isolated **y** and defined it as 3x-4/2\n", 30 | "\n", 31 | "While we can't express **y** as a particular value, we can calculate it for any value of **x**. For example, if **x** has a value of 6, then **y** can be calculated as:\n", 32 | "\n", 33 | "\\begin{equation}y = \\frac{3\\cdot6 - 4}{2} \\end{equation}\n", 34 | "\n", 35 | "This gives the result 14/2 which can be simplified to 7.\n", 36 | "\n", 37 | "You can view the values of **y** for a range of **x** values by applying the equation to them using the following Python code:" 38 | ] 39 | }, 40 | { 41 | "cell_type": "code", 42 | "execution_count": null, 43 | "metadata": {}, 44 | "outputs": [], 45 | "source": [ 46 | "import pandas as pd\n", 47 | "\n", 48 | "# Create a dataframe with an x column containing values from -10 to 10\n", 49 | "df = pd.DataFrame ({'x': range(-10, 11)})\n", 50 | "\n", 51 | "# Add a y column by applying the solved equation to x\n", 52 | "df['y'] = (3*df['x'] - 4) / 2\n", 53 | "\n", 54 | "#Display the dataframe\n", 55 | "df" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "We can also plot these values to visualize the relationship between x and y as a line. For this reason, equations that describe a relative relationship between two variables are known as *linear equations*:" 63 | ] 64 | }, 65 | { 66 | "cell_type": "code", 67 | "execution_count": null, 68 | "metadata": {}, 69 | "outputs": [], 70 | "source": [ 71 | "%matplotlib inline\n", 72 | "from matplotlib import pyplot as plt\n", 73 | "\n", 74 | "plt.plot(df.x, df.y, color=\"grey\", marker = \"o\")\n", 75 | "plt.xlabel('x')\n", 76 | "plt.ylabel('y')\n", 77 | "plt.grid()\n", 78 | "plt.show()" 79 | ] 80 | }, 81 | { 82 | "cell_type": "markdown", 83 | "metadata": {}, 84 | "source": [ 85 | "In a linear equation, a valid solution is described by an ordered pair of x and y values. For example, valid solutions to the linear equation above include:\n", 86 | "- (-10, -17)\n", 87 | "- (0, -2)\n", 88 | "- (9, 11.5)\n", 89 | "\n", 90 | "The cool thing about linear equations is that we can plot the points for some specific ordered pair solutions to create the line, and then interpolate the x value for any y value (or vice-versa) along the line." 91 | ] 92 | }, 93 | { 94 | "cell_type": "markdown", 95 | "metadata": {}, 96 | "source": [ 97 | "## Intercepts\n", 98 | "When we use a linear equation to plot a line, we can easily see where the line intersects the X and Y axes of the plot. These points are known as *intercepts*. The *x-intercept* is where the line intersects the X (horizontal) axis, and the *y-intercept* is where the line intersects the Y (horizontal) axis.\n", 99 | "\n", 100 | "Let's take a look at the line from our linear equation with the X and Y axis shown through the origin (0,0)." 101 | ] 102 | }, 103 | { 104 | "cell_type": "code", 105 | "execution_count": null, 106 | "metadata": {}, 107 | "outputs": [], 108 | "source": [ 109 | "plt.plot(df.x, df.y, color=\"grey\")\n", 110 | "plt.xlabel('x')\n", 111 | "plt.ylabel('y')\n", 112 | "plt.grid()\n", 113 | "\n", 114 | "## add axis lines for 0,0\n", 115 | "plt.axhline()\n", 116 | "plt.axvline()\n", 117 | "plt.show()" 118 | ] 119 | }, 120 | { 121 | "cell_type": "markdown", 122 | "metadata": {}, 123 | "source": [ 124 | "The x-intercept is the point where the line crosses the X axis, and at this point, the **y** value is always 0. Similarly, the y-intercept is where the line crosses the Y axis, at which point the **x** value is 0. So to find the intercepts, we need to solve the equation for **x** when **y** is 0.\n", 125 | "\n", 126 | "For the x-intercept, our equation looks like this:\n", 127 | "\n", 128 | "\\begin{equation}0 = \\frac{3x - 4}{2} \\end{equation}\n", 129 | "\n", 130 | "Which can be reversed to make it look more familar with the x expression on the left:\n", 131 | "\n", 132 | "\\begin{equation}\\frac{3x - 4}{2} = 0 \\end{equation}\n", 133 | "\n", 134 | "We can multiply both sides by 2 to get rid of the fraction:\n", 135 | "\n", 136 | "\\begin{equation}3x - 4 = 0 \\end{equation}\n", 137 | "\n", 138 | "Then we can add 4 to both sides to get rid of the constant on the left:\n", 139 | "\n", 140 | "\\begin{equation}3x = 4 \\end{equation}\n", 141 | "\n", 142 | "And finally we can divide both sides by 3 to get the value for x:\n", 143 | "\n", 144 | "\\begin{equation}x = \\frac{4}{3} \\end{equation}\n", 145 | "\n", 146 | "Which simplifies to:\n", 147 | "\n", 148 | "\\begin{equation}x = 1\\frac{1}{3} \\end{equation}\n", 149 | "\n", 150 | "So the x-intercept is 11/3 (approximately 1.333).\n", 151 | "\n", 152 | "To get the y-intercept, we solve the equation for y when x is 0:\n", 153 | "\n", 154 | "\\begin{equation}y = \\frac{3\\cdot0 - 4}{2} \\end{equation}\n", 155 | "\n", 156 | "Since 3 x 0 is 0, this can be simplified to:\n", 157 | "\n", 158 | "\\begin{equation}y = \\frac{-4}{2} \\end{equation}\n", 159 | "\n", 160 | "-4 divided by 2 is -2, so:\n", 161 | "\n", 162 | "\\begin{equation}y = -2 \\end{equation}\n", 163 | "\n", 164 | "This gives us our y-intercept, so we can plot both intercepts on the graph:" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": null, 170 | "metadata": {}, 171 | "outputs": [], 172 | "source": [ 173 | "plt.plot(df.x, df.y, color=\"grey\")\n", 174 | "plt.xlabel('x')\n", 175 | "plt.ylabel('y')\n", 176 | "plt.grid()\n", 177 | "\n", 178 | "## add axis lines for 0,0\n", 179 | "plt.axhline()\n", 180 | "plt.axvline()\n", 181 | "plt.annotate('x-intercept',(1.333, 0))\n", 182 | "plt.annotate('y-intercept',(0,-2))\n", 183 | "plt.show()" 184 | ] 185 | }, 186 | { 187 | "cell_type": "markdown", 188 | "metadata": {}, 189 | "source": [ 190 | "The ability to calculate the intercepts for a linear equation is useful, because you can calculate only these two points and then draw a straight line through them to create the entire line for the equation." 191 | ] 192 | }, 193 | { 194 | "cell_type": "markdown", 195 | "metadata": {}, 196 | "source": [ 197 | "## Slope\n", 198 | "It's clear from the graph that the line from our linear equation describes a slope in which values increase as we travel up and to the right along the line. It can be useful to quantify the slope in terms of how much **x** increases (or decreases) for a given change in **y**. In the notation for this, we use the greek letter Δ (*delta*) to represent change:\n", 199 | "\n", 200 | "\\begin{equation}slope = \\frac{\\Delta{y}}{\\Delta{x}} \\end{equation}\n", 201 | "\n", 202 | "Sometimes slope is represented by the variable ***m***, and the equation is written as:\n", 203 | "\n", 204 | "\\begin{equation}m = \\frac{y_{2} - y_{1}}{x_{2} - x_{1}} \\end{equation}\n", 205 | "\n", 206 | "Although this form of the equation is a little more verbose, it gives us a clue as to how we calculate slope. What we need is any two ordered pairs of x,y values for the line - for example, we know that our line passes through the following two points:\n", 207 | "- (0,-2)\n", 208 | "- (6,7)\n", 209 | "\n", 210 | "We can take the x and y values from the first pair, and label them x1 and y1; and then take the x and y values from the second point and label them x2 and y2. Then we can plug those into our slope equation:\n", 211 | "\n", 212 | "\\begin{equation}m = \\frac{7 - -2}{6 - 0} \\end{equation}\n", 213 | "\n", 214 | "This is the same as:\n", 215 | "\n", 216 | "\\begin{equation}m = \\frac{7 + 2}{6 - 0} \\end{equation}\n", 217 | "\n", 218 | "That gives us the result 9/6 which is 11/2 or 1.5 .\n", 219 | "\n", 220 | "So what does that actually mean? Well, it tells us that for every change of **1** in x, **y** changes by 11/2 or 1.5. So if we start from any point on the line and move one unit to the right (along the X axis), we'll need to move 1.5 units up (along the Y axis) to get back to the line.\n", 221 | "\n", 222 | "You can plot the slope onto the original line with the following Python code to verify it fits:" 223 | ] 224 | }, 225 | { 226 | "cell_type": "code", 227 | "execution_count": null, 228 | "metadata": {}, 229 | "outputs": [], 230 | "source": [ 231 | "plt.plot(df.x, df.y, color=\"grey\")\n", 232 | "plt.xlabel('x')\n", 233 | "plt.ylabel('y')\n", 234 | "plt.grid()\n", 235 | "plt.axhline()\n", 236 | "plt.axvline()\n", 237 | "\n", 238 | "# set the slope\n", 239 | "m = 1.5\n", 240 | "\n", 241 | "# get the y-intercept\n", 242 | "yInt = -2\n", 243 | "\n", 244 | "# plot the slope from the y-intercept for 1x\n", 245 | "mx = [0, 1]\n", 246 | "my = [yInt, yInt + m]\n", 247 | "plt.plot(mx,my, color='red', lw=5)\n", 248 | "\n", 249 | "plt.show()" 250 | ] 251 | }, 252 | { 253 | "cell_type": "markdown", 254 | "metadata": {}, 255 | "source": [ 256 | "### Slope-Intercept Form\n", 257 | "One of the great things about algebraic expressions is that you can write the same equation in multiple ways, or *forms*. The *slope-intercept form* is a specific way of writing a 2-variable linear equation so that the equation definition includes the slope and y-intercept. The generalised slope-intercept form looks like this:\n", 258 | "\n", 259 | "\\begin{equation}y = mx + b \\end{equation}\n", 260 | "\n", 261 | "In this notation, ***m*** is the slope and ***b*** is the y-intercept.\n", 262 | "\n", 263 | "For example, let's look at the solved linear equation we've been working with so far in this section:\n", 264 | "\n", 265 | "\\begin{equation}y = \\frac{3x - 4}{2} \\end{equation}\n", 266 | "\n", 267 | "Now that we know the slope and y-intercept for the line that this equation defines, we can rewrite the equation as:\n", 268 | "\n", 269 | "\\begin{equation}y = 1\\frac{1}{2}x + -2 \\end{equation}\n", 270 | "\n", 271 | "You can see intuitively that this is true. In our original form of the equation, to find y we multiply x by three, subtract 4, and divide by two - in other words, x is half of 3x - 4; which is 1.5x - 2. So these equations are equivalent, but the slope-intercept form has the advantages of being simpler, and including two key pieces of information we need to plot the line represented by the equation. We know the y-intecept that the line passes through (0, -2), and we know the slope of the line (for every x, we add 1.5 to y.\n", 272 | "\n", 273 | "Let's recreate our set of test x and y values using the slope-intercept form of the equation, and plot them to prove that this describes the same line:" 274 | ] 275 | }, 276 | { 277 | "cell_type": "code", 278 | "execution_count": null, 279 | "metadata": {}, 280 | "outputs": [], 281 | "source": [ 282 | "%matplotlib inline\n", 283 | "\n", 284 | "import pandas as pd\n", 285 | "from matplotlib import pyplot as plt\n", 286 | "\n", 287 | "# Create a dataframe with an x column containing values from -10 to 10\n", 288 | "df = pd.DataFrame ({'x': range(-10, 11)})\n", 289 | "\n", 290 | "# Define slope and y-intercept\n", 291 | "m = 1.5\n", 292 | "yInt = -2\n", 293 | "\n", 294 | "# Add a y column by applying the slope-intercept equation to x\n", 295 | "df['y'] = m*df['x'] + yInt\n", 296 | "\n", 297 | "# Plot the line\n", 298 | "from matplotlib import pyplot as plt\n", 299 | "\n", 300 | "plt.plot(df.x, df.y, color=\"grey\")\n", 301 | "plt.xlabel('x')\n", 302 | "plt.ylabel('y')\n", 303 | "plt.grid()\n", 304 | "plt.axhline()\n", 305 | "plt.axvline()\n", 306 | "\n", 307 | "# label the y-intercept\n", 308 | "plt.annotate('y-intercept',(0,yInt))\n", 309 | "\n", 310 | "# plot the slope from the y-intercept for 1x\n", 311 | "mx = [0, 1]\n", 312 | "my = [yInt, yInt + m]\n", 313 | "plt.plot(mx,my, color='red', lw=5)\n", 314 | "\n", 315 | "plt.show()" 316 | ] 317 | } 318 | ], 319 | "metadata": { 320 | "kernelspec": { 321 | "display_name": "Python 3.6", 322 | "language": "python", 323 | "name": "python36" 324 | }, 325 | "language_info": { 326 | "codemirror_mode": { 327 | "name": "ipython", 328 | "version": 3 329 | }, 330 | "file_extension": ".py", 331 | "mimetype": "text/x-python", 332 | "name": "python", 333 | "nbconvert_exporter": "python", 334 | "pygments_lexer": "ipython3", 335 | "version": "3.6.3" 336 | } 337 | }, 338 | "nbformat": 4, 339 | "nbformat_minor": 2 340 | } 341 | -------------------------------------------------------------------------------- /Basics Of Algebra by Hiren/01-03-Systems of Equations.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Systems of Equations\n", 8 | "Imagine you are at a casino, and you have a mixture of £10 and £25 chips. You know that you have a total of 16 chips, and you also know that the total value of chips you have is £250. Is this enough information to determine how many of each denomination of chip you have?\n", 9 | "\n", 10 | "Well, we can express each of the facts that we have as an equation. The first equation deals with the total number of chips - we know that this is 16, and that it is the number of £10 chips (which we'll call ***x*** ) added to the number of £25 chips (***y***).\n", 11 | "\n", 12 | "The second equation deals with the total value of the chips (£250), and we know that this is made up of ***x*** chips worth £10 and ***y*** chips worth £25.\n", 13 | "\n", 14 | "Here are the equations\n", 15 | "\n", 16 | "\\begin{equation}x + y = 16 \\end{equation}\n", 17 | "\\begin{equation}10x + 25y = 250 \\end{equation}\n", 18 | "\n", 19 | "Taken together, these equations form a *system of equations* that will enable us to determine how many of each chip denomination we have.\n", 20 | "\n", 21 | "## Graphing Lines to Find the Intersection Point\n", 22 | "One approach is to determine all possible values for x and y in each equation and plot them.\n", 23 | "\n", 24 | "A collection of 16 chips could be made up of 16 £10 chips and no £25 chips, no £10 chips and 16 £25 chips, or any combination between these.\n", 25 | "\n", 26 | "Similarly, a total of £250 could be made up of 25 £10 chips and no £25 chips, no £10 chips and 10 £25 chips, or a combination in between.\n", 27 | "\n", 28 | "Let's plot each of these ranges of values as lines on a graph:" 29 | ] 30 | }, 31 | { 32 | "cell_type": "code", 33 | "execution_count": null, 34 | "metadata": {}, 35 | "outputs": [], 36 | "source": [ 37 | "%matplotlib inline\n", 38 | "from matplotlib import pyplot as plt\n", 39 | "\n", 40 | "# Get the extremes for number of chips\n", 41 | "chipsAll10s = [16, 0]\n", 42 | "chipsAll25s = [0, 16]\n", 43 | "\n", 44 | "# Get the extremes for values\n", 45 | "valueAll10s = [25,0]\n", 46 | "valueAll25s = [0,10]\n", 47 | "\n", 48 | "# Plot the lines\n", 49 | "plt.plot(chipsAll10s,chipsAll25s, color='blue')\n", 50 | "plt.plot(valueAll10s, valueAll25s, color=\"orange\")\n", 51 | "plt.xlabel('x (£10 chips)')\n", 52 | "plt.ylabel('y (£25 chips)')\n", 53 | "plt.grid()\n", 54 | "\n", 55 | "plt.show()" 56 | ] 57 | }, 58 | { 59 | "cell_type": "markdown", 60 | "metadata": {}, 61 | "source": [ 62 | "Looking at the graph, you can see that there is only a single combination of £10 and £25 chips that is on both the line for all possible combinations of 16 chips and the line for all possible combinations of £250. The point where the line intersects is (10, 6); or put another way, there are ten £10 chips and six £25 chips.\n", 63 | "\n", 64 | "### Solving a System of Equations with Elimination\n", 65 | "You can also solve a system of equations mathematically. Let's take a look at our two equations:\n", 66 | "\n", 67 | "\\begin{equation}x + y = 16 \\end{equation}\n", 68 | "\\begin{equation}10x + 25y = 250 \\end{equation}\n", 69 | "\n", 70 | "We can combine these equations to eliminate one of the variable terms and solve the resulting equation to find the value of one of the variables. Let's start by combining the equations and eliminating the x term.\n", 71 | "\n", 72 | "We can combine the equations by adding them together, but first, we need to manipulate one of the equations so that adding them will eliminate the x term. The first equation includes the term ***x***, and the second includes the term ***10x***, so if we multiply the first equation by -10, the two x terms will cancel each other out. So here are the equations with the first one multiplied by -10:\n", 73 | "\n", 74 | "\\begin{equation}-10(x + y) = -10(16) \\end{equation}\n", 75 | "\\begin{equation}10x + 25y = 250 \\end{equation}\n", 76 | "\n", 77 | "After we apply the multiplication to all of the terms in the first equation, the system of equations look like this:\n", 78 | "\n", 79 | "\\begin{equation}-10x + -10y = -160 \\end{equation}\n", 80 | "\\begin{equation}10x + 25y = 250 \\end{equation}\n", 81 | "\n", 82 | "Now we can combine the equations by adding them. The ***-10x*** and ***10x*** cancel one another, leaving us with a single equation like this:\n", 83 | "\n", 84 | "\\begin{equation}15y = 90 \\end{equation}\n", 85 | "\n", 86 | "We can isolate ***y*** by dividing both sides by 15:\n", 87 | "\n", 88 | "\\begin{equation}y = \\frac{90}{15} \\end{equation}\n", 89 | "\n", 90 | "So now we have a value for ***y***:\n", 91 | "\n", 92 | "\\begin{equation}y = 6 \\end{equation}\n", 93 | "\n", 94 | "So how does that help us? Well, now we have a value for ***y*** that satisfies both equations. We can simply use it in either of the equations to determine the value of ***x***. Let's use the first one:\n", 95 | "\n", 96 | "\\begin{equation}x + 6 = 16 \\end{equation}\n", 97 | "\n", 98 | "When we work through this equation, we get a value for ***x***:\n", 99 | "\n", 100 | "\\begin{equation}x = 10 \\end{equation}\n", 101 | "\n", 102 | "So now we've calculated values for ***x*** and ***y***, and we find, just as we did with the graphical intersection method, that there are ten £10 chips and six £25 chips.\n", 103 | "\n", 104 | "You can run the following Python code to verify that the equations are both true with an ***x*** value of 10 and a ***y*** value of 6." 105 | ] 106 | }, 107 | { 108 | "cell_type": "code", 109 | "execution_count": null, 110 | "metadata": {}, 111 | "outputs": [], 112 | "source": [ 113 | "x = 10\n", 114 | "y = 6\n", 115 | "print ((x + y == 16) & ((10*x) + (25*y) == 250))" 116 | ] 117 | } 118 | ], 119 | "metadata": { 120 | "kernelspec": { 121 | "display_name": "Python 3.6", 122 | "language": "python", 123 | "name": "python36" 124 | }, 125 | "language_info": { 126 | "codemirror_mode": { 127 | "name": "ipython", 128 | "version": 3 129 | }, 130 | "file_extension": ".py", 131 | "mimetype": "text/x-python", 132 | "name": "python", 133 | "nbconvert_exporter": "python", 134 | "pygments_lexer": "ipython3", 135 | "version": "3.6.3" 136 | } 137 | }, 138 | "nbformat": 4, 139 | "nbformat_minor": 2 140 | } 141 | -------------------------------------------------------------------------------- /Basics Of Algebra by Hiren/01-04-Exponentials Radicals and Logarithms.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Exponentials, Radicals, and Logs\n", 8 | "Up to this point, all of our equations have included standard arithmetic operations, such as division, multiplication, addition, and subtraction. Many real-world calculations involve exponential values in which numbers are raised by a specific power.\n", 9 | "\n", 10 | "## Exponentials\n", 11 | "A simple case of of using an exponential is squaring a number; in other words, multipying a number by itself. For example, 2 squared is 2 times 2, which is 4. This is written like this:\n", 12 | "\n", 13 | "\\begin{equation}2^{2} = 2 \\cdot 2 = 4\\end{equation}\n", 14 | "\n", 15 | "Similarly, 2 cubed is 2 times 2 times 2 (which is of course 8):\n", 16 | "\n", 17 | "\\begin{equation}2^{3} = 2 \\cdot 2 \\cdot 2 = 8\\end{equation}\n", 18 | "\n", 19 | "In Python, you use the ****** operator, like this example in which **x** is assigned the value of 5 raised to the power of 3 (in other words, 5 x 5 x 5, or 5-cubed):" 20 | ] 21 | }, 22 | { 23 | "cell_type": "code", 24 | "execution_count": null, 25 | "metadata": {}, 26 | "outputs": [], 27 | "source": [ 28 | "x = 5**3\n", 29 | "print(x)" 30 | ] 31 | }, 32 | { 33 | "cell_type": "markdown", 34 | "metadata": {}, 35 | "source": [ 36 | "Multiplying a number by itself twice or three times to calculate the square or cube of a number is a common operation, but you can raise a number by any exponential power. For example, the following notation shows 4 to the power of 7 (or 4 x 4 x 4 x 4 x 4 x 4 x 4), which has the value:\n", 37 | "\n", 38 | "\\begin{equation}4^{7} = 16384 \\end{equation}\n", 39 | "\n", 40 | "In mathematical terminology, **4** is the *base*, and **7** is the *power* or *exponent* in this expression.\n", 41 | "\n", 42 | "## Radicals (Roots)\n", 43 | "While it's common to need to calculate the solution for a given base and exponential, sometimes you'll need to calculate one or other of the elements themselves. For example, consider the following expression:\n", 44 | "\n", 45 | "\\begin{equation}?^{2} = 9 \\end{equation}\n", 46 | "\n", 47 | "This expression is asking, given a number (9) and an exponent (2), what's the base? In other words, which number multipled by itself results in 9? This type of operation is referred to as calculating the *root*, and in this particular case it's the *square root* (the base for a specified number given the exponential **2**). In this case, the answer is 3, because 3 x 3 = 9. We show this with a **√** symbol, like this:\n", 48 | "\n", 49 | "\\begin{equation}\\sqrt{9} = 3 \\end{equation}\n", 50 | "\n", 51 | "Other common roots include the *cube root* (the base for a specified number given the exponential **3**). For example, the cube root of 64 is 4 (because 4 x 4 x 4 = 64). To show that this is the cube root, we include the exponent **3** in the **√** symbol, like this:\n", 52 | "\n", 53 | "\\begin{equation}\\sqrt[3]{64} = 4 \\end{equation}\n", 54 | "\n", 55 | "We can calculate any root of any non-negative number, indicating the exponent in the **√** symbol.\n", 56 | "\n", 57 | "The **math** package in Python includes a **sqrt** function that calculates the square root of a number. To calculate other roots, you need to reverse the exponential calculation by raising the given number to the power of 1 divided by the given exponent:" 58 | ] 59 | }, 60 | { 61 | "cell_type": "code", 62 | "execution_count": null, 63 | "metadata": {}, 64 | "outputs": [], 65 | "source": [ 66 | "import math\n", 67 | "\n", 68 | "# Calculate square root of 25\n", 69 | "x = math.sqrt(25)\n", 70 | "print (x)\n", 71 | "\n", 72 | "# Calculate cube root of 64\n", 73 | "cr = round(64 ** (1. / 3))\n", 74 | "print(cr)" 75 | ] 76 | }, 77 | { 78 | "cell_type": "markdown", 79 | "metadata": {}, 80 | "source": [ 81 | "The code used in Python to calculate roots other than the square root reveals something about the relationship between roots and exponentials. The exponential root of a number is the same as that number raised to the power of 1 divided by the exponential. For example, consider the following statement:\n", 82 | "\n", 83 | "\\begin{equation} 8^{\\frac{1}{3}} = \\sqrt[3]{8} = 2 \\end{equation}\n", 84 | "\n", 85 | "Note that a number to the power of 1/3 is the same as the cube root of that number.\n", 86 | "\n", 87 | "Based on the same arithmetic, a number to the power of 1/2 is the same as the square root of the number:\n", 88 | "\n", 89 | "\\begin{equation} 9^{\\frac{1}{2}} = \\sqrt{9} = 3 \\end{equation}\n", 90 | "\n", 91 | "You can see this for yourself with the following Python code:" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": {}, 98 | "outputs": [], 99 | "source": [ 100 | "import math\n", 101 | "\n", 102 | "print (9**0.5)\n", 103 | "print (math.sqrt(9))" 104 | ] 105 | }, 106 | { 107 | "cell_type": "markdown", 108 | "metadata": {}, 109 | "source": [ 110 | "## Logarithms\n", 111 | "Another consideration for exponential values is the requirement occassionally to determine the exponent for a given number and base. In other words, how many times do I need to multiply a base number by itself to get the given result. This kind of calculation is known as the *logarithm*.\n", 112 | "\n", 113 | "For example, consider the following expression:\n", 114 | "\n", 115 | "\\begin{equation}4^{?} = 16 \\end{equation}\n", 116 | "\n", 117 | "In other words, to what power must you raise 4 to produce the result 16?\n", 118 | "\n", 119 | "The answer to this is 2, because 4 x 4 (or 4 to the power of 2) = 16. The notation looks like this:\n", 120 | "\n", 121 | "\\begin{equation}log_{4}(16) = 2 \\end{equation}\n", 122 | "\n", 123 | "In Python, you can calculate the logarithm of a number using the **log** function in the **math** package, indicating the number and the base:" 124 | ] 125 | }, 126 | { 127 | "cell_type": "code", 128 | "execution_count": null, 129 | "metadata": {}, 130 | "outputs": [], 131 | "source": [ 132 | "import math\n", 133 | "\n", 134 | "x = math.log(16, 4)\n", 135 | "print(x)" 136 | ] 137 | }, 138 | { 139 | "cell_type": "markdown", 140 | "metadata": {}, 141 | "source": [ 142 | "The final thing you need to know about exponentials and logarithms is that there are some special logarithms:\n", 143 | "\n", 144 | "The *common* logarithm of a number is its exponential for the base **10**. You'll occassionally see this written using the usual *log* notation with the base omitted:\n", 145 | "\n", 146 | "\\begin{equation}log(1000) = 3 \\end{equation}\n", 147 | "\n", 148 | "Another special logarithm is something called the *natural log*, which is a exponential of a number for base ***e***, where ***e*** is a constant with the approximate value 2.718. This number occurs naturally in a lot of scenarios, and you'll see it often as you work with data in many analytical contexts. For the time being, just be aware that the natural log is sometimes written as ***ln***:\n", 149 | "\n", 150 | "\\begin{equation}log_{e}(64) = ln(64) = 4.1589 \\end{equation}\n", 151 | "\n", 152 | "The **math.log** function in Python returns the natural log (base ***e***) when no base is specified. Note that this can be confusing, as the mathematical notation *log* with no base usually refers to the common log (base **10**). To return the common log in Python, use the **math.log10** function:" 153 | ] 154 | }, 155 | { 156 | "cell_type": "code", 157 | "execution_count": null, 158 | "metadata": {}, 159 | "outputs": [], 160 | "source": [ 161 | "import math\n", 162 | "\n", 163 | "# Natural log of 29\n", 164 | "print (math.log(29))\n", 165 | "\n", 166 | "# Common log of 100\n", 167 | "print(math.log10(100))" 168 | ] 169 | }, 170 | { 171 | "cell_type": "markdown", 172 | "metadata": {}, 173 | "source": [ 174 | "## Solving Equations with Exponentials\n", 175 | "OK, so now that you have a basic understanding of exponentials, roots, and logarithms; let's take a look at some equations that involve exponential calculations.\n", 176 | "\n", 177 | "Let's start with what might at first glance look like a complicated example, but don't worry - we'll solve it step-by-step and learn a few tricks along the way:\n", 178 | "\n", 179 | "\\begin{equation}2y = 2x^{4} ( \\frac{x^{2} + 2x^{2}}{x^{3}} ) \\end{equation}\n", 180 | "\n", 181 | "First, let's deal with the fraction on the right side. The numerator of this fraction is x2 + 2x2 - so we're adding two exponential terms. When the terms you're adding (or subtracting) have the same exponential, you can simply add (or subtract) the coefficients. In this case, x2 is the same as 1x2, which when added to 2x2 gives us the result 3x2, so our equation now looks like this: \n", 182 | "\n", 183 | "\\begin{equation}2y = 2x^{4} ( \\frac{3x^{2}}{x^{3}} ) \\end{equation}\n", 184 | "\n", 185 | "Now that we've condolidated the numerator, let's simplify the entire fraction by dividing the numerator by the denominator. When you divide exponential terms with the same variable, you simply divide the coefficients as you usually would and subtract the exponential of the denominator from the exponential of the numerator. In this case, we're dividing 3x2 by 1x3: The coefficient 3 divided by 1 is 3, and the exponential 2 minus 3 is -1, so the result is 3x-1, making our equation:\n", 186 | "\n", 187 | "\\begin{equation}2y = 2x^{4} ( 3x^{-1} ) \\end{equation}\n", 188 | "\n", 189 | "So now we've got rid of the fraction on the right side, let's deal with the remaining multiplication. We need to multiply 3x-1 by 2x4. Multiplication, is the opposite of division, so this time we'll multipy the coefficients and add the exponentials: 3 multiplied by 2 is 6, and -1 + 4 is 3, so the result is 6x3:\n", 190 | "\n", 191 | "\\begin{equation}2y = 6x^{3} \\end{equation}\n", 192 | "\n", 193 | "We're in the home stretch now, we just need to isolate y on the left side, and we can do that by dividing both sides by 2. Note that we're not dividing by an exponential, we simply need to divide the whole 6x3 term by two; and half of 6 times x3 is just 3 times x3:\n", 194 | "\n", 195 | "\\begin{equation}y = 3x^{3} \\end{equation}\n", 196 | "\n", 197 | "Now we have a solution that defines y in terms of x. We can use Python to plot the line created by this equation for a set of arbitrary *x* and *y* values:" 198 | ] 199 | }, 200 | { 201 | "cell_type": "code", 202 | "execution_count": null, 203 | "metadata": {}, 204 | "outputs": [], 205 | "source": [ 206 | "import pandas as pd\n", 207 | "\n", 208 | "# Create a dataframe with an x column containing values from -10 to 10\n", 209 | "df = pd.DataFrame ({'x': range(-10, 11)})\n", 210 | "\n", 211 | "# Add a y column by applying the slope-intercept equation to x\n", 212 | "df['y'] = 3*df['x']**3\n", 213 | "\n", 214 | "#Display the dataframe\n", 215 | "print(df)\n", 216 | "\n", 217 | "# Plot the line\n", 218 | "%matplotlib inline\n", 219 | "from matplotlib import pyplot as plt\n", 220 | "\n", 221 | "plt.plot(df.x, df.y, color=\"magenta\")\n", 222 | "plt.xlabel('x')\n", 223 | "plt.ylabel('y')\n", 224 | "plt.grid()\n", 225 | "plt.axhline()\n", 226 | "plt.axvline()\n", 227 | "plt.show()" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "Note that the line is curved. This is symptomatic of an exponential equation: as values on one axis increase or decrease, the values on the other axis scale *exponentially* rather than *linearly*.\n", 235 | "\n", 236 | "Let's look at an example in which x is the exponential, not the base:\n", 237 | "\n", 238 | "\\begin{equation}y = 2^{x} \\end{equation}\n", 239 | "\n", 240 | "We can still plot this as a line:" 241 | ] 242 | }, 243 | { 244 | "cell_type": "code", 245 | "execution_count": null, 246 | "metadata": {}, 247 | "outputs": [], 248 | "source": [ 249 | "import pandas as pd\n", 250 | "\n", 251 | "# Create a dataframe with an x column containing values from -10 to 10\n", 252 | "df = pd.DataFrame ({'x': range(-10, 11)})\n", 253 | "\n", 254 | "# Add a y column by applying the slope-intercept equation to x\n", 255 | "df['y'] = 2.0**df['x']\n", 256 | "\n", 257 | "#Display the dataframe\n", 258 | "print(df)\n", 259 | "\n", 260 | "# Plot the line\n", 261 | "%matplotlib inline\n", 262 | "from matplotlib import pyplot as plt\n", 263 | "\n", 264 | "plt.plot(df.x, df.y, color=\"magenta\")\n", 265 | "plt.xlabel('x')\n", 266 | "plt.ylabel('y')\n", 267 | "plt.grid()\n", 268 | "plt.axhline()\n", 269 | "plt.axvline()\n", 270 | "plt.show()" 271 | ] 272 | }, 273 | { 274 | "cell_type": "markdown", 275 | "metadata": {}, 276 | "source": [ 277 | "Note that when the exponential is a negative number, Python reports the result as 0. Actually, it's a very small fractional number, but because the base is positive the exponential number will always positive. Also, note the rate at which y increases as x increases - exponential growth can be be pretty dramatic.\n", 278 | "\n", 279 | "So what's the practical application of this?\n", 280 | "\n", 281 | "Well, let's suppose you deposit $100 in a bank account that earns 5% interest per year. What would the balance of the account be in twenty years, assuming you don't deposit or withdraw any additional funds?\n", 282 | "\n", 283 | "To work this out, you could calculate the balance for each year:\n", 284 | "\n", 285 | "After the first year, the balance will be the initial deposit ($100) plus 5% of that amount:\n", 286 | "\n", 287 | "\\begin{equation}y1 = 100 + (100 \\cdot 0.05) \\end{equation}\n", 288 | "\n", 289 | "Another way of saying this is:\n", 290 | "\n", 291 | "\\begin{equation}y1 = 100 \\cdot 1.05 \\end{equation}\n", 292 | "\n", 293 | "At the end of year two, the balance will be the year one balance plus 5%:\n", 294 | "\n", 295 | "\\begin{equation}y2 = 100 \\cdot 1.05 \\cdot 1.05 \\end{equation}\n", 296 | "\n", 297 | "Note that the interest for year two, is the interest for year one multiplied by itself - in other words, squared. So another way of saying this is:\n", 298 | "\n", 299 | "\\begin{equation}y2 = 100 \\cdot 1.05^{2} \\end{equation}\n", 300 | "\n", 301 | "It turns out, if we just use the year as the exponent, we can easily calculate the growth after twenty years like this:\n", 302 | "\n", 303 | "\\begin{equation}y20 = 100 \\cdot 1.05^{20} \\end{equation}\n", 304 | "\n", 305 | "Let's apply this logic in Python to see how the account balance would grow over twenty years:" 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": null, 311 | "metadata": {}, 312 | "outputs": [], 313 | "source": [ 314 | "import pandas as pd\n", 315 | "\n", 316 | "# Create a dataframe with 20 years\n", 317 | "df = pd.DataFrame ({'Year': range(1, 21)})\n", 318 | "\n", 319 | "# Calculate the balance for each year based on the exponential growth from interest\n", 320 | "df['Balance'] = 100 * (1.05**df['Year'])\n", 321 | "\n", 322 | "#Display the dataframe\n", 323 | "print(df)\n", 324 | "\n", 325 | "# Plot the line\n", 326 | "%matplotlib inline\n", 327 | "from matplotlib import pyplot as plt\n", 328 | "\n", 329 | "plt.plot(df.Year, df.Balance, color=\"green\")\n", 330 | "plt.xlabel('Year')\n", 331 | "plt.ylabel('Balance')\n", 332 | "plt.show()" 333 | ] 334 | } 335 | ], 336 | "metadata": { 337 | "kernelspec": { 338 | "display_name": "Python 3.6", 339 | "language": "python", 340 | "name": "python36" 341 | }, 342 | "language_info": { 343 | "codemirror_mode": { 344 | "name": "ipython", 345 | "version": 3 346 | }, 347 | "file_extension": ".py", 348 | "mimetype": "text/x-python", 349 | "name": "python", 350 | "nbconvert_exporter": "python", 351 | "pygments_lexer": "ipython3", 352 | "version": "3.6.3" 353 | } 354 | }, 355 | "nbformat": 4, 356 | "nbformat_minor": 2 357 | } 358 | -------------------------------------------------------------------------------- /Basics Of Algebra by Hiren/01-05-Polynomials.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Polynomials\n", 8 | "Some of the equations we've looked at so far include expressions that are actually *polynomials*; but what *is* a polynomial, and why should you care?\n", 9 | "\n", 10 | "A polynomial is an algebraic expression containing one or more *terms* that each meet some specific criteria. Specifically:\n", 11 | "- Each term can contain:\n", 12 | " - Numeric values that are coefficients or constants (for example 2, -5, 1/7)\n", 13 | " - Variables (for example, x, y)\n", 14 | " - Non-negative integer exponents (for example 2, 64)\n", 15 | "- The terms can be combined using arithmetic operations - but **not** division by a variable.\n", 16 | "\n", 17 | "For example, the following expression is a polynomial:\n", 18 | "\n", 19 | "\\begin{equation}12x^{3} + 2x - 16 \\end{equation}\n", 20 | "\n", 21 | "When identifying the terms in a polynomial, it's important to correctly interpret the arithmetic addition and subtraction operators as the sign for the term that follows. For example, the polynomial above contains the following three terms:\n", 22 | "- 12x3\n", 23 | "- 2x\n", 24 | "- -16\n", 25 | "\n", 26 | "The terms themselves include:\n", 27 | "- Two coefficients(12 and 2) and a constant (-16)\n", 28 | "- A variable (x)\n", 29 | "- An exponent (3)\n", 30 | "\n", 31 | "A polynomial that contains three terms is also known as a *trinomial*. Similarly, a polynomial with two terms is known as a *binomial* and a polynomial with only one term is known as a *monomial*.\n", 32 | "\n", 33 | "So why do we care? Well, polynomials have some useful properties that make them easy to work with. for example, if you multiply, add, or subtract a polynomial, the result is always another polynomial.\n", 34 | "\n", 35 | "## Standard Form for Polynomials\n", 36 | "Techbnically, you can write the terms of a polynomial in any order; but the *standard form* for a polynomial is to start with the highest *degree* first and constants last. The degree of a term is the highest order (exponent) in the term, and the highest order in a polynomial determines the degree of the polynomial itself.\n", 37 | "\n", 38 | "For example, consider the following expression:\n", 39 | "\\begin{equation}3x + 4xy^{2} - 3 + x^{3} \\end{equation}\n", 40 | "\n", 41 | "To express this as a polynomial in the standard form, we need to re-order the terms like this:\n", 42 | "\n", 43 | "\\begin{equation}x^{3} + 4xy^{2} + 3x - 3 \\end{equation}\n", 44 | "\n", 45 | "## Simplifying Polynomials\n", 46 | "We saw previously how you can simplify an equation by combining *like terms*. You can simplify polynomials in the same way.\n", 47 | "\n", 48 | "For example, look at the following polynomial:\n", 49 | "\n", 50 | "\\begin{equation}x^{3} + 2x^{3} - 3x - x + 8 - 3 \\end{equation}\n", 51 | "\n", 52 | "In this case, we can combine x3 and 2x3 by adding them to make 3x3. Then we can add -3x and -x (which is really just a shorthand way to say -1x) to get -4x, and then add 8 and -3 to get 5. Our simplified polynomial then looks like this:\n", 53 | "\n", 54 | "\\begin{equation}3x^{3} - 4x + 5 \\end{equation}\n", 55 | "\n", 56 | "We can use Python to compare the original and simplified polynomials to check them - using an arbitrary random value for ***x***:" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "collapsed": true 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "from random import randint\n", 68 | "x = randint(1,100)\n", 69 | "\n", 70 | "(x**3 + 2*x**3 - 3*x - x + 8 - 3) == (3*x**3 - 4*x + 5)" 71 | ] 72 | }, 73 | { 74 | "cell_type": "markdown", 75 | "metadata": {}, 76 | "source": [ 77 | "## Adding Polynomials\n", 78 | "When you add two polynomials, the result is a polynomial. Here's an example:\n", 79 | "\n", 80 | "\\begin{equation}(3x^{3} - 4x + 5) + (2x^{3} + 3x^{2} - 2x + 2) \\end{equation}\n", 81 | "\n", 82 | "because this is an addition operation, you can simply add all of the like terms from both polynomials. To make this clear, let's first put the like terms together:\n", 83 | "\n", 84 | "\\begin{equation}3x^{3} + 2x^{3} + 3x^{2} - 4x -2x + 5 + 2 \\end{equation}\n", 85 | "\n", 86 | "This simplifies to:\n", 87 | "\n", 88 | "\\begin{equation}5x^{3} + 3x^{2} - 6x + 7 \\end{equation}\n", 89 | "\n", 90 | "We can verify this with Python:" 91 | ] 92 | }, 93 | { 94 | "cell_type": "code", 95 | "execution_count": null, 96 | "metadata": { 97 | "collapsed": true 98 | }, 99 | "outputs": [], 100 | "source": [ 101 | "from random import randint\n", 102 | "x = randint(1,100)\n", 103 | "\n", 104 | "\n", 105 | "(3*x**3 - 4*x + 5) + (2*x**3 + 3*x**2 - 2*x + 2) == 5*x**3 + 3*x**2 - 6*x + 7" 106 | ] 107 | }, 108 | { 109 | "cell_type": "markdown", 110 | "metadata": {}, 111 | "source": [ 112 | "## Subtracting Polynomials\n", 113 | "Subtracting polynomials is similar to adding them but you need to take into account that one of the polynomials is a negative.\n", 114 | "\n", 115 | "Consider this expression:\n", 116 | "\n", 117 | "\\begin{equation}(2x^{2} - 4x + 5) - (x^{2} - 2x + 2) \\end{equation}\n", 118 | "\n", 119 | "The key to performing this calculation is to realize that the subtraction of the second polynomial is really an expression that adds -1(x2 - 2x + 2); so you can use the distributive property to multiply each of the terms in the polynomial by -1 (which in effect simply reverses the sign for each term). So our expression becomes:\n", 120 | "\n", 121 | "\\begin{equation}(2x^{2} - 4x + 5) + (-x^{2} + 2x - 2) \\end{equation}\n", 122 | "\n", 123 | "Which we can solve as an addition problem. First place the like terms together:\n", 124 | "\n", 125 | "\\begin{equation}2x^{2} + -x^{2} + -4x + 2x + 5 + -2 \\end{equation}\n", 126 | "\n", 127 | "Which simplifies to:\n", 128 | "\n", 129 | "\\begin{equation}x^{2} - 2x + 3 \\end{equation}\n", 130 | "\n", 131 | "Let's check that with Python:" 132 | ] 133 | }, 134 | { 135 | "cell_type": "code", 136 | "execution_count": null, 137 | "metadata": { 138 | "collapsed": true 139 | }, 140 | "outputs": [], 141 | "source": [ 142 | "from random import randint\n", 143 | "x = randint(1,100)\n", 144 | "\n", 145 | "(2*x**2 - 4*x + 5) - (x**2 - 2*x + 2) == x**2 - 2*x + 3" 146 | ] 147 | }, 148 | { 149 | "cell_type": "markdown", 150 | "metadata": {}, 151 | "source": [ 152 | "## Multiplying Polynomials\n", 153 | "To multiply two polynomials, you need to perform the following two steps:\n", 154 | "1. Multiply each term in the first polynomial by each term in the second polynomial.\n", 155 | "2. Add the results of the multiplication operations, combining like terms where possible.\n", 156 | "\n", 157 | "For example, consider this expression:\n", 158 | "\n", 159 | "\\begin{equation}(x^{4} + 2)(2x^{2} + 3x - 3) \\end{equation}\n", 160 | "\n", 161 | "Let's do the first step and multiply each term in the first polynomial by each term in the second polynomial. The first term in the first polynomial is x4, and the first term in the second polynomial is 2x2, so multiplying these gives us 2x6. Then we can multiply the first term in the first polynomial (x4) by the second term in the second polynomial (3x), which gives us 3x5, and so on until we've multipled all of the terms in the first polynomial by all of the terms in the second polynomial, which results in this:\n", 162 | "\n", 163 | "\\begin{equation}2x^{6} + 3x^{5} - 3x^{4} + 4x^{2} + 6x - 6 \\end{equation}\n", 164 | "\n", 165 | "We can verify a match between this result and the original expression this with the following Python code:" 166 | ] 167 | }, 168 | { 169 | "cell_type": "code", 170 | "execution_count": null, 171 | "metadata": { 172 | "collapsed": true 173 | }, 174 | "outputs": [], 175 | "source": [ 176 | "from random import randint\n", 177 | "x = randint(1,100)\n", 178 | "\n", 179 | "(x**4 + 2)*(2*x**2 + 3*x - 3) == 2*x**6 + 3*x**5 - 3*x**4 + 4*x**2 + 6*x - 6" 180 | ] 181 | }, 182 | { 183 | "cell_type": "markdown", 184 | "metadata": {}, 185 | "source": [ 186 | "## Dividing Polynomials\n", 187 | "When you need to divide one polynomial by another, there are two approaches you can take depending on the number of terms in the divisor (the expression you're dividing by).\n", 188 | "\n", 189 | "### Dividing Polynomials Using Simplification\n", 190 | "In the simplest case, division of a polynomial by a monomial, the operation is really just simplification of a fraction.\n", 191 | "\n", 192 | "For example, consider the following expression:\n", 193 | "\n", 194 | "\\begin{equation}(4x + 6x^{2}) \\div 2x \\end{equation}\n", 195 | "\n", 196 | "This can also be written as:\n", 197 | "\n", 198 | "\\begin{equation}\\frac{4x + 6x^{2}}{2x} \\end{equation}\n", 199 | "\n", 200 | "One approach to simplifying this fraction is to split it it into a separate fraction for each term in the dividend (the expression we're dividing), like this:\n", 201 | "\n", 202 | "\\begin{equation}\\frac{4x}{2x} + \\frac{6x^{2}}{2x}\\end{equation}\n", 203 | "\n", 204 | "Then we can simplify each fraction and add the results. For the first fraction, 2x goes into 4x twice, so the fraction simplifies to 2; and for the second, 6x2 is 2x mutliplied by 3x. So our answer is 2 + 3x:\n", 205 | "\n", 206 | "\\begin{equation}2 + 3x\\end{equation}\n", 207 | "\n", 208 | "Let's use Python to compare the original fraction with the simplified result for an arbitrary value of ***x***:" 209 | ] 210 | }, 211 | { 212 | "cell_type": "code", 213 | "execution_count": null, 214 | "metadata": { 215 | "collapsed": true 216 | }, 217 | "outputs": [], 218 | "source": [ 219 | "from random import randint\n", 220 | "x = randint(1,100)\n", 221 | "\n", 222 | "(4*x + 6*x**2) / (2*x) == 2 + 3*x" 223 | ] 224 | }, 225 | { 226 | "cell_type": "markdown", 227 | "metadata": {}, 228 | "source": [ 229 | "### Dividing Polynomials Using Long Division\n", 230 | "Things get a little more complicated for divisors with more than one term.\n", 231 | "\n", 232 | "Suppose we have the following expression:\n", 233 | "\\begin{equation}(x^{2} + 2x - 3) \\div (x - 2) \\end{equation}\n", 234 | "\n", 235 | "Another way of writing this is to use the long-division format, like this:\n", 236 | "\\begin{equation} x - 2 |\\overline{x^{2} + 2x - 3} \\end{equation}\n", 237 | "\n", 238 | "We begin long-division by dividing the highest order divisor into the highest order dividend - so in this case we divide x into x2. X goes into x2 x times, so we put an x on top and then multiply it through the divisor:\n", 239 | "\\begin{equation} \\;\\;\\;\\;x \\end{equation}\n", 240 | "\\begin{equation}x - 2 |\\overline{x^{2} + 2x - 3} \\end{equation}\n", 241 | "\\begin{equation} \\;x^{2} -2x \\end{equation}\n", 242 | "\n", 243 | "Now we'll subtract the remaining dividend, and then carry down the -3 that we haven't used to see what's left:\n", 244 | "\\begin{equation} \\;\\;\\;\\;x \\end{equation}\n", 245 | "\\begin{equation}x - 2 |\\overline{x^{2} + 2x - 3} \\end{equation}\n", 246 | "\\begin{equation}- (x^{2} -2x) \\end{equation}\n", 247 | "\\begin{equation}\\;\\;\\;\\;\\;\\overline{\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;4x -3} \\end{equation}\n", 248 | "\n", 249 | "OK, now we'll divide our highest order divisor into the highest order of the remaining dividend. In this case, x goes into 4x four times, so we'll add a 4 to the top line, multiply it through the divisor, and subtract the remaining dividend:\n", 250 | "\\begin{equation} \\;\\;\\;\\;\\;\\;\\;\\;x + 4 \\end{equation}\n", 251 | "\\begin{equation}x - 2 |\\overline{x^{2} + 2x - 3} \\end{equation}\n", 252 | "\\begin{equation}- (x^{2} -2x) \\end{equation}\n", 253 | "\\begin{equation}\\;\\;\\;\\;\\;\\overline{\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;4x -3} \\end{equation}\n", 254 | "\\begin{equation}- (\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;4x -8) \\end{equation}\n", 255 | "\\begin{equation}\\;\\;\\;\\;\\;\\overline{\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;\\;5} \\end{equation}\n", 256 | "\n", 257 | "We're now left with just 5, which we can't divide further by x - 2; so that's our remainder, which we'll add as a fraction.\n", 258 | "\n", 259 | "The solution to our division problem is:\n", 260 | "\n", 261 | "\\begin{equation}x + 4 + \\frac{5}{x-2} \\end{equation}\n", 262 | "\n", 263 | "Once again, we can use Python to check our answer:" 264 | ] 265 | }, 266 | { 267 | "cell_type": "code", 268 | "execution_count": null, 269 | "metadata": { 270 | "collapsed": true 271 | }, 272 | "outputs": [], 273 | "source": [ 274 | "from random import randint\n", 275 | "x = randint(3,100)\n", 276 | "\n", 277 | "(x**2 + 2*x -3)/(x-2) == x + 4 + (5/(x-2))\n", 278 | " " 279 | ] 280 | } 281 | ], 282 | "metadata": { 283 | "kernelspec": { 284 | "display_name": "Python 3.6", 285 | "language": "python", 286 | "name": "python36" 287 | }, 288 | "language_info": { 289 | "codemirror_mode": { 290 | "name": "ipython", 291 | "version": 3 292 | }, 293 | "file_extension": ".py", 294 | "mimetype": "text/x-python", 295 | "name": "python", 296 | "nbconvert_exporter": "python", 297 | "pygments_lexer": "ipython3", 298 | "version": "3.6.3" 299 | } 300 | }, 301 | "nbformat": 4, 302 | "nbformat_minor": 2 303 | } 304 | -------------------------------------------------------------------------------- /Basics Of Algebra by Hiren/01-06-Factorization.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Factorization\n", 8 | "Factorization is the process of restating an expression as the *product* of two expressions (in other words, expressions multiplied together).\n", 9 | "\n", 10 | "For example, you can make the value **16** by performing the following multiplications of integer numbers:\n", 11 | "- 1 x 16\n", 12 | "- 2 x 8\n", 13 | "- 4 x 4\n", 14 | "\n", 15 | "Another way of saying this is that 1, 2, 4, 8, and 16 are all factors of 16.\n", 16 | "\n", 17 | "## Factors of Polynomial Expressions\n", 18 | "We can apply the same logic to polynomial expressions. For example, consider the following monomial expression:\n", 19 | "\n", 20 | "\\begin{equation}-6x^{2}y^{3} \\end{equation}\n", 21 | "\n", 22 | "You can get this value by performing the following multiplication:\n", 23 | "\n", 24 | "\\begin{equation}(2xy^{2})(-3xy) \\end{equation}\n", 25 | "\n", 26 | "Run the following Python code to test this with arbitrary ***x*** and ***y*** values:" 27 | ] 28 | }, 29 | { 30 | "cell_type": "code", 31 | "execution_count": null, 32 | "metadata": { 33 | "collapsed": true 34 | }, 35 | "outputs": [], 36 | "source": [ 37 | "from random import randint\n", 38 | "x = randint(1,100)\n", 39 | "y = randint(1,100)\n", 40 | "\n", 41 | "(2*x*y**2)*(-3*x*y) == -6*x**2*y**3" 42 | ] 43 | }, 44 | { 45 | "cell_type": "markdown", 46 | "metadata": {}, 47 | "source": [ 48 | "So, we can say that **2xy2** and **-3xy** are both factors of **-6x2y3**.\n", 49 | "\n", 50 | "This also applies to polynomials with more than one term. For example, consider the following expression:\n", 51 | "\n", 52 | "\\begin{equation}(x + 2)(2x^{2} - 3y + 2) = 2x^{3} + 4x^{2} - 3xy + 2x - 6y + 4 \\end{equation}\n", 53 | "\n", 54 | "Based on this, **x+2** and **2x2 - 3y + 2** are both factors of **2x3 + 4x2 - 3xy + 2x - 6y + 4**.\n", 55 | "\n", 56 | "(and if you don't believe me, you can try this with random values for x and y with the following Python code):" 57 | ] 58 | }, 59 | { 60 | "cell_type": "code", 61 | "execution_count": null, 62 | "metadata": { 63 | "collapsed": true 64 | }, 65 | "outputs": [], 66 | "source": [ 67 | "from random import randint\n", 68 | "x = randint(1,100)\n", 69 | "y = randint(1,100)\n", 70 | "\n", 71 | "(x + 2)*(2*x**2 - 3*y + 2) == 2*x**3 + 4*x**2 - 3*x*y + 2*x - 6*y + 4" 72 | ] 73 | }, 74 | { 75 | "cell_type": "markdown", 76 | "metadata": {}, 77 | "source": [ 78 | "## Greatest Common Factor\n", 79 | "Of course, these may not be the only factors of **-6x2y3**, just as 8 and 2 are not the only factors of 16.\n", 80 | "\n", 81 | "Additionally, 2 and 8 aren't just factors of 16; they're factors of other numbers too - for example, they're both factors of 24 (because 2 x 12 = 24 and 8 x 3 = 24). Which leads us to the question, what is the highest number that is a factor of both 16 and 24? Well, let's look at all the numbers that multiply evenly into 12 and all the numbers that multiply evenly into 24:\n", 82 | "\n", 83 | "| 16 | 24 |\n", 84 | "|--------|--------|\n", 85 | "| 1 x 16 | 1 x 24 |\n", 86 | "| 2 x **8** | 2 x 12 |\n", 87 | "| | 3 x **8** |\n", 88 | "| 4 x 4 | 4 x 6 |\n", 89 | "\n", 90 | "The highest value that is a multiple of both 16 and 24 is **8**, so 8 is the *Greatest Common Factor* (or GCF) of 16 and 24.\n", 91 | "\n", 92 | "OK, let's apply that logic to the following expressions:\n", 93 | "\n", 94 | "\\begin{equation}15x^{2}y\\;\\;\\;\\;\\;\\;\\;\\;9xy^{3}\\end{equation}\n", 95 | "\n", 96 | "So what's the greatest common factor of these two expressions?\n", 97 | "\n", 98 | "It helps to break the expressions into their consitituent components. Let's deal with the coefficients first; we have 15 and 9. The highest value that divides evenly into both of these is **3** (3 x 5 = 15 and 3 x 3 = 9).\n", 99 | "\n", 100 | "Now let's look at the ***x*** terms; we have x2 and x. The highest value that divides evenly into both is these is **x** (*x* goes into *x* once and into *x*2 *x* times).\n", 101 | "\n", 102 | "Finally, for our ***y*** terms, we have y and y3. The highest value that divides evenly into both is these is **y** (*y* goes into *y* once and into *y*3 *y•y* times).\n", 103 | "\n", 104 | "Putting all of that together, the GCF of both of our expression is:\n", 105 | "\n", 106 | "\\begin{equation}3xy\\end{equation}\n", 107 | "\n", 108 | "An easy shortcut to identifying the GCF of an expression that includes variables with exponentials is that it will always consist of:\n", 109 | "- The *largest* numeric factor of the numeric coefficients in the polynomial expressions (in this case 3)\n", 110 | "- The *smallest* exponential of each variable (in this case, x and y, which technically are x1 and y1.\n", 111 | "\n", 112 | "You can check your answer by dividing the original expressions by the GCF to find the coefficent expressions for the GCF (in other words, how many times the GCF divides into the original expression). The result, when multiplied by the GCF will always produce the original expression. So in this case, we need to perform the following divisions:\n", 113 | "\n", 114 | "\\begin{equation}\\frac{15x^{2}y}{3xy}\\;\\;\\;\\;\\;\\;\\;\\;\\frac{9xy^{3}}{3xy}\\end{equation}\n", 115 | "\n", 116 | "These fractions simplify to **5x** and **3y2**, giving us the following calculations to prove our factorization:\n", 117 | "\n", 118 | "\\begin{equation}3xy(5x) = 15x^{2}y\\end{equation}\n", 119 | "\\begin{equation}3xy(3y^{2}) = 9xy^{3}\\end{equation}\n", 120 | "\n", 121 | "Let's try both of those in Python:" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": null, 127 | "metadata": { 128 | "collapsed": true 129 | }, 130 | "outputs": [], 131 | "source": [ 132 | "from random import randint\n", 133 | "x = randint(1,100)\n", 134 | "y = randint(1,100)\n", 135 | "\n", 136 | "print((3*x*y)*(5*x) == 15*x**2*y)\n", 137 | "print((3*x*y)*(3*y**2) == 9*x*y**3)" 138 | ] 139 | }, 140 | { 141 | "cell_type": "markdown", 142 | "metadata": {}, 143 | "source": [ 144 | "## Distributing Factors\n", 145 | "Let's look at another example. Here is a binomial expression:\n", 146 | "\n", 147 | "\\begin{equation}6x + 15y \\end{equation}\n", 148 | "\n", 149 | "To factor this, we need to find an expression that divides equally into both of these expressions. In this case, we can use **3** to factor the coefficents, because 3 • 2x = 6x and 3• 5y = 15y, so we can write our original expression as:\n", 150 | "\n", 151 | "\\begin{equation}6x + 15y = 3(2x) + 3(5y) \\end{equation}\n", 152 | "\n", 153 | "Now, remember the distributive property? It enables us to multiply each term of an expression by the same factor to calculate the product of the expression multiplied by the factor. We can *factor-out* the common factor in this expression to distribute it like this:\n", 154 | "\n", 155 | "\\begin{equation}6x + 15y = 3(2x) + 3(5y) = \\mathbf{3(2x + 5y)} \\end{equation}\n", 156 | "\n", 157 | "Let's prove to ourselves that these all evaluate to the same thing:" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": { 164 | "collapsed": true 165 | }, 166 | "outputs": [], 167 | "source": [ 168 | "from random import randint\n", 169 | "x = randint(1,100)\n", 170 | "y = randint(1,100)\n", 171 | "\n", 172 | "(6*x + 15*y) == (3*(2*x) + 3*(5*y)) == (3*(2*x + 5*y))" 173 | ] 174 | }, 175 | { 176 | "cell_type": "markdown", 177 | "metadata": {}, 178 | "source": [ 179 | "For something a little more complex, let's return to our previous example. Suppose we want to add our original 15x2y and 9xy3 expressions:\n", 180 | "\n", 181 | "\\begin{equation}15x^{2}y + 9xy^{3}\\end{equation}\n", 182 | "\n", 183 | "We've already calculated the common factor, so we know that:\n", 184 | "\n", 185 | "\\begin{equation}3xy(5x) = 15x^{2}y\\end{equation}\n", 186 | "\\begin{equation}3xy(3y^{2}) = 9xy^{3}\\end{equation}\n", 187 | "\n", 188 | "Now we can factor-out the common factor to produce a single expression:\n", 189 | "\n", 190 | "\\begin{equation}15x^{2}y + 9xy^{3} = \\mathbf{3xy(5x + 3y^{2})}\\end{equation}\n", 191 | "\n", 192 | "And here's the Python test code:" 193 | ] 194 | }, 195 | { 196 | "cell_type": "code", 197 | "execution_count": null, 198 | "metadata": { 199 | "collapsed": true 200 | }, 201 | "outputs": [], 202 | "source": [ 203 | "from random import randint\n", 204 | "x = randint(1,100)\n", 205 | "y = randint(1,100)\n", 206 | "\n", 207 | "(15*x**2*y + 9*x*y**3) == (3*x*y*(5*x + 3*y**2))" 208 | ] 209 | }, 210 | { 211 | "cell_type": "markdown", 212 | "metadata": {}, 213 | "source": [ 214 | "So you might be wondering what's so great about being able to distribute the common factor like this. The answer is that it can often be useful to apply a common factor to multiple terms in order to solve seemingly complex problems.\n", 215 | "\n", 216 | "For example, consider this:\n", 217 | "\n", 218 | "\\begin{equation}x^{2} + y^{2} + z^{2} = 127\\end{equation}\n", 219 | "\n", 220 | "Now solve this equation:\n", 221 | "\n", 222 | "\\begin{equation}a = 5x^{2} + 5y^{2} + 5z^{2}\\end{equation}\n", 223 | "\n", 224 | "At first glance, this seems tricky because there are three unknown variables, and even though we know that their squares add up to 127, we don't know their individual values. However, we can distribute the common factor and apply what we *do* know. Let's restate the problem like this:\n", 225 | "\n", 226 | "\\begin{equation}a = 5(x^{2} + y^{2} + z^{2})\\end{equation}\n", 227 | "\n", 228 | "Now it becomes easier to solve, because we know that the expression in parenthesis is equal to 127, so actually our equation is:\n", 229 | "\n", 230 | "\\begin{equation}a = 5(127)\\end{equation}\n", 231 | "\n", 232 | "So ***a*** is 5 times 127, which is 635" 233 | ] 234 | }, 235 | { 236 | "cell_type": "markdown", 237 | "metadata": {}, 238 | "source": [ 239 | "## Formulae for Factoring Squares\n", 240 | "There are some useful ways that you can employ factoring to deal with expressions that contain squared values (that is, values with an exponential of 2).\n", 241 | "\n", 242 | "### Differences of Squares\n", 243 | "Consider the following expression:\n", 244 | "\n", 245 | "\\begin{equation}x^{2} - 9\\end{equation}\n", 246 | "\n", 247 | "The constant *9* is 32, so we could rewrite this as:\n", 248 | "\n", 249 | "\\begin{equation}x^{2} - 3^{2}\\end{equation}\n", 250 | "\n", 251 | "Whenever you need to subtract one squared term from another, you can use an approach called the *difference of squares*, whereby we can factor *a2 - b2* as *(a - b)(a + b)*; so we can rewrite the expression as:\n", 252 | "\n", 253 | "\\begin{equation}(x - 3)(x + 3)\\end{equation}\n", 254 | "\n", 255 | "Run the code below to check this:" 256 | ] 257 | }, 258 | { 259 | "cell_type": "code", 260 | "execution_count": null, 261 | "metadata": { 262 | "collapsed": true 263 | }, 264 | "outputs": [], 265 | "source": [ 266 | "from random import randint\n", 267 | "x = randint(1,100)\n", 268 | "\n", 269 | "(x**2 - 9) == (x - 3)*(x + 3)" 270 | ] 271 | }, 272 | { 273 | "cell_type": "markdown", 274 | "metadata": {}, 275 | "source": [ 276 | "### Perfect Squares\n", 277 | "A *perfect square* is a number multiplied by itself, for example 3 multipled by 3 is 9, so 9 is a perfect square.\n", 278 | "\n", 279 | "When working with equations, the ability to factor between polynomial expressions and binomial perfect square expressions can be a useful tool. For example, consider this expression:\n", 280 | "\n", 281 | "\\begin{equation}x^{2} + 10x + 25\\end{equation}\n", 282 | "\n", 283 | "We can use 5 as a common factor to rewrite this as:\n", 284 | "\n", 285 | "\\begin{equation}(x + 5)(x + 5)\\end{equation}\n", 286 | "\n", 287 | "So what happened here?\n", 288 | "\n", 289 | "Well, first we found a common factor for our coefficients: 5 goes into 10 twice and into 25 five times (in other words, squared). Then we just expressed this factoring as a multiplication of two identical binomials *(x + 5)(x + 5)*.\n", 290 | "\n", 291 | "Remember the rule for multiplication of polynomials is to multiple each term in the first polynomial by each term in the second polynomial and then add the results; so you can do this to verify the factorization:\n", 292 | "\n", 293 | "- x • x = x2\n", 294 | "- x • 5 = 5x\n", 295 | "- 5 • x = 5x\n", 296 | "- 5 • 5 = 25\n", 297 | "\n", 298 | "When you combine the two 5x terms we get back to our original expression of x2 + 10x + 25.\n", 299 | "\n", 300 | "Now we have an expression multipled by itself; in other words, a perfect square. We can therefore rewrite this as:\n", 301 | "\n", 302 | "\\begin{equation}(x + 5)^{2}\\end{equation}\n", 303 | "\n", 304 | "Factorization of perfect squares is a useful technique, as you'll see when we start to tackle quadratic equations in the next section. In fact, it's so useful that it's worth memorizing its formula:\n", 305 | "\n", 306 | "\\begin{equation}(a + b)^{2} = a^{2} + b^{2}+ 2ab \\end{equation}\n", 307 | "\n", 308 | "In our example, the *a* terms is ***x*** and the *b* terms is ***5***, and in standard form, our equation *x2 + 10x + 25* is actually *a2 + 2ab + b2*. The operations are all additions, so the order isn't actually important!\n", 309 | "\n", 310 | "Run the following code with random values for *a* and *b* to verify that the formula works:" 311 | ] 312 | }, 313 | { 314 | "cell_type": "code", 315 | "execution_count": null, 316 | "metadata": {}, 317 | "outputs": [], 318 | "source": [ 319 | "from random import randint\n", 320 | "a = randint(1,100)\n", 321 | "b = randint(1,100)\n", 322 | "\n", 323 | "a**2 + b**2 + (2*a*b) == (a + b)**2" 324 | ] 325 | } 326 | ], 327 | "metadata": { 328 | "kernelspec": { 329 | "display_name": "Python 3.6", 330 | "language": "python", 331 | "name": "python36" 332 | }, 333 | "language_info": { 334 | "codemirror_mode": { 335 | "name": "ipython", 336 | "version": 3 337 | }, 338 | "file_extension": ".py", 339 | "mimetype": "text/x-python", 340 | "name": "python", 341 | "nbconvert_exporter": "python", 342 | "pygments_lexer": "ipython3", 343 | "version": "3.6.3" 344 | } 345 | }, 346 | "nbformat": 4, 347 | "nbformat_minor": 2 348 | } 349 | -------------------------------------------------------------------------------- /Basics Of Algebra by Hiren/01-08-Functions.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Functions\n", 8 | "So far in this course we've explored equations that perform algebraic operations to produce one or more results. A *function* is a way of encapsulating an operation that takes an input and produces exactly one ouput.\n", 9 | "\n", 10 | "For example, consider the following function definition:\n", 11 | "\n", 12 | "\\begin{equation}f(x) = x^{2} + 2\\end{equation}\n", 13 | "\n", 14 | "This defines a function named ***f*** that accepts one input (***x***) and returns a single value that is the result calculated by the expression *x2 + 2*.\n", 15 | "\n", 16 | "Having defined the function, we can use it for any input value. For example:\n", 17 | "\n", 18 | "\\begin{equation}f(3) = 11\\end{equation}\n", 19 | "\n", 20 | "You've already seen a few examples of Python functions, which are defined using the **def** keyword. However, the strict definition of an algebraic function is that it must return a single value. Here's an example of defining and using a Python function that meets this criteria:" 21 | ] 22 | }, 23 | { 24 | "cell_type": "code", 25 | "execution_count": null, 26 | "metadata": { 27 | "collapsed": true 28 | }, 29 | "outputs": [], 30 | "source": [ 31 | "# define a function to return x^2 + 2\n", 32 | "def f(x):\n", 33 | " return x**2 + 2\n", 34 | "\n", 35 | "# call the function\n", 36 | "f(3)" 37 | ] 38 | }, 39 | { 40 | "cell_type": "markdown", 41 | "metadata": {}, 42 | "source": [ 43 | "You can use functions in equations, just like any other term. For example, consider the following equation:\n", 44 | "\n", 45 | "\\begin{equation}y = f(x) - 1\\end{equation}\n", 46 | "\n", 47 | "To calculate a value for ***y***, we take the ***f*** of ***x*** and subtract 1. So assuming that ***f*** is defined as previously, given an ***x*** value of 4, this equation returns a ***y*** value of **17** (*f*(4) returns 42 + 2, so 16 + 2 = 18; and then the equation subtracts 1 to give us 17). Here it is in Python:" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": { 54 | "collapsed": true 55 | }, 56 | "outputs": [], 57 | "source": [ 58 | "x = 4\n", 59 | "y = f(x) - 1\n", 60 | "print(y)" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "Of course, the value returned by a function depends on the input; and you can graph this with the iput (let's call it ***x***) on one axis and the output (***f(x)***) on the other." 68 | ] 69 | }, 70 | { 71 | "cell_type": "code", 72 | "execution_count": null, 73 | "metadata": { 74 | "collapsed": true 75 | }, 76 | "outputs": [], 77 | "source": [ 78 | "%matplotlib inline\n", 79 | "\n", 80 | "import numpy as np\n", 81 | "from matplotlib import pyplot as plt\n", 82 | "\n", 83 | "# Create an array of x values from -100 to 100\n", 84 | "x = np.array(range(-100, 101))\n", 85 | "\n", 86 | "# Set up the graph\n", 87 | "plt.xlabel('x')\n", 88 | "plt.ylabel('f(x)')\n", 89 | "plt.grid()\n", 90 | "\n", 91 | "# Plot x against f(x)\n", 92 | "plt.plot(x,f(x), color='purple')\n", 93 | "\n", 94 | "plt.show()" 95 | ] 96 | }, 97 | { 98 | "cell_type": "markdown", 99 | "metadata": {}, 100 | "source": [ 101 | "As you can see (if you hadn't already figured it out), our function is a *quadratic function* - it returns a squared value that results in a parabolic graph when the output for multiple input values are plotted." 102 | ] 103 | }, 104 | { 105 | "cell_type": "markdown", 106 | "metadata": {}, 107 | "source": [ 108 | "## Bounds of a Function\n", 109 | "Some functions will work for any input and may return any output. For example, consider the function ***u*** defined here:\n", 110 | "\n", 111 | "\\begin{equation}u(x) = x + 1\\end{equation}\n", 112 | "\n", 113 | "This function simply adds 1 to whatever input is passed to it, so it will produce a defined output for any value of ***x*** that is a *real* number; in other words, any \"regular\" number - but not an *imaginary* number like √-1, or ∞ (infinity). You can specify the set of real numbers using the symbol ${\\rm I\\!R}$ (note the double stroke). The values that can be used for ***x*** can be expressed as a *set*, which we indicate by enclosing all of the members of the set in \"{...}\" braces; so to indicate the set of all possible values for x such that x is a member of the set of all real numbers, we can use the following expression:\n", 114 | "\n", 115 | "\\begin{equation}\\{x \\in \\rm I\\!R\\}\\end{equation}\n", 116 | "\n", 117 | "\n", 118 | "### Domain of a Function\n", 119 | "We call the set of numbers for which a function can return value it's *domain*, and in this case, the domain of ***u*** is the set of all real numbers; which is actually the default assumption for most functions.\n", 120 | "\n", 121 | "Now consider the following function ***g***:\n", 122 | "\n", 123 | "\\begin{equation}g(x) = (\\frac{12}{2x})^{2}\\end{equation}\n", 124 | "\n", 125 | "If we use this function with an ***x*** value of **2**, we would get the output **9**; because (12 ÷ (2•2))2 is 9. Similarly, if we use the value **-3** for ***x***, the output will be **4**. However, what happens when we apply this function to an ***x*** value of **0**? Anything divided by 0 is undefined, so the function ***g*** doesn't work for an ***x*** value of 0.\n", 126 | "\n", 127 | "So we need a way to denote the domain of the function ***g*** by indicating the input values for which a defined output can be returned. Specifically, we need to restrict ***x*** to a specific list of values - specifically any real number that is not 0. To indicate this, we can use the following notation:\n", 128 | "\n", 129 | "\\begin{equation}\\{x \\in \\rm I\\!R\\;\\;|\\;\\; x \\ne 0 \\}\\end{equation}\n", 130 | "\n", 131 | "This is interpreted as *Any value for x where x is in the set of real numbers such that x is not equal to 0*, and we can incorporate this into the function's definition like this:\n", 132 | "\n", 133 | "\\begin{equation}g(x) = (\\frac{12}{2x})^{2}, \\{x \\in \\rm I\\!R\\;\\;|\\;\\; x \\ne 0 \\}\\end{equation}\n", 134 | "\n", 135 | "Or more simply:\n", 136 | "\n", 137 | "\\begin{equation}g(x) = (\\frac{12}{2x})^{2},\\;\\; x \\ne 0\\end{equation}\n", 138 | "\n", 139 | "When you plot the output of a function, you can indicate the gaps caused by input values that are not in the function's domain by plotting an empty circle to show that the function is not defined at this point:" 140 | ] 141 | }, 142 | { 143 | "cell_type": "code", 144 | "execution_count": null, 145 | "metadata": { 146 | "collapsed": true 147 | }, 148 | "outputs": [], 149 | "source": [ 150 | "%matplotlib inline\n", 151 | "\n", 152 | "# Define function g\n", 153 | "def g(x):\n", 154 | " if x != 0:\n", 155 | " return (12/(2*x))**2\n", 156 | "\n", 157 | "# Plot output from function g\n", 158 | "import numpy as np\n", 159 | "from matplotlib import pyplot as plt\n", 160 | "\n", 161 | "# Create an array of x values from -100 to 100\n", 162 | "x = range(-100, 101)\n", 163 | "\n", 164 | "# Get the corresponding y values from the function\n", 165 | "y = [g(a) for a in x]\n", 166 | "\n", 167 | "# Set up the graph\n", 168 | "plt.xlabel('x')\n", 169 | "plt.ylabel('g(x)')\n", 170 | "plt.grid()\n", 171 | "\n", 172 | "# Plot x against g(x)\n", 173 | "plt.plot(x,y, color='purple')\n", 174 | "\n", 175 | "# plot an empty circle to show the undefined point\n", 176 | "plt.plot(0,g(0.0000001), color='purple', marker='o', markerfacecolor='w', markersize=8)\n", 177 | "\n", 178 | "plt.show()" 179 | ] 180 | }, 181 | { 182 | "cell_type": "markdown", 183 | "metadata": {}, 184 | "source": [ 185 | "Note that the function works for every value other than 0; so the function is defined for x = 0.000000001, and for x = -0.000000001; it only fails to return a defined value for exactly 0.\n", 186 | "\n", 187 | "OK, let's take another example. Consider this function:\n", 188 | "\n", 189 | "\\begin{equation}h(x) = 2\\sqrt{x}\\end{equation}\n", 190 | "\n", 191 | "Applying this function to a non-negative ***x*** value returns a meaningful output; but for any value where ***x*** is negative, the output is undefined.\n", 192 | "\n", 193 | "We can indicate the domain of this function in its definition like this:\n", 194 | "\n", 195 | "\\begin{equation}h(x) = 2\\sqrt{x}, \\{x \\in \\rm I\\!R\\;\\;|\\;\\; x \\ge 0 \\}\\end{equation}\n", 196 | "\n", 197 | "This is interpreted as *Any value for x where x is in the set of real numbers such that x is greater than or equal to 0*.\n", 198 | "\n", 199 | "Or, you might see this in a simpler format:\n", 200 | "\n", 201 | "\\begin{equation}h(x) = 2\\sqrt{x},\\;\\; x \\ge 0\\end{equation}\n", 202 | "\n", 203 | "Note that the symbol ≥ is used to indicate that the value must be *greater than **or equal to*** 0; and this means that **0** is included in the set of valid values. To indicate that the value must be *greater than 0, **not including 0***, use the > symbol. You can also use the equivalent symbols for *less than or equal to* (≤) and *less than* (<).\n", 204 | "\n", 205 | "When plotting a function line that marks the end of a continuous range, the end of the line is shown as a circle, which is filled if the function includes the value at that point, and unfilled if it does not.\n", 206 | "\n", 207 | "Here's the Python to plot function ***h***:" 208 | ] 209 | }, 210 | { 211 | "cell_type": "code", 212 | "execution_count": null, 213 | "metadata": { 214 | "collapsed": true 215 | }, 216 | "outputs": [], 217 | "source": [ 218 | "%matplotlib inline\n", 219 | "\n", 220 | "def h(x):\n", 221 | " if x >= 0:\n", 222 | " import numpy as np\n", 223 | " return 2 * np.sqrt(x)\n", 224 | "\n", 225 | "# Plot output from function h\n", 226 | "import numpy as np\n", 227 | "from matplotlib import pyplot as plt\n", 228 | "\n", 229 | "# Create an array of x values from -100 to 100\n", 230 | "x = range(-100, 101)\n", 231 | "\n", 232 | "# Get the corresponding y values from the function\n", 233 | "y = [h(a) for a in x]\n", 234 | "\n", 235 | "# Set up the graph\n", 236 | "plt.xlabel('x')\n", 237 | "plt.ylabel('h(x)')\n", 238 | "plt.grid()\n", 239 | "\n", 240 | "# Plot x against h(x)\n", 241 | "plt.plot(x,y, color='purple')\n", 242 | "\n", 243 | "# plot a filled circle at the end to indicate a closed interval\n", 244 | "plt.plot(0, h(0), color='purple', marker='o', markerfacecolor='purple', markersize=8)\n", 245 | "\n", 246 | "plt.show()" 247 | ] 248 | }, 249 | { 250 | "cell_type": "markdown", 251 | "metadata": {}, 252 | "source": [ 253 | "Sometimes, a function may be defined for a specific *interval*; for example, for all values between 0 and 5:\n", 254 | "\n", 255 | "\\begin{equation}j(x) = x + 2,\\;\\; x \\ge 0 \\text{ and } x \\le 5\\end{equation}\n", 256 | "\n", 257 | "In this case, the function is defined for ***x*** values between 0 and 5 *inclusive*; in other words, **0** and **5** are included in the set of defined values. This is known as a *closed* interval and can be indicated like this:\n", 258 | "\n", 259 | "\\begin{equation}\\{x \\in \\rm I\\!R\\;\\;|\\;\\; 0 \\le x \\le 5 \\}\\end{equation}\n", 260 | "\n", 261 | "It could also be indicated like this:\n", 262 | "\n", 263 | "\\begin{equation}\\{x \\in \\rm I\\!R\\;\\;|\\;\\; [0,5] \\}\\end{equation}\n", 264 | "\n", 265 | "If the condition in the function was **x > 0 and x < 5**, then the interval would be described as *open* and 0 and 5 would *not* be included in the set of defined values. This would be indicated using one of the following expressions:\n", 266 | "\n", 267 | "\\begin{equation}\\{x \\in \\rm I\\!R\\;\\;|\\;\\; 0 \\lt x \\lt 5 \\}\\end{equation}\n", 268 | "\\begin{equation}\\{x \\in \\rm I\\!R\\;\\;|\\;\\; (0,5) \\}\\end{equation}\n", 269 | "\n", 270 | "Here's function ***j*** in Python:" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": null, 276 | "metadata": { 277 | "collapsed": true 278 | }, 279 | "outputs": [], 280 | "source": [ 281 | "%matplotlib inline\n", 282 | "\n", 283 | "def j(x):\n", 284 | " if x >= 0 and x <= 5:\n", 285 | " return x + 2\n", 286 | "\n", 287 | " \n", 288 | "# Plot output from function j\n", 289 | "import numpy as np\n", 290 | "from matplotlib import pyplot as plt\n", 291 | "\n", 292 | "# Create an array of x values from -100 to 100\n", 293 | "x = range(-100, 101)\n", 294 | "y = [j(a) for a in x]\n", 295 | "\n", 296 | "# Set up the graph\n", 297 | "plt.xlabel('x')\n", 298 | "plt.ylabel('j(x)')\n", 299 | "plt.grid()\n", 300 | "\n", 301 | "# Plot x against k(x)\n", 302 | "plt.plot(x, y, color='purple')\n", 303 | "\n", 304 | "# plot a filled circle at the ends to indicate an open interval\n", 305 | "plt.plot(0, j(0), color='purple', marker='o', markerfacecolor='purple', markersize=8)\n", 306 | "plt.plot(5, j(5), color='purple', marker='o', markerfacecolor='purple', markersize=8)\n", 307 | "\n", 308 | "plt.show()" 309 | ] 310 | }, 311 | { 312 | "cell_type": "markdown", 313 | "metadata": {}, 314 | "source": [ 315 | "Now, suppose we have a function like this:\n", 316 | "\n", 317 | "\\begin{equation}\n", 318 | "k(x) = \\begin{cases}\n", 319 | " 0, & \\text{if } x = 0, \\\\\n", 320 | " 1, & \\text{if } x = 100\n", 321 | "\\end{cases}\n", 322 | "\\end{equation}\n", 323 | "\n", 324 | "In this case, the function has highly restricted domain; it only returns a defined output for 0 and 100. No output for any other ***x*** value is defined. In this case, the set of the domain is:\n", 325 | "\n", 326 | "\\begin{equation}\\{0,100\\}\\end{equation}\n", 327 | "\n", 328 | "Note that this does not include all real numbers, it only includes 0 and 100.\n", 329 | "\n", 330 | "When we use Python to plot this function, note that it only makes sense to plot a scatter plot showing the individual values returned, there is no line in between because the function is not continuous between the values within the domain. " 331 | ] 332 | }, 333 | { 334 | "cell_type": "code", 335 | "execution_count": null, 336 | "metadata": { 337 | "collapsed": true 338 | }, 339 | "outputs": [], 340 | "source": [ 341 | "%matplotlib inline\n", 342 | "\n", 343 | "def k(x):\n", 344 | " if x == 0:\n", 345 | " return 0\n", 346 | " elif x == 100:\n", 347 | " return 1\n", 348 | "\n", 349 | " \n", 350 | "# Plot output from function k\n", 351 | "from matplotlib import pyplot as plt\n", 352 | "\n", 353 | "# Create an array of x values from -100 to 100\n", 354 | "x = range(-100, 101)\n", 355 | "# Get the k(x) values for every value in x\n", 356 | "y = [k(a) for a in x]\n", 357 | "\n", 358 | "# Set up the graph\n", 359 | "plt.xlabel('x')\n", 360 | "plt.ylabel('k(x)')\n", 361 | "plt.grid()\n", 362 | "\n", 363 | "# Plot x against k(x)\n", 364 | "plt.scatter(x, y, color='purple')\n", 365 | "\n", 366 | "plt.show()" 367 | ] 368 | }, 369 | { 370 | "cell_type": "markdown", 371 | "metadata": {}, 372 | "source": [ 373 | "### Range of a Function\n", 374 | "Just as the domain of a function defines the set of values for which the function is defined, the *range* of a function defines the set of possible outputs from the function.\n", 375 | "\n", 376 | "For example, consider the following function:\n", 377 | "\n", 378 | "\\begin{equation}p(x) = x^{2} + 1\\end{equation}\n", 379 | "\n", 380 | "The domain of this function is all real numbers. However, this is a quadratic function, so the output values will form a parabola; and since the function has no negative coefficient or constant, it will be an upward opening parabola with a vertex that has a y value of 1.\n", 381 | "\n", 382 | "So what does that tell us? Well, the minimum value that will be returned by this function is 1, so it's range is:\n", 383 | "\n", 384 | "\\begin{equation}\\{p(x) \\in \\rm I\\!R\\;\\;|\\;\\; p(x) \\ge 1 \\}\\end{equation}\n", 385 | "\n", 386 | "Let's create and plot the function for a range of ***x*** values in Python:" 387 | ] 388 | }, 389 | { 390 | "cell_type": "code", 391 | "execution_count": null, 392 | "metadata": { 393 | "collapsed": true 394 | }, 395 | "outputs": [], 396 | "source": [ 397 | "%matplotlib inline\n", 398 | "\n", 399 | "# define a function to return x^2 + 1\n", 400 | "def p(x):\n", 401 | " return x**2 + 1\n", 402 | "\n", 403 | "\n", 404 | "# Plot the function\n", 405 | "import numpy as np\n", 406 | "from matplotlib import pyplot as plt\n", 407 | "\n", 408 | "# Create an array of x values from -100 to 100\n", 409 | "x = np.array(range(-100, 101))\n", 410 | "\n", 411 | "# Set up the graph\n", 412 | "plt.xlabel('x')\n", 413 | "plt.ylabel('p(x)')\n", 414 | "plt.grid()\n", 415 | "\n", 416 | "# Plot x against f(x)\n", 417 | "plt.plot(x,p(x), color='purple')\n", 418 | "\n", 419 | "plt.show()" 420 | ] 421 | }, 422 | { 423 | "cell_type": "markdown", 424 | "metadata": {}, 425 | "source": [ 426 | "Note that the ***p(x)*** values in the plot drop exponentially for ***x*** values that are negative, and then rise exponentially for positive ***x*** values; but the minimum value returned by the function (for an *x* value of 0) is **1**." 427 | ] 428 | } 429 | ], 430 | "metadata": { 431 | "kernelspec": { 432 | "display_name": "Python 3", 433 | "language": "python", 434 | "name": "python3" 435 | }, 436 | "language_info": { 437 | "codemirror_mode": { 438 | "name": "ipython", 439 | "version": 3 440 | }, 441 | "file_extension": ".py", 442 | "mimetype": "text/x-python", 443 | "name": "python", 444 | "nbconvert_exporter": "python", 445 | "pygments_lexer": "ipython3", 446 | "version": "3.6.1" 447 | } 448 | }, 449 | "nbformat": 4, 450 | "nbformat_minor": 2 451 | } 452 | -------------------------------------------------------------------------------- /Basics of Calculus by Hiren/02-01-Rate of Change.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Rate of Change\n", 8 | "Functions are often visualized as a line on a graph, and this line shows how the value returned by the function changes based on changes in the input value.\n", 9 | "\n", 10 | "## Linear Rate of Change\n", 11 | "\n", 12 | "For example, imagine a function that returns the number of meters travelled by a cyclist based on the number of seconds that the cyclist has been cycling.\n", 13 | "\n", 14 | "Here is such a function:\n", 15 | "\n", 16 | "\\begin{equation}q(x) = 2x + 1\\end{equation}\n", 17 | "\n", 18 | "We can plot the output for this function for a period of 10 seconds like this:" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": {}, 25 | "outputs": [], 26 | "source": [ 27 | "%matplotlib inline\n", 28 | "\n", 29 | "def q(x):\n", 30 | " return 2*x + 1\n", 31 | "\n", 32 | "# Plot the function\n", 33 | "import numpy as np\n", 34 | "from matplotlib import pyplot as plt\n", 35 | "\n", 36 | "# Create an array of x values from 0 to 10\n", 37 | "x = np.array(range(0, 11))\n", 38 | "\n", 39 | "# Set up the graph\n", 40 | "plt.xlabel('Seconds')\n", 41 | "plt.ylabel('Meters')\n", 42 | "plt.xticks(range(0,11, 1))\n", 43 | "plt.yticks(range(0, 22, 1))\n", 44 | "plt.grid()\n", 45 | "\n", 46 | "# Plot x against q(x)\n", 47 | "plt.plot(x,q(x), color='green')\n", 48 | "\n", 49 | "plt.show()" 50 | ] 51 | }, 52 | { 53 | "cell_type": "markdown", 54 | "metadata": {}, 55 | "source": [ 56 | "It's clear from the graph that ***q*** is a *linear* function that describes a slope in which distance increases at a constant rate over time. In other words, the cyclist is travelling at a constant speed.\n", 57 | "\n", 58 | "But what speed?\n", 59 | "\n", 60 | "Speed, or more technically, velocity is a measure of change - it measures how the distance travelled changes over time (which is why we typically express it as a unit of distance per a unit of time, like *miles-per-hour* or *meters-per-second*). So we're looking for a way to measure the change in the line created by the function.\n", 61 | "\n", 62 | "The change in values along the line define its *slope*, which we know from a previous lesson is represented like this:\n", 63 | "\n", 64 | "\\begin{equation}m = \\frac{\\Delta{y}}{\\Delta{x}} \\end{equation}\n", 65 | "\n", 66 | "We can calculate the slope of our function like this:\n", 67 | "\n", 68 | "\\begin{equation}m = \\frac{q(x)_{2} - q(x)_{1}}{x_{2} - x_{1}} \\end{equation}\n", 69 | "\n", 70 | "So we just need two ordered pairs of ***x*** and ***q(x)*** values from our line to apply this equation.\n", 71 | "\n", 72 | "- After 1 second, ***x*** is 1 and ***q***(1) = **3**.\n", 73 | "- After 10 seconds, ***x*** is 10 and ***q***(10) = 21.\n", 74 | "\n", 75 | "So we can meassure the rate of change like this:\n", 76 | "\n", 77 | "\\begin{equation}m = \\frac{21 - 3}{10 - 1} \\end{equation}\n", 78 | "\n", 79 | "This is the same as:\n", 80 | "\n", 81 | "\\begin{equation}m = \\frac{18}{9} \\end{equation}\n", 82 | "\n", 83 | "Which simplifies to:\n", 84 | "\n", 85 | "\\begin{equation}m = \\frac{2}{1} \\end{equation}\n", 86 | "\n", 87 | "So our rate of change is 2/1 or put another way, the cyclist is travelling at 2 meters-per-second." 88 | ] 89 | }, 90 | { 91 | "cell_type": "markdown", 92 | "metadata": {}, 93 | "source": [ 94 | "## Average Rate of Change\n", 95 | "OK, let's look at another function that calculates distance travelled for a given number of seconds:\n", 96 | "\n", 97 | "\\begin{equation}r(x) = x^{2} + x\\end{equation}\n", 98 | "\n", 99 | "Let's take a look at that using Python:" 100 | ] 101 | }, 102 | { 103 | "cell_type": "code", 104 | "execution_count": null, 105 | "metadata": { 106 | "collapsed": true 107 | }, 108 | "outputs": [], 109 | "source": [ 110 | "%matplotlib inline\n", 111 | "\n", 112 | "def r(x):\n", 113 | " return x**2 + x\n", 114 | "\n", 115 | "# Plot the function\n", 116 | "import numpy as np\n", 117 | "from matplotlib import pyplot as plt\n", 118 | "\n", 119 | "# Create an array of x values from 0 to 10\n", 120 | "x = np.array(range(0, 11))\n", 121 | "\n", 122 | "# Set up the graph\n", 123 | "plt.xlabel('Seconds')\n", 124 | "plt.ylabel('Meters')\n", 125 | "plt.grid()\n", 126 | "\n", 127 | "# Plot x against r(x)\n", 128 | "plt.plot(x,r(x), color='green')\n", 129 | "\n", 130 | "plt.show()" 131 | ] 132 | }, 133 | { 134 | "cell_type": "markdown", 135 | "metadata": {}, 136 | "source": [ 137 | "This time, the function is not linear. It's actually a quadratic function, and the line from 0 seconds to 10 seconds shows an exponential increase; in other words, the cyclist is *accelerating*.\n", 138 | "\n", 139 | "Technically, acceleration itself is a measure of change in velocity over time; and velocity, as we've already discussed, is a measure of change in distance over time. So measuring accelleration is pretty complex, and requires *differential calculus*, which we're going to cover shortly. In fact, even just measuring the velocity at a single point in time requires differential calculus; but we can use algebraic methods to calculate an *average* rate of velocity for a given period shown in the graph.\n", 140 | "\n", 141 | "First, we need to define a *secant* line that joins two points in our exponential arc to create a straight slope. For example, a secant line for the entire 10 second time span would join the following two points:\n", 142 | "\n", 143 | "- 0, ***r***(0)\n", 144 | "- 10, ***r***(10)\n", 145 | "\n", 146 | "Run the following Python code to visualize this line:" 147 | ] 148 | }, 149 | { 150 | "cell_type": "code", 151 | "execution_count": null, 152 | "metadata": { 153 | "collapsed": true 154 | }, 155 | "outputs": [], 156 | "source": [ 157 | "%matplotlib inline\n", 158 | "\n", 159 | "def r(x):\n", 160 | " return (x)**2 + x\n", 161 | "\n", 162 | "# Plot the function\n", 163 | "import numpy as np\n", 164 | "from matplotlib import pyplot as plt\n", 165 | "\n", 166 | "# Create an array of x values from 0 to 10\n", 167 | "x = np.array(range(0, 11))\n", 168 | "\n", 169 | "# Create an array for the secant line\n", 170 | "s = np.array([0,10])\n", 171 | "\n", 172 | "# Set up the graph\n", 173 | "plt.xlabel('Seconds')\n", 174 | "plt.ylabel('Meters')\n", 175 | "plt.grid()\n", 176 | "\n", 177 | "# Plot x against r(x)\n", 178 | "plt.plot(x,r(x), color='green')\n", 179 | "\n", 180 | "# Plot the secant line\n", 181 | "plt.plot(s,r(s), color='magenta')\n", 182 | "\n", 183 | "plt.show()" 184 | ] 185 | }, 186 | { 187 | "cell_type": "markdown", 188 | "metadata": {}, 189 | "source": [ 190 | "Now, because the secant line is straight, we can apply the slope formula we used for a linear function to calculate the average velocity for the 10 second period:\n", 191 | "\n", 192 | "- At 0 seconds, ***x*** is 0 and ***r***(0) = **0**.\n", 193 | "- At 10 seconds, ***x*** is 10 and ***r***(10) = 110.\n", 194 | "\n", 195 | "So we can meassure the rate of change like this:\n", 196 | "\n", 197 | "\\begin{equation}m = \\frac{110 - 0}{10 - 0} \\end{equation}\n", 198 | "\n", 199 | "This is the same as:\n", 200 | "\n", 201 | "\\begin{equation}m = \\frac{110}{10} \\end{equation}\n", 202 | "\n", 203 | "Which simplifies to:\n", 204 | "\n", 205 | "\\begin{equation}m = \\frac{11}{1} \\end{equation}\n", 206 | "\n", 207 | "So our rate of change is 11/1 or put another way, the cyclist is travelling at an average velocity of 11 meters-per-second over the 10-second period.\n", 208 | "\n", 209 | "Of course, we can measure the average velocity between any two points on the exponential line. Use the following Python code to show the secant line for the period between 2 and 7 seconds, and calculate the average velocity for that period" 210 | ] 211 | }, 212 | { 213 | "cell_type": "code", 214 | "execution_count": null, 215 | "metadata": { 216 | "collapsed": true 217 | }, 218 | "outputs": [], 219 | "source": [ 220 | "%matplotlib inline\n", 221 | "\n", 222 | "def r(x):\n", 223 | " return x**2 + x\n", 224 | "\n", 225 | "# Plot the function\n", 226 | "import numpy as np\n", 227 | "from matplotlib import pyplot as plt\n", 228 | "\n", 229 | "# Create an array of x values from 0 to 10\n", 230 | "x = np.array(range(0, 11))\n", 231 | "\n", 232 | "# Create an array for the secant line\n", 233 | "s = np.array([2,7])\n", 234 | "\n", 235 | "# Calculate rate of change\n", 236 | "x1 = s[0]\n", 237 | "x2 = s[-1]\n", 238 | "y1 = r(x1)\n", 239 | "y2 = r(x2)\n", 240 | "a = (y2 - y1)/(x2 - x1)\n", 241 | "\n", 242 | "\n", 243 | "# Set up the graph\n", 244 | "plt.xlabel('Seconds')\n", 245 | "plt.ylabel('Meters')\n", 246 | "plt.grid()\n", 247 | "\n", 248 | "# Plot x against r(x)\n", 249 | "plt.plot(x,r(x), color='green')\n", 250 | "\n", 251 | "# Plot the secant line\n", 252 | "plt.plot(s,r(s), color='magenta')\n", 253 | "\n", 254 | "plt.annotate('Average Velocity =' + str(a) + ' m/s',((x2+x1)/2, (y2+y1)/2))\n", 255 | "\n", 256 | "plt.show()\n", 257 | "\n" 258 | ] 259 | } 260 | ], 261 | "metadata": { 262 | "kernelspec": { 263 | "display_name": "Python 3.6", 264 | "language": "python", 265 | "name": "python36" 266 | }, 267 | "language_info": { 268 | "codemirror_mode": { 269 | "name": "ipython", 270 | "version": 3 271 | }, 272 | "file_extension": ".py", 273 | "mimetype": "text/x-python", 274 | "name": "python", 275 | "nbconvert_exporter": "python", 276 | "pygments_lexer": "ipython3", 277 | "version": "3.6.3" 278 | } 279 | }, 280 | "nbformat": 4, 281 | "nbformat_minor": 2 282 | } 283 | -------------------------------------------------------------------------------- /Basics of Calculus by Hiren/02-05-Multivariate Functions and Partial Derivatives.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Partial Derivatives\n", 8 | "Until now, we've considered derivatives of functions that operate on a single variable. How do we take the derivatives of a function like the following?\n", 9 | "\n", 10 | "$$f(x,y) = x^2 + y^2$$\n", 11 | "\n", 12 | "We can take a derivative of the changes in the function with respect to either x or y. We call these derivatives with respect to one variable partial derivatives. Let's give this a try by taking the derivative of $f(x,y)$ with respect to ***x***. We write this partial derivative as follows.\n", 13 | "\n", 14 | "$$\\frac{\\partial f(x,y)}{\\partial x} = \\frac{\\partial (x^2 + y^2)}{\\partial x}$$\n", 15 | "\n", 16 | "Just as ordinary derivatives give us a way to compute the rate of change of a function, partial derivatives give us a way to compute the rate of change of a function of many variables with respect to one of those variables.\n", 17 | "\n", 18 | "Since $f(x,y)$ is the sum of several simpler functions we need to take the partial derivative of each of these and sum the result. The first two parts are easy.\n", 19 | "\n", 20 | "$$\\frac{\\partial x^2}{\\partial x} = 2x$$\n", 21 | "\n", 22 | "Notice that we are following the usual rules of differentiation for any function of ***x*** here. \n", 23 | "\n", 24 | "Now we need to take the partial derivative of the last part of $f(x,y)$, which does not depend on ***x*** at all. In these care we get the following.\n", 25 | "\n", 26 | "$$\\frac{\\partial y^2}{\\partial x} = 0$$\n", 27 | "\n", 28 | "Now we can add up the parts to get the complete partail derivative of $f(x,y)$.\n", 29 | "\n", 30 | "$$\\frac{\\partial f(x,y)}{\\partial x} = 2x + 0 = 2x$$" 31 | ] 32 | }, 33 | { 34 | "cell_type": "markdown", 35 | "metadata": {}, 36 | "source": [ 37 | "We can also take the partial derivative of $f(x,y)$ with respect to ***y***. The process proceeds in the following manner.\n", 38 | "\n", 39 | "$$\\frac{\\partial f(x,y)}{\\partial y} = 0 + 2y = 2y$$" 40 | ] 41 | }, 42 | { 43 | "cell_type": "markdown", 44 | "metadata": { 45 | "collapsed": true 46 | }, 47 | "source": [ 48 | "## Computing a Gradient\n", 49 | "\n", 50 | "At this point, you may well ask what is the point of computing partial derivatives? Yes, they are a nifty math trick, but what are they good for? It turns out that partial derivatives are important if you want to find the analog of the slope for multi-dimensonal surfaces. We call this quantity the **gradient**. \n", 51 | "\n", 52 | "Recall that you can find minimum and maximum of curves using derivatives. In the same way, you can find the minimum and maximum of surfaces by following the gradiennt and finding the points were the gradient is zero in all directions. " 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "You have already examined the partial derivatives of the function, $f(x,y) = x^2 + y^2$. These partial derivatives are:\n", 60 | "\n", 61 | "$$\\frac{\\partial f(x,y)}{\\partial x} = 2x \\\\\n", 62 | "\\frac{\\partial f(x,y)}{\\partial y} = 2y$$\n", 63 | "\n", 64 | "In this case, the gradient is a 2-dimensional vector of the change of the function in the $x$ direction and the change in the function in the $y$ direction. This vector can be written as follows:\n", 65 | "\n", 66 | "$$grad(f(x,y)) = \\vec{g(x,y)} = \\begin{bmatrix}\\frac{\\partial f(x,y)}{\\partial x} \\\\ \\frac{\\partial f(x,y)}{\\partial y} \\end{bmatrix} = \\begin{bmatrix}2x \\\\ 2y \\end{bmatrix} $$" 67 | ] 68 | }, 69 | { 70 | "cell_type": "markdown", 71 | "metadata": {}, 72 | "source": [ 73 | "## Plotting the Gradient\n", 74 | "\n", 75 | "A plot will help you get feel for the meaning of the gradient. The code below plots the gradient of the function $f(x,y) = x^2 + y^2$ along with contours of the value of the function. Run this code and examine the plot. " 76 | ] 77 | }, 78 | { 79 | "cell_type": "code", 80 | "execution_count": null, 81 | "metadata": { 82 | "scrolled": false 83 | }, 84 | "outputs": [], 85 | "source": [ 86 | "%matplotlib inline\n", 87 | "import matplotlib.pyplot as plt\n", 88 | "import numpy as np\n", 89 | "import math\n", 90 | "\n", 91 | "## Create a uniform grid\n", 92 | "el = np.arange(-5,6)\n", 93 | "nx, ny = np.meshgrid(el, el, sparse=False, indexing='ij')\n", 94 | "\n", 95 | "## flatten the gird to 1-d and compute the value of the function z\n", 96 | "x_coord = []\n", 97 | "y_coord = []\n", 98 | "z = []\n", 99 | "for i in range(11): \n", 100 | " for j in range(11):\n", 101 | " x_coord.append(float(-nx[i,j]))\n", 102 | " y_coord.append(float(-ny[i,j])) \n", 103 | " z.append(nx[i,j]**2 + ny[i,j]**2)\n", 104 | "\n", 105 | "## perform vector arithmetic to get the x and y gradients \n", 106 | "x_grad = [-2 * x for x in x_coord]\n", 107 | "y_grad = [-2 * y for y in y_coord] \n", 108 | "\n", 109 | "## Plot the arrows using width for gradient\n", 110 | "plt.xlim(-5.5,5.5)\n", 111 | "plt.ylim(-5.5,5.5)\n", 112 | "for x, y, xg, yg in zip(list(x_coord), list(y_coord), list(x_grad), list(y_grad)):\n", 113 | " if x != 0.0 or y != 0.0: ## Avoid the zero divide when scaling the arrow\n", 114 | " l = math.sqrt(xg**2 + yg**2)/2.0\n", 115 | " plt.quiver(x, y, xg, yg, width = l, units = 'dots')\n", 116 | "\n", 117 | "## Plot the countours of the function surface\n", 118 | "z = np.array(z).reshape(11,11) \n", 119 | "plt.contour(el, el, z) " 120 | ] 121 | }, 122 | { 123 | "cell_type": "markdown", 124 | "metadata": { 125 | "collapsed": true 126 | }, 127 | "source": [ 128 | "Notice the following properties of this plot. \n", 129 | "- The arrows in the plot point in the direction of the gradient.\n", 130 | "- The width of the arrows is proportional to the value of the gradient. The width of the arrows and the **gradient decreases as function gets closer to the minimum**. If this is the case everywhere, you can say that a function is **convex**. It is always much easier to find minimum of convex functions. \n", 131 | "- The **direction of the gradient is always perpendicular to the contours**. This is an important property of multivariate functions. \n", 132 | "\n", 133 | "## Using the gradient\n", 134 | "\n", 135 | "So, what is all this good for? Say that you want to find the minimum of the function $f(x,y) = x^2 + y^2$. It is easy to see that the minimum of this function is at $x = 0$ and $y = 0$. But, what if you did not know this solution? Then you could do the following:\n", 136 | "\n", 137 | "1. Take some starting guess.\n", 138 | "2. Compute the gradient.\n", 139 | "3. take a small step in the direction of the gradient.\n", 140 | "4. Determine if the gradient is close to zero. If so, then stop, since the gradient will be zero at the minimum.\n", 141 | "5. Repeate steps 2, 3 and 4. \n", 142 | "\n", 143 | "The algorithm outlined above is called the **gradient decent method**. It is the basis of many real-world minimization algorithms. " 144 | ] 145 | } 146 | ], 147 | "metadata": { 148 | "anaconda-cloud": {}, 149 | "kernelspec": { 150 | "display_name": "Python 3", 151 | "language": "python", 152 | "name": "python3" 153 | }, 154 | "language_info": { 155 | "codemirror_mode": { 156 | "name": "ipython", 157 | "version": 3 158 | }, 159 | "file_extension": ".py", 160 | "mimetype": "text/x-python", 161 | "name": "python", 162 | "nbconvert_exporter": "python", 163 | "pygments_lexer": "ipython3", 164 | "version": "3.5.4" 165 | } 166 | }, 167 | "nbformat": 4, 168 | "nbformat_minor": 1 169 | } 170 | -------------------------------------------------------------------------------- /Basics of Calculus by Hiren/02-06-Integration.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Introduction to Integration\n", 8 | "\n", 9 | "Integrals are the inverses of derivatives. More importantly, using integration provides a way to compute the area under the curve of most any function. There are many applications for integration. For example, if you need to compute a probability of some occurance between limits (which we'll discuss later in this course), then you will use an integral.\n", 10 | "\n", 11 | "Let's start with a simple function:\n", 12 | "\n", 13 | "$$f(x)=x$$\n", 14 | "\n", 15 | "We can plot this function as a line. Run the code below to plot the function for the range 0 to 10:" 16 | ] 17 | }, 18 | { 19 | "cell_type": "code", 20 | "execution_count": null, 21 | "metadata": {}, 22 | "outputs": [], 23 | "source": [ 24 | "import numpy as np\n", 25 | "from matplotlib import pyplot as plt\n", 26 | "%matplotlib inline\n", 27 | "\n", 28 | "# Define function f\n", 29 | "def f(x):\n", 30 | " return x\n", 31 | "\n", 32 | "# Create an array of x values from 0 to 10\n", 33 | "x = range(0, 11)\n", 34 | "\n", 35 | "# Get the corresponding y values from the function\n", 36 | "y = [f(a) for a in x]\n", 37 | "\n", 38 | "# Set up the plot\n", 39 | "plt.xlabel('x')\n", 40 | "plt.ylabel('f(x)')\n", 41 | "plt.grid()\n", 42 | "\n", 43 | "# Plot x against f(x)\n", 44 | "plt.plot(x,y, color='purple')\n", 45 | "\n", 46 | "plt.show()" 47 | ] 48 | }, 49 | { 50 | "cell_type": "markdown", 51 | "metadata": {}, 52 | "source": [ 53 | "## Performing Integration\n", 54 | "\n", 55 | "The *integral* of a function is the area under it - in this case, the area under the purple diagonal line down to the x-axis.\n", 56 | "\n", 57 | "So how do you find the integral of a function? well, for our simple function $f(x) = x$, the formula for an integral is written as follows:\n", 58 | "\n", 59 | "$$\\int f(x)\\;dx$$\n", 60 | "\n", 61 | "The $\\int$ symbol shows that this formula is an integral. The $dx$ indicates that the integration is with respect to the $x$ variable. Note that since $f(x) = x$, we could also write this integral formula as $\\int x\\;dx$\n", 62 | "\n", 63 | "So, what is the integral of $x\\ dx$? To answer this question, we need the *antiderivative* of ***f*** - in other words we need to find a function which has a derivative matching the output of $f$, which is just $x$. Using the power rule in reverse, a function that has the derivative $x$ would be $\\frac{1}{2} x^2$\n", 64 | "\n", 65 | "So, the *unbound* integral formula for $f$ with respect to $x$ can be written as:\n", 66 | "\n", 67 | "$$\\int f(x)\\;dx = \\frac{1}{2} x^2$$" 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "## Integration between Limits\n", 75 | "\n", 76 | "Now that we have the unbound integral formula, we can use it to find the integral between specific start and end points. Let's suppose we want to find the area under the function between the $x$ values 0 and 2. In other words, the *integral* of $f$ for the range 0 to 2 with respect to $x$.\n", 77 | "\n", 78 | "Run the following code to re-plot the function and show the area we're interested in:" 79 | ] 80 | }, 81 | { 82 | "cell_type": "code", 83 | "execution_count": null, 84 | "metadata": {}, 85 | "outputs": [], 86 | "source": [ 87 | "# Set up the plot\n", 88 | "plt.xlabel('x')\n", 89 | "plt.ylabel('f(x)')\n", 90 | "plt.grid()\n", 91 | "\n", 92 | "# Plot x against f(x)\n", 93 | "plt.plot(x,y, color='purple')\n", 94 | "\n", 95 | "# show area for integral\n", 96 | "section = np.arange(0, 2, 1/20)\n", 97 | "plt.fill_between(section,f(section), color='orange')\n", 98 | "\n", 99 | "plt.show()" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "We call the start and end point the **limits** of the integral. The lower limit is placed as a subscript of the integral sign. The upper limit is placed as a superscript of the integral sign. Using this notation the integral of $f(x)$ from $0$ to $2$ is written as follows:\n", 107 | "\n", 108 | "$$\\int_0^2 f(x)\\;dx$$\n", 109 | "\n", 110 | "The integral is evaluated by subtracting the value of the integrand at the lower limit from the integrand at the upper limit; and since we know the formula based on our antiderivative function, the integral can be evaluated in the following manner.\n", 111 | "\n", 112 | "$$\\int_0^2 f(x)\\;dx\\\\ = \\frac{1}{2} x^2\\ \\big|_0^2\\\\\n", 113 | "= \\frac{1}{2} 2^2 - \\frac{1}{2} 0^2\\\\\n", 114 | "= \\frac{4}{2} - \\frac{0}{2} x^2\\\\ = 2$$" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "Execute the code in the cell below and verify that the result returned by the ***scipy.integrate.quad*** function in Python is approximately the same as we computed analytically. " 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": null, 127 | "metadata": {}, 128 | "outputs": [], 129 | "source": [ 130 | "import scipy.integrate as integrate\n", 131 | "i, e = integrate.quad(lambda x: f(x), 0, 2)\n", 132 | "print (i)" 133 | ] 134 | }, 135 | { 136 | "cell_type": "markdown", 137 | "metadata": {}, 138 | "source": [ 139 | "## Another Integral\n", 140 | "\n", 141 | "Here is another example for a slightly more complex function. What is the area under the curve of the function $3x^2 + 2x + 1$ between $0$ and $3$?\n", 142 | "\n", 143 | "let's look at that function and the area in question:" 144 | ] 145 | }, 146 | { 147 | "cell_type": "code", 148 | "execution_count": null, 149 | "metadata": {}, 150 | "outputs": [], 151 | "source": [ 152 | "import numpy as np\n", 153 | "from matplotlib import pyplot as plt\n", 154 | "from matplotlib.patches import Polygon\n", 155 | "%matplotlib inline\n", 156 | "\n", 157 | "# Define function g\n", 158 | "def g(x):\n", 159 | " return 3 * x**2 + 2 * x + 1\n", 160 | "\n", 161 | "# Create an array of x values from 0 to 10\n", 162 | "x = range(0, 11)\n", 163 | "\n", 164 | "# Get the corresponding y values from the function\n", 165 | "y = [g(a) for a in x]\n", 166 | "\n", 167 | "# Set up the plot\n", 168 | "fig, ax = plt.subplots()\n", 169 | "plt.xlabel('x')\n", 170 | "plt.ylabel('f(x)')\n", 171 | "plt.grid()\n", 172 | "\n", 173 | "# Plot x against g(x)\n", 174 | "plt.plot(x,y, color='purple')\n", 175 | "\n", 176 | "# Make the shaded region\n", 177 | "ix = np.linspace(0, 3)\n", 178 | "iy = g(ix)\n", 179 | "verts = [(0, 0)] + list(zip(ix, iy)) + [(3, 0)]\n", 180 | "poly = Polygon(verts, facecolor='orange')\n", 181 | "ax.add_patch(poly)\n", 182 | "\n", 183 | "plt.show()" 184 | ] 185 | }, 186 | { 187 | "cell_type": "markdown", 188 | "metadata": {}, 189 | "source": [ 190 | "We can evaluate this integral just as before, this time using function:\n", 191 | "\n", 192 | "$$\\int_0^3 3x^2 + 2x + 1\\;dx$$ \n", 193 | "\n", 194 | "We can calculate the antiderivative of $3x^2 + 2x + 1\\;dx$ as $\\frac{3}{3} x^3 + \\frac{2}{2} x^2 + x$, so:\n", 195 | "\n", 196 | "$$\\int_0^3= \\frac{3}{3} x^3 + \\frac{2}{2} x^2 + x\\ \\big|_0^3\\\\\n", 197 | "= \\frac{3}{3} 3^3 + \\frac{2}{2} 3^2 + 3 - \\frac{3}{3} 0^3 - \\frac{2}{2} 0^2 + 0\\\\\n", 198 | "= 27 + 9 + 3 + 0 + 0 + 0\\\\\n", 199 | "= 39$$\n", 200 | "\n", 201 | "Now, execute the code in the cell below to verify the result:" 202 | ] 203 | }, 204 | { 205 | "cell_type": "code", 206 | "execution_count": null, 207 | "metadata": {}, 208 | "outputs": [], 209 | "source": [ 210 | "i, e = integrate.quad(lambda x: 3 * x**2 + 2 * x + 1, 0, 3)\n", 211 | "print(i)" 212 | ] 213 | }, 214 | { 215 | "cell_type": "markdown", 216 | "metadata": {}, 217 | "source": [ 218 | "Note that the result from the ***scipy.integrate.quad*** function is approximate - the function actually returns an estimated integral (*i* in this case) and also a measure of absolute error (*e*). Run the following code to see what the absolute error was in this case:" 219 | ] 220 | }, 221 | { 222 | "cell_type": "code", 223 | "execution_count": null, 224 | "metadata": {}, 225 | "outputs": [], 226 | "source": [ 227 | "print(e)" 228 | ] 229 | }, 230 | { 231 | "cell_type": "markdown", 232 | "metadata": {}, 233 | "source": [ 234 | "The absolute error in this case is extremely small (around $4.3 \\times 10^{-13}$).\n", 235 | "\n", 236 | "## Infinite limits\n", 237 | "\n", 238 | "In many cases the limits of an integral can be $+/- \\infty$. Perhaps suprisingly, this situation is not really a problem if the function being integrated converges to $0$ at the infinite limit. \n", 239 | "\n", 240 | "Here is an example. The function $e^{-5x} \\rightarrow 0$ as $x \\rightarrow \\infty$. Therefore, the integral of this function from some limit to $\\infty$. This integral can be written as follows:\n", 241 | "\n", 242 | "$$\\int^{\\infty}_0 e^{-5x} dx$$\n", 243 | "\n", 244 | "The code in the cell below computes this integral numerically." 245 | ] 246 | }, 247 | { 248 | "cell_type": "code", 249 | "execution_count": null, 250 | "metadata": {}, 251 | "outputs": [], 252 | "source": [ 253 | "import numpy as np\n", 254 | "i, e = integrate.quad(lambda x: np.exp(-x*5), 0, np.inf)\n", 255 | "\n", 256 | "print('Integral: ' + str(i))\n", 257 | "print('Absolute Error: ' + str(e))" 258 | ] 259 | }, 260 | { 261 | "cell_type": "markdown", 262 | "metadata": {}, 263 | "source": [ 264 | "This integral converges to a small number with a much smaller error estimate. \n", 265 | "\n", 266 | "Here is another example that illustrates why having infinite integration limits is so useful. When computing probabilities it is often necessary to have infinite limits. Don't worry too much about the details of probability theory. This is covered in a later lesson. \n", 267 | "\n", 268 | "A Normal distribution with zero mean and a standard deviation of $1$ has the following density function:\n", 269 | "\n", 270 | "$$\\frac{1}{2 \\pi} e^{\\frac{-x^2}{\\sqrt(2 \\pi)}}$$\n", 271 | "\n", 272 | "It makes sense that the integral of this probability density function from $-\\infty$ to $\\infty$ must be $1.0$. In other words the probability of a Normally distributed event ocurring at all possible values must be $1.0$. \n", 273 | "\n", 274 | "The code in the cell below computes the following integral:\n", 275 | "\n", 276 | "$$\\int_{-\\infty}^{\\infty} \\frac{1}{2 \\pi} e^{\\frac{-x^2}{\\sqrt(2 \\pi)}} dx$$\n", 277 | "\n", 278 | "Execute this code and verify that the result is approximately $1.0$." 279 | ] 280 | }, 281 | { 282 | "cell_type": "code", 283 | "execution_count": null, 284 | "metadata": {}, 285 | "outputs": [], 286 | "source": [ 287 | "import numpy as np\n", 288 | "norms = lambda x: np.exp(-x**2/2.0)/np.sqrt(2.0 * 3.14159)\n", 289 | "i, e = integrate.quad(norms, -np.inf, np.inf)\n", 290 | "\n", 291 | "print('Integral: ' + str(i))\n", 292 | "print('Absolute Error: ' + str(e))" 293 | ] 294 | }, 295 | { 296 | "cell_type": "code", 297 | "execution_count": null, 298 | "metadata": {}, 299 | "outputs": [], 300 | "source": [] 301 | } 302 | ], 303 | "metadata": { 304 | "anaconda-cloud": {}, 305 | "kernelspec": { 306 | "display_name": "Python 3", 307 | "language": "python", 308 | "name": "python3" 309 | }, 310 | "language_info": { 311 | "codemirror_mode": { 312 | "name": "ipython", 313 | "version": 3 314 | }, 315 | "file_extension": ".py", 316 | "mimetype": "text/x-python", 317 | "name": "python", 318 | "nbconvert_exporter": "python", 319 | "pygments_lexer": "ipython3", 320 | "version": "3.5.4" 321 | } 322 | }, 323 | "nbformat": 4, 324 | "nbformat_minor": 1 325 | } 326 | -------------------------------------------------------------------------------- /Cheat Sheet Suggested by Siraj Raval/Calculus Cheat Sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Cheat Sheet Suggested by Siraj Raval/Calculus Cheat Sheet.pdf -------------------------------------------------------------------------------- /Cheat Sheet Suggested by Siraj Raval/Linear Algebra CheatSheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Cheat Sheet Suggested by Siraj Raval/Linear Algebra CheatSheet.pdf -------------------------------------------------------------------------------- /Cheat Sheet Suggested by Siraj Raval/Statistics Cheat Sheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Cheat Sheet Suggested by Siraj Raval/Statistics Cheat Sheet.pdf -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [2018] [Hiren K. Namera] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Other Cheat Sheets/Probability/probability_cheatsheet (1).pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Other Cheat Sheets/Probability/probability_cheatsheet (1).pdf -------------------------------------------------------------------------------- /Other Cheat Sheets/Probability/probability_cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Other Cheat Sheets/Probability/probability_cheatsheet.pdf -------------------------------------------------------------------------------- /Other Cheat Sheets/Statistics/427513-Statistics-Reference-Cheatsheet.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Other Cheat Sheets/Statistics/427513-Statistics-Reference-Cheatsheet.pdf -------------------------------------------------------------------------------- /Other Cheat Sheets/calculus/Calculus_Cheat_Sheet_All.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Other Cheat Sheets/calculus/Calculus_Cheat_Sheet_All.pdf -------------------------------------------------------------------------------- /Other Cheat Sheets/calculus/Final Notes for AB and BC.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Other Cheat Sheets/calculus/Final Notes for AB and BC.pdf -------------------------------------------------------------------------------- /Other Cheat Sheets/linear Algebra/A-linalg.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Other Cheat Sheets/linear Algebra/A-linalg.pdf -------------------------------------------------------------------------------- /Other Cheat Sheets/linear Algebra/linear-algebra.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/hrnbot/Basic-Mathematics-for-Machine-Learning/575ac794f30b0650331d8e25bddfd4a868f46ebe/Other Cheat Sheets/linear Algebra/linear-algebra.pdf -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Basic-Mathematics-for-Machine-Learning 2 | The motive behind Creating this repo is to feel the fear of mathematics and do what ever you want to do in Machine Learning , Deep Learning and other fields of AI . 3 | 4 | In this Repo I Demonstrated Basics of **Algebra, Calculus ,Statistics and Probability.** So, try this Code in your python notebook which is provided in edx Course. 5 | 6 | In this Repo you will also learn the Libraries which are essential like **numpy, pandas, matplotlib...** 7 | 8 | I am going to upload new material when i find those material useful, you can also help me in keeping this repo fresh. 9 | 10 | 11 | # Why Worry About The Maths?[ Source of this topic](https://towardsdatascience.com/the-mathematics-of-machine-learning-894f046c568) 12 | There are many reasons why the mathematics of Machine Learning is important and I will highlight some of them below: 13 | 14 | 1. Selecting the right algorithm which includes giving considerations to accuracy, training time, model complexity, number of parameters and number of features. 15 | 16 | 2. Choosing parameter settings and validation strategies. 17 | 18 | 3. Identifying underfitting and overfitting by understanding the Bias-Variance tradeoff. 19 | 20 | 4. Estimating the right confidence interval and uncertainty. 21 | 22 | # What Level of Maths Do You Need?[ Source of this topic](https://towardsdatascience.com/the-mathematics-of-machine-learning-894f046c568) 23 | # Linear Algebra: 24 | A scientist, Skyler Speakman, recently said that “Linear Algebra is the mathematics of the 21st century” and I totally agree with the statement. In ML, Linear Algebra comes up everywhere. Topics such as Principal Component Analysis (PCA), Singular Value Decomposition (SVD), Eigendecomposition of a matrix, LU Decomposition, QR Decomposition/Factorization, Symmetric Matrices, Orthogonalization & Orthonormalization, Matrix Operations, Projections, Eigenvalues & Eigenvectors, Vector Spaces and Norms are needed for understanding the optimization methods used for machine learning. The amazing thing about Linear Algebra is that there are so many online resources. I have always said that the traditional classroom is dying because of the vast amount of resources available on the internet. My favorite Linear Algebra course is the one offered by MIT Courseware (Prof. Gilbert Strang). 25 | 26 | 27 | # Probability Theory and Statistics: 28 | Machine Learning and Statistics aren’t very different fields. Actually, someone recently defined Machine Learning as ‘doing statistics on a Mac’. Some of the fundamental Statistical and Probability Theory needed for ML are Combinatorics, Probability Rules & Axioms, Bayes’ Theorem, Random Variables, Variance and Expectation, Conditional and Joint Distributions, Standard Distributions (Bernoulli, Binomial, Multinomial, Uniform and Gaussian), Moment Generating Functions, Maximum Likelihood Estimation (MLE), Prior and Posterior, Maximum a Posteriori Estimation (MAP) and Sampling Methods. 29 | 30 | # Multivariate Calculus: 31 | Some of the necessary topics include Differential and Integral Calculus, Partial Derivatives, Vector-Values Functions, Directional Gradient, Hessian, Jacobian, Laplacian and Lagrangian Distribution. 32 | 33 | # Algorithms and Complex Optimizations: 34 | This is important for understanding the computational efficiency and scalability of our Machine Learning Algorithm and for exploiting sparsity in our datasets. Knowledge of data structures (Binary Trees, Hashing, Heap, Stack etc), Dynamic Programming, Randomized & Sublinear Algorithm, Graphs, Gradient/Stochastic Descents and Primal-Dual methods are needed. 35 | 36 | # Others: 37 | This comprises of other Math topics not covered in the four major areas described above. They include Real and Complex Analysis (Sets and Sequences, Topology, Metric Spaces, Single-Valued and Continuous Functions, Limits, Cauchy Kernel, Fourier Transforms), Information Theory (Entropy, Information Gain), Function Spaces and Manifolds. 38 | 39 | Buy Me A Coffee 40 | -------------------------------------------------------------------------------- /Statistics and Probability by Hiren/04-01-Data and Visualization.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Data and Data Visualization\n", 8 | "Machine learning, and therefore a large part of AI, is based on statistical analysis of data. In this notebook, you'll examine some fundamental concepts related to data and data visualization." 9 | ] 10 | }, 11 | { 12 | "cell_type": "markdown", 13 | "metadata": {}, 14 | "source": [ 15 | "## Introduction to Data\n", 16 | "Statistics are based on data, which consist of a collection of pieces of information about things you want to study. This information can take the form of descriptions, quantities, measurements, and other observations. Typically, we work with related data items in a *dataset*, which often consists of a collection of *observations* or *cases*. Most commonly, we thing about this dataset as a table that consists of a row for each observation, and a column for each individual data point related to that observation - we variously call these data points *attributes* or *features*, and they each describe a specific characteristic of the thing we're observing.\n", 17 | "\n", 18 | "Let's take a look at a real example. In 1886, Francis Galton conducted a study into the relationship between heights of parents and their (adult) children. Run the Python code below to view the data he collected (you can safely ignore a deprecation warning if it is displayed):" 19 | ] 20 | }, 21 | { 22 | "cell_type": "code", 23 | "execution_count": null, 24 | "metadata": { 25 | "scrolled": true 26 | }, 27 | "outputs": [], 28 | "source": [ 29 | "import statsmodels.api as sm\n", 30 | "\n", 31 | "df = sm.datasets.get_rdataset('GaltonFamilies', package='HistData').data\n", 32 | "df" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "### Types of Data\n", 40 | "Now, let's take a closer look at this data (you can click the left margin next to the dataset to toggle between full height and a scrollable pane). There are 933 observations, each one recording information pertaining to an individual child. The information recorded consists of the following features:\n", 41 | "- **family**: An identifier for the family to which the child belongs.\n", 42 | "- **father**: The height of the father.\n", 43 | "- ** mother**: The height of the mother.\n", 44 | "- **midparentHeight**: The mid-point between the father and mother's heights (calculated as *(father + 1.08 x mother) ÷ 2*)\n", 45 | "- **children**: The total number of children in the family.\n", 46 | "- **childNum**: The number of the child to whom this observation pertains (Galton numbered the children in desending order of height, with male children listed before female children)\n", 47 | "- **gender**: The gender of the child to whom this observation pertains.\n", 48 | "- **childHeight**: The height of the child to whom this observation pertains.\n", 49 | "\n", 50 | "It's worth noting that there are several distinct types of data recorded here. To begin with, there are some features that represent *qualities*, or characteristics of the child - for example, gender. Other feaures represent a *quantity* or measurement, such as the child's height. So broadly speaking, we can divide data into *qualitative* and *quantitative* data.\n", 51 | "\n", 52 | "#### Qualitative Data\n", 53 | "Let's take a look at qualitative data first. This type of data is categorical - it is used to categorize or identify the entity being observed. Sometimes you'll see features of this type described as *factors*. \n", 54 | "##### Nominal Data\n", 55 | "In his observations of children's height, Galton assigned an identifier to each family and he recorded the gender of each child. Note that even though the **family** identifier is a number, it is not a measurement or quantity. Family 002 it not \"greater\" than family 001, just as a **gender** value of \"male\" does not indicate a larger or smaller value than \"female\". These are simply named values for some characteristic of the child, and as such they're known as *nominal* data.\n", 56 | "##### Ordinal Data\n", 57 | "So what about the **childNum** feature? It's not a measurement or quantity - it's just a way to identify individual children within a family. However, the number assigned to each child has some additional meaning - the numbers are ordered. You can find similar data that is text-based; for example, data about training courses might include a \"level\" attribute that indicates the level of the course as \"basic:, \"intermediate\", or \"advanced\". This type of data, where the value is not itself a quantity or measurement, but it indicates some sort of inherent order or heirarchy, is known as *ordinal* data.\n", 58 | "#### Quantitative Data\n", 59 | "Now let's turn our attention to the features that indicate some kind of quantity or measurement.\n", 60 | "##### Discrete Data\n", 61 | "Galton's observations include the number of **children** in each family. This is a *discrete* quantative data value - it's something we *count* rather than *measure*. You can't, for example, have 2.33 children!\n", 62 | "##### Continuous Data\n", 63 | "The data set also includes height values for **father**, **mother**, **midparentHeight**, and **childHeight**. These are measurements along a scale, and as such they're described as *continuous* quantative data values that we *measure* rather than *count*.\n", 64 | "\n", 65 | "### Sample vs Population\n", 66 | "Galton's dataset includes 933 observations. It's safe to assume that this does not account for every person in the world, or even just the UK, in 1886 when the data was collected. In other words, Galton's data represents a *sample* of a larger *population*. It's worth pausing to think about this for a few seconds, because there are some implications for any conclusions we might draw from Galton's observations.\n", 67 | "\n", 68 | "Think about how many times you see a claim such as \"one in four Americans enjoys watching football\". How do the people who make this claim know that this is a fact? Have they asked everyone in the the US about their football-watching habits? Well, that would be a bit impractical, so what usually happens is that a study is conducted on a subset of the population, and (assuming that this is a well-conducted study), that subset will be a representative sample of the population as a whole. If the survey was conducted at the stadium where the Superbowl is being played, then the results are likely to be skewed because of a bias in the study participants.\n", 69 | "\n", 70 | "Similarly, we might look at Galton's data and assume that the heights of the people included in the study bears some relation to the heights of the general population in 1886; but if Galton specifically selected abnormally tall people for his study, then this assumption would be unfounded.\n", 71 | "\n", 72 | "When we deal with statistics, we usually work with a sample of the data rather than a full population. As you'll see later, this affects the way we use notation to indicate statistical measures; and in some cases we calculate statistics from a sample differently than from a full population to account for bias in the sample." 73 | ] 74 | }, 75 | { 76 | "cell_type": "markdown", 77 | "metadata": {}, 78 | "source": [ 79 | "### Visualizing Data\n", 80 | "Data visualization is one of the key ways in which we can examine data and get insights from it. If a picture is worth a thousand words, then a good graph or chart is worth any number of tables of data.\n", 81 | "\n", 82 | "Let's examine some common kinds of data visualization:\n", 83 | "#### Bar Charts\n", 84 | "A *bar chart* is a good way to compare numeric quantities or counts across categories. For example, in the Galton dataset, you might want to compare the number of female and male children.\n", 85 | "\n", 86 | "Here's some Python code to create a bar chart showing the number of children of each gender." 87 | ] 88 | }, 89 | { 90 | "cell_type": "code", 91 | "execution_count": null, 92 | "metadata": {}, 93 | "outputs": [], 94 | "source": [ 95 | "import statsmodels.api as sm\n", 96 | "\n", 97 | "df = sm.datasets.get_rdataset('GaltonFamilies', package='HistData').data\n", 98 | "\n", 99 | "# Create a data frame of gender counts\n", 100 | "genderCounts = df['gender'].value_counts()\n", 101 | "\n", 102 | "# Plot a bar chart\n", 103 | "%matplotlib inline\n", 104 | "from matplotlib import pyplot as plt\n", 105 | "\n", 106 | "genderCounts.plot(kind='bar', title='Gender Counts')\n", 107 | "plt.xlabel('Gender')\n", 108 | "plt.ylabel('Number of Children')\n", 109 | "plt.show()" 110 | ] 111 | }, 112 | { 113 | "cell_type": "markdown", 114 | "metadata": {}, 115 | "source": [ 116 | "From this chart, you can see that there are slightly more male children than female children; but the data is reasonably evenly split between the two genders.\n", 117 | "\n", 118 | "Bar charts are typically used to compare categorical (qualitative) data values; but in some cases you might treat a discrete quantitative data value as a category. For example, in the Galton dataset the number of children in each family could be used as a way to categorize families. We might want to see how many familes have one child, compared to how many have two children, etc.\n", 119 | "\n", 120 | "Here's some Python code to create a bar chart showing family counts based on the number of children in the family." 121 | ] 122 | }, 123 | { 124 | "cell_type": "code", 125 | "execution_count": null, 126 | "metadata": {}, 127 | "outputs": [], 128 | "source": [ 129 | "import statsmodels.api as sm\n", 130 | "\n", 131 | "df = sm.datasets.get_rdataset('GaltonFamilies', package='HistData').data\n", 132 | "\n", 133 | "# Create a data frame of child counts\n", 134 | "# there's a row for each child, so we need to filter to one row per family to avoid over-counting\n", 135 | "families = df[['family', 'children']].drop_duplicates()\n", 136 | "# Now count number of rows for each 'children' value, and sort by the index (children)\n", 137 | "childCounts = families['children'].value_counts().sort_index()\n", 138 | "\n", 139 | "\n", 140 | "# Plot a bar chart\n", 141 | "%matplotlib inline\n", 142 | "from matplotlib import pyplot as plt\n", 143 | "\n", 144 | "childCounts.plot(kind='bar', title='Family Size')\n", 145 | "plt.xlabel('Number of Children')\n", 146 | "plt.ylabel('Families')\n", 147 | "plt.show()\n" 148 | ] 149 | }, 150 | { 151 | "cell_type": "markdown", 152 | "metadata": {}, 153 | "source": [ 154 | "Note that the code sorts the data so that the categories on the *x* axis are in order - attention to this sort of detail can make your charts easier to read. In this case, we can see that the most common number of children per family is 1, followed by 5 and 6. Comparatively fewer families have more than 8 children." 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "#### Histograms\n", 162 | "Bar charts work well for comparing categorical or discrete numeric values. When you need to compare continuous quantitative values, you can use a similar style of chart called a *histogram*. Histograms differ from bar charts in that they group the continuous values into ranges or *bins* - so the chart doesn't show a bar for each individual value, but rather a bar for each range of binned values. Because these bins represent continuous data rather than discrete data, the bars aren't separated by a gap. Typically, a histogram is used to show the relative frequency of values in the dataset.\n", 163 | "\n", 164 | "Here's some Python code to create a histogram of the **father** values in the Galton dataset, which record the father's height:" 165 | ] 166 | }, 167 | { 168 | "cell_type": "code", 169 | "execution_count": null, 170 | "metadata": {}, 171 | "outputs": [], 172 | "source": [ 173 | "import statsmodels.api as sm\n", 174 | "\n", 175 | "df = sm.datasets.get_rdataset('GaltonFamilies', package='HistData').data\n", 176 | "\n", 177 | "# Plot a histogram of midparentHeight\n", 178 | "%matplotlib inline\n", 179 | "from matplotlib import pyplot as plt\n", 180 | "\n", 181 | "df['father'].plot.hist(title='Father Heights')\n", 182 | "plt.xlabel('Height')\n", 183 | "plt.ylabel('Frequency')\n", 184 | "plt.show()" 185 | ] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "The histogram shows that the most frequently occuring heights tend to be in the mid-range. There are fewer extremely short or exteremely tall fathers.\n", 192 | "\n", 193 | "In the histogram above, the number of bins (and their corresponding ranges, or *bin widths*) was determined automatically by Python. In some cases you may want to explicitly control the number of bins, as this can help you see detail in the distribution of data values that otherwise you might miss. The following code creates a histogram for the same father's height values, but explicitly distributes them over 20 bins (19 are specified, and Python adds one):" 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": null, 199 | "metadata": {}, 200 | "outputs": [], 201 | "source": [ 202 | "import statsmodels.api as sm\n", 203 | "\n", 204 | "df = sm.datasets.get_rdataset('GaltonFamilies', package='HistData').data\n", 205 | "\n", 206 | "# Plot a histogram of midparentHeight\n", 207 | "%matplotlib inline\n", 208 | "from matplotlib import pyplot as plt\n", 209 | "\n", 210 | "df['father'].plot.hist(title='Father Heights', bins=19)\n", 211 | "plt.xlabel('Height')\n", 212 | "plt.ylabel('Frequency')\n", 213 | "plt.show()" 214 | ] 215 | }, 216 | { 217 | "cell_type": "markdown", 218 | "metadata": {}, 219 | "source": [ 220 | "We can still see that the most common heights are in the middle, but there's a notable drop in the number of fathers with a height between 67.5 and 70." 221 | ] 222 | }, 223 | { 224 | "cell_type": "markdown", 225 | "metadata": {}, 226 | "source": [ 227 | "#### Pie Charts\n", 228 | "Pie charts are another way to compare relative quantities of categories. They're not commonly used by data scientists, but they can be useful in many business contexts with manageable numbers of categories because they not only make it easy to compare relative quantities by categories; they also show those quantities as a proportion of the whole set of data.\n", 229 | "\n", 230 | "Here's some Python to show the gender counts as a pie chart:" 231 | ] 232 | }, 233 | { 234 | "cell_type": "code", 235 | "execution_count": null, 236 | "metadata": {}, 237 | "outputs": [], 238 | "source": [ 239 | "import statsmodels.api as sm\n", 240 | "\n", 241 | "df = sm.datasets.get_rdataset('GaltonFamilies', package='HistData').data\n", 242 | "\n", 243 | "# Create a data frame of gender counts\n", 244 | "genderCounts = df['gender'].value_counts()\n", 245 | "\n", 246 | "# Plot a pie chart\n", 247 | "%matplotlib inline\n", 248 | "from matplotlib import pyplot as plt\n", 249 | "genderCounts.plot(kind='pie', title='Gender Counts', figsize=(6,6))\n", 250 | "plt.legend()\n", 251 | "plt.show()" 252 | ] 253 | }, 254 | { 255 | "cell_type": "markdown", 256 | "metadata": {}, 257 | "source": [ 258 | "Note that the chart includes a *legend* to make it clear what category each colored area in the pie chart represents. From this chart, you can see that males make up slightly more than half of the overall number of children; with females accounting for the rest." 259 | ] 260 | }, 261 | { 262 | "cell_type": "markdown", 263 | "metadata": {}, 264 | "source": [ 265 | "#### Scatter Plots\n", 266 | "Often you'll want to compare quantative values. This can be especially useful in data science scenarios where you are exploring data prior to building a machine learning model, as it can help identify apparent relationships between numeric features. Scatter plots can also help identify potential outliers - values that are significantly outside of the normal range of values.\n", 267 | "\n", 268 | "The following Python code creates a scatter plot that plots the intersection points for **midparentHeight** on the *x* axis, and **childHeight** on the *y* axis:" 269 | ] 270 | }, 271 | { 272 | "cell_type": "code", 273 | "execution_count": null, 274 | "metadata": {}, 275 | "outputs": [], 276 | "source": [ 277 | "import statsmodels.api as sm\n", 278 | "\n", 279 | "df = sm.datasets.get_rdataset('GaltonFamilies', package='HistData').data\n", 280 | "\n", 281 | "# Create a data frame of heights (father vs child)\n", 282 | "parentHeights = df[['midparentHeight', 'childHeight']]\n", 283 | "\n", 284 | "# Plot a scatter plot chart\n", 285 | "%matplotlib inline\n", 286 | "from matplotlib import pyplot as plt\n", 287 | "parentHeights.plot(kind='scatter', title='Parent vs Child Heights', x='midparentHeight', y='childHeight')\n", 288 | "plt.xlabel('Avg Parent Height')\n", 289 | "plt.ylabel('Child Height')\n", 290 | "plt.show()" 291 | ] 292 | }, 293 | { 294 | "cell_type": "markdown", 295 | "metadata": {}, 296 | "source": [ 297 | "In a scatter plot, each dot marks the intersection point of the two values being plotted. In this chart, most of the heights are clustered around the center; which indicates that most parents and children tend to have a height that is somewhere in the middle of the range of heights observed. At the bottom left, there's a small cluster of dots that show some parents from the shorter end of the range who have children that are also shorter than their peers. At the top right, there are a few extremely tall parents who have extremely tall children. It's also interesting to note that the top left and bottom right of the chart are empty - there aren't any cases of extremely short parents with extremely tall children or vice-versa." 298 | ] 299 | }, 300 | { 301 | "cell_type": "markdown", 302 | "metadata": {}, 303 | "source": [ 304 | "#### Line Charts\n", 305 | "*Line charts* are a great way to see changes in values along a series - usually (but not always) based on a time period. The Galton dataset doesn't include any data of this type, so we'll use a different dataset that includes observations of sea surface temperature between 1950 and 2010 for this example:" 306 | ] 307 | }, 308 | { 309 | "cell_type": "code", 310 | "execution_count": null, 311 | "metadata": { 312 | "scrolled": false 313 | }, 314 | "outputs": [], 315 | "source": [ 316 | "import statsmodels.api as sm\n", 317 | "\n", 318 | "df = sm.datasets.elnino.load_pandas().data\n", 319 | "\n", 320 | "df['AVGSEATEMP'] = df.mean(1)\n", 321 | "\n", 322 | "# Plot a line chart\n", 323 | "%matplotlib inline\n", 324 | "from matplotlib import pyplot as plt\n", 325 | "df.plot(title='Average Sea Temperature', x='YEAR', y='AVGSEATEMP')\n", 326 | "plt.xlabel('Year')\n", 327 | "plt.ylabel('Average Sea Temp')\n", 328 | "plt.show()" 329 | ] 330 | }, 331 | { 332 | "cell_type": "markdown", 333 | "metadata": {}, 334 | "source": [ 335 | "The line chart shows the temperature trend from left to right for the period of observations. From this chart, you can see that the average temperature fluctuates from year to year, but the general trend shows an increase." 336 | ] 337 | } 338 | ], 339 | "metadata": { 340 | "kernelspec": { 341 | "display_name": "Python 3.6", 342 | "language": "python", 343 | "name": "python36" 344 | }, 345 | "language_info": { 346 | "codemirror_mode": { 347 | "name": "ipython", 348 | "version": 3 349 | }, 350 | "file_extension": ".py", 351 | "mimetype": "text/x-python", 352 | "name": "python", 353 | "nbconvert_exporter": "python", 354 | "pygments_lexer": "ipython3", 355 | "version": "3.6.3" 356 | } 357 | }, 358 | "nbformat": 4, 359 | "nbformat_minor": 2 360 | } 361 | -------------------------------------------------------------------------------- /Statistics and Probability by Hiren/04-06-Hypothesis Testing.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Hypothesis Testing" 8 | ] 9 | }, 10 | { 11 | "cell_type": "markdown", 12 | "metadata": {}, 13 | "source": [ 14 | "## Single-Sample, One-Sided Tests\n", 15 | "Our students have completed their school year, and been asked to rate their statistics class on a scale between -5 (terrible) and 5 (fantastic). The statistics class is taught online to tens of thousands of students, so to assess its success, we'll take a random sample of 50 ratings.\n", 16 | "\n", 17 | "Run the following code to draw 50 samples." 18 | ] 19 | }, 20 | { 21 | "cell_type": "code", 22 | "execution_count": null, 23 | "metadata": {}, 24 | "outputs": [], 25 | "source": [ 26 | "import numpy as np\n", 27 | "import matplotlib.pyplot as plt\n", 28 | "%matplotlib inline\n", 29 | "\n", 30 | "np.random.seed(123)\n", 31 | "lo = np.random.randint(-5, -1, 6)\n", 32 | "mid = np.random.randint(0, 3, 38)\n", 33 | "hi = np.random.randint(4, 6, 6)\n", 34 | "sample = np.append(lo,np.append(mid, hi))\n", 35 | "print(\"Min:\" + str(sample.min()))\n", 36 | "print(\"Max:\" + str(sample.max()))\n", 37 | "print(\"Mean:\" + str(sample.mean()))\n", 38 | "\n", 39 | "plt.hist(sample)\n", 40 | "plt.show()" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "A question we might immediately ask is: \"how do students tend to like the class\"? In this case, possible ratings were between -5 and 5, with a \"neutral\" score of 0. In other words, if our average score is above zero, then students tend to enjoy the course. \n", 48 | "\n", 49 | "In the sample above, the mean score is above 0 (in other words, people liked the class in this data). If you had actually run this course and saw this data, it might lead you to believe that the overall mean rating for this class (i.e., not just the sample) is likely to be positive. \n", 50 | "\n", 51 | "There is an important point to be made, though: this is just a sample, and you want to make a statement not just about your sample but the whole population from which it came. In other words, you want to know how the class was received overall, but you only have access to a limited set of data. This often the case when analyzing data. \n", 52 | "\n", 53 | "So, how can you test your belief that your positive looking *sample* reflects the fact that the course does tend to get good evaluations, that your *population* mean (not just your sample mean) is positive?\n", 54 | "\n", 55 | "We start by defining two hypotheses:\n", 56 | "\n", 57 | "* The *null* hypothesis (**H0**) is that the population mean for all of the ratings is *not* higher than 0, and the fact that our sample mean is higher than this is due to random chance in our sample selection. \n", 58 | "* The *alternative* hypothesis (**H1**) is that the population mean is actually higher than 0, and the fact that our sample mean is higher than this means that our sample correctly detected this trend. \n", 59 | "\n", 60 | "You can write these as mutually exclusive expressions like this:\n", 61 | "\n", 62 | "\\begin{equation}H_{0}: \\mu \\le 0 \\\\ H_{1}: \\mu > 0 \\end{equation}\n", 63 | "\n", 64 | "So how do we test these hypotheses? Because they are mutually exclusive, if we can show the null is probably not true, then we are safe to reject it and conclude that people really do like our online course. But how do we do that?\n", 65 | "\n", 66 | "Well, if the *null* hypothesis is true, the sampling distribution for ratings with a sample size of 50 will be a normal distribution with a mean of 0. Run the following code to visualize this, with the mean of 0 shown as a yellow dashed line.\n", 67 | "\n", 68 | "*(The code just generates a normal distribution with a mean of 0 and a standard deviation that makes it approximate a sampling distribution of 50 random means between -5 and 5 - don't worry too much about the actual values, it's just to illustrate the key points!)*" 69 | ] 70 | }, 71 | { 72 | "cell_type": "code", 73 | "execution_count": null, 74 | "metadata": { 75 | "scrolled": false 76 | }, 77 | "outputs": [], 78 | "source": [ 79 | "import numpy as np\n", 80 | "import matplotlib.pyplot as plt\n", 81 | "%matplotlib inline\n", 82 | "\n", 83 | "pop = np.random.normal(0, 1.15, 100000)\n", 84 | "plt.hist(pop, bins=100)\n", 85 | "plt.axvline(pop.mean(), color='yellow', linestyle='dashed', linewidth=2)\n", 86 | "plt.show()" 87 | ] 88 | }, 89 | { 90 | "cell_type": "markdown", 91 | "metadata": {}, 92 | "source": [ 93 | "This illustrates all the *sample* results you could get if the null hypothesis was true (that is, the rating population mean is actually 0). Note that if the null hypothesis is true, it's still *possible* to get a sample with a mean ranging from just over -5 to just under 5. The question is how *probable* is it to get a sample with a mean as high we did for our 50-rating sample under the null hypothesis? And how improbable would it *need* to be for us to conclude that the null is, in fact, a poor explanation for our data? \n", 94 | "\n", 95 | "Well, we measure distance from the mean in standard deviations, so we need to find out how many standard deviations above the null-hypothesized population mean of 0 our sample mean is, and measure the area under the distribution curve from this point on - that will give us the probability of observing a mean that is *at least* as high as our sample mean. We call the number of standard deviations above the mean where our sample mean is found the *test statistic* (or sometimes just *t-statistic*), and we call the area under the curve from this point (representing the probability of observing a sample mean this high or greater) the *p-value*.\n", 96 | "\n", 97 | "So the p-value tells us how probable our sample mean is when the null is true, but we need to set a threshold under which we consider this to be too improbable to be explained by random chance alone. We call this threshold our *critical value*, and we usually indicate it using the Greek letter alpha (**α**). You can use any value you think is appropriate for **α** - commonly a value of 0.05 (5%) is used, but there's nothing special about this value.\n", 98 | "\n", 99 | "We calculate the t-statistic by performing a statistical test. Technically, when the standard deviation of the population is known, we call it a *z-test* (because a *normal* distribution is often called a *z-distribution* and we measure variance from the mean in multiples of standard deviation known as *z-scores*). When the standard deviation of the population is not known, the test is referred to as a *t-test* and based on an adjusted version of a normal distribution called a *student's t distribution*, in which the distribution is \"flattened\" to allow for more sample variation depending on the sample size. Generally, with a sample size of 30 or more, a t-test is approximately equivalent to a z-test.\n", 100 | "\n", 101 | "Specifically, in this case we're performing a *single sample* test (we're comparing the mean from a single sample of ratings against the hypothesized population mean), and it's a *one-tailed* test (we're checking to see if the sample mean is *greater than* the null-hypothesized population mean - in other words, in the *right* tail of the distribution).\n", 102 | "\n", 103 | "The general formula for one-tailed, single-sample t-test is:\n", 104 | "\n", 105 | "\\begin{equation}t = \\frac{\\bar{x} - \\mu}{s \\div \\sqrt{n}} \\end{equation}\n", 106 | "\n", 107 | "In this formula, **x̄** is the sample mean, **μ** is the population mean, **s** is the standard deviation, and **n** is the sample size. You can think of the numerator of this equation (the expression at the top of the fraction) as a *signal*, and the denominator (the expression at the bottom of the fraction) as being *noise*. The signal measures the difference between the statistic and the null-hypothesized value, and the noise represents the random variance in the data in the form of standard deviation (or standard error). The t-statistic is the ratio of signal to noise, and measures the number of standard errors between the null-hypothesized value and the observed sample mean. A large value tells you that your \"result\" or \"signal\" was much larger than you would typically expect by chance.\n", 108 | "\n", 109 | "Fortunately, most programming languages used for statistical analysis include functions to perform a t-test, so you rarely need to manually calculate the results using the formula.\n", 110 | "\n", 111 | "Run the code below to run a single-sample t-test comparing our sample mean for ratings to a hypothesized population mean of 0, and visualize the resulting t-statistic on the normal distribution for the null hypothesis.\n" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "from scipy import stats\n", 121 | "import numpy as np\n", 122 | "import matplotlib.pyplot as plt\n", 123 | "%matplotlib inline\n", 124 | "\n", 125 | "# T-Test\n", 126 | "t,p = stats.ttest_1samp(sample, 0)\n", 127 | "# ttest_1samp is 2-tailed, so half the resulting p-value to get a 1-tailed p-value\n", 128 | "p1 = '%f' % (p/2)\n", 129 | "print (\"t-statistic:\" + str(t))\n", 130 | "print(\"p-value:\" + str(p1))\n", 131 | "\n", 132 | "# calculate a 90% confidence interval. 10% of the probability is outside this, 5% in each tail\n", 133 | "ci = stats.norm.interval(0.90, 0, 1.15)\n", 134 | "plt.hist(pop, bins=100)\n", 135 | "# show the hypothesized population mean\n", 136 | "plt.axvline(pop.mean(), color='yellow', linestyle='dashed', linewidth=2)\n", 137 | "# show the right-tail confidence interval threshold - 5% of propbability is under the curve to the right of this.\n", 138 | "plt.axvline(ci[1], color='red', linestyle='dashed', linewidth=2)\n", 139 | "# show the t-statistic - the p-value is the area under the curve to the right of this\n", 140 | "plt.axvline(pop.mean() + t*pop.std(), color='magenta', linestyle='dashed', linewidth=2)\n", 141 | "plt.show()" 142 | ] 143 | }, 144 | { 145 | "cell_type": "markdown", 146 | "metadata": {}, 147 | "source": [ 148 | "In the plot produced by the code above, the yellow line shows the population mean for the null hypothesis. The area under the curve to the right of the red line represents the critical value of 0.05 (or 5%). The magenta line indicates how much higher the sample mean is compared to the hypothesized population mean. This is calculated as the t-statistic (which is printed above the plot) multiplied by the standard deviation. The area under the curve to the right of this encapsulates the p-value calculated by the test (which is also printed above the plot).\n", 149 | "\n", 150 | "So what should we conclude from these results?\n", 151 | "\n", 152 | "Well, if the p-value is smaller than our critical value of 0.05, that means that under the null hypothesis, the probability of observing a sample mean as high as we did by random chance is low. That's a good sign for us, because it means that our sample is unlikely under the null, and therefore the null is a poor explanation for the data. We can safely *reject* the null hypothesis in favor of the alternative hypothesis - there's enough evidence to suggest that the population mean for our class ratings is greater than 0.\n", 153 | "\n", 154 | "Conversely, if the p-value is greater than the critical value, we *fail to reject the null hypothesis* and conclude that the mean rating is not greater than 0. Note that we never actually *accept* the null hypothesis, we just conclude that there isn't enough evidence to reject it!" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "## Two-Tailed Tests\n", 162 | "The previous test was an example of a one-tailed test in which the p-value represents the area under one tail of the distribution curve. In this case, the area in question is under the right tail because the alternative hypothesis we were trying to show was that the true population mean is *greater than* the mean of the null hypothesis scenario.\n", 163 | "\n", 164 | "Suppose we restated our hypotheses like this:\n", 165 | "* The *null* hypothesis (**H0**) is that the population mean for all of the ratings is 0, and the fact that our sample mean is higher or lower than this can be explained by random chance in our sample selection.\n", 166 | "* The *alternative* hypothesis (**H1**) is that the population mean is not equal to 0.\n", 167 | "\n", 168 | "We can write these as mutually exclusive expressions like this:\n", 169 | "\n", 170 | "\\begin{equation}H_{0}: \\mu = 0 \\\\ H_{1}: \\mu \\neq 0 \\end{equation}\n", 171 | "\n", 172 | "Why would we do this? Well, in the test we performed earlier, we could only reject the null hypothesis if we had really *positive* ratings, but what if our sample data looked really *negative*? It would be a mistake to turn around and run a one-tailed test the other way, for negative ratings. Instead, we conduct a test designed for such a question: a two-tailed test.\n", 173 | "\n", 174 | "In a two-tailed test, we are willing to reject the null hypothesis if the result is significantly *greater* or *lower* than the null hypothesis. Our critical value (5%) is therefore split in two: the top 2.5% of the curve and the bottom 2.5% of the curve. As long as our test statistic is in that region, we are in the extreme 5% of values (p < .05) and we reject the null hypothesis. In other words, our p-value now needs to be below .025, but it can be in either tail of the distribution. For convenience, we usually \"double\" the p-value in a two-tailed test so that we don't have to remember this rule and still compare against .05 (this is known as a \"two-tailed p-value\"). In fact, it is assumed this has been done in all statistical analyses unless stated otherwise. \n", 175 | "\n", 176 | "The following code shows the results of a two-tailed, single sample test of our class ratings. Note that the ***ttest_1samp*** function in the ***stats*** library returns a 2-tailed p-value by default (which is why we halved it in the previous example).\n" 177 | ] 178 | }, 179 | { 180 | "cell_type": "code", 181 | "execution_count": null, 182 | "metadata": {}, 183 | "outputs": [], 184 | "source": [ 185 | "from scipy import stats\n", 186 | "import numpy as np\n", 187 | "import matplotlib.pyplot as plt\n", 188 | "%matplotlib inline\n", 189 | "\n", 190 | "# T-Test\n", 191 | "t,p = stats.ttest_1samp(sample, 0)\n", 192 | "print (\"t-statistic:\" + str(t))\n", 193 | "# ttest_1samp is 2-tailed\n", 194 | "print(\"p-value:\" + '%f' % p)\n", 195 | "# calculate a 95% confidence interval. 50% of the probability is outside this, 2.5% in each tail\n", 196 | "ci = stats.norm.interval(0.95, 0, 1.15)\n", 197 | "plt.hist(pop, bins=100)\n", 198 | "# show the hypothesized population mean\n", 199 | "plt.axvline(pop.mean(), color='yellow', linestyle='dashed', linewidth=2)\n", 200 | "# show the confidence interval thresholds - 5% of propbability is under the curve outside these.\n", 201 | "plt.axvline(ci[0], color='red', linestyle='dashed', linewidth=2)\n", 202 | "plt.axvline(ci[1], color='red', linestyle='dashed', linewidth=2)\n", 203 | "# show the t-statistic thresholds - the p-value is the area under the curve outside these\n", 204 | "plt.axvline(pop.mean() - t*pop.std(), color='magenta', linestyle='dashed', linewidth=2)\n", 205 | "plt.axvline(pop.mean() + t*pop.std(), color='magenta', linestyle='dashed', linewidth=2)\n", 206 | "plt.show()" 207 | ] 208 | }, 209 | { 210 | "cell_type": "markdown", 211 | "metadata": {}, 212 | "source": [ 213 | "Here we see that our 2-tailed p-value was clearly less than 0.05; so We reject the null hypothesis.\n", 214 | "\n", 215 | "You may note that doubling the p-value in a two-tailed test makes it harder to reject the null. This is true; we require more evidence because we are asking a more complicated question. " 216 | ] 217 | }, 218 | { 219 | "cell_type": "markdown", 220 | "metadata": {}, 221 | "source": [ 222 | "\n", 223 | "\n", 224 | "## Two-Sample Tests\n", 225 | "In both of the previous examples, we compared a statistic from a single data sample to a null-hypothesized population parameter. Sometimes you might want to compare two samples against one another.\n", 226 | "\n", 227 | "For example, let's suppose that some of the students who took the statistics course had previously studied mathematics, while other students had no previous math experience. You might hypothesize that the grades of students who had previously studied math are significantly higher than the grades of students who had not.\n", 228 | "\n", 229 | "* The *null* hypothesis (**H0**) is that the population mean grade for students with previous math studies is not greater than the population mean grade for students without any math experience, and the fact that our sample mean for math students is higher than our sample mean for non-math students can be explained by random chance in our sample selection.\n", 230 | "* The *alternative* hypothesis (**H1**) is that the population mean grade for students with previous math studies is greater than the population mean grade for students without any math experience.\n", 231 | "\n", 232 | "We can write these as mutually exclusive expressions like this:\n", 233 | "\n", 234 | "\\begin{equation}H_{0}: \\mu_{1} \\le \\mu_{2} \\\\ H_{1}: \\mu_{1} > \\mu_{2} \\end{equation}\n", 235 | "\n", 236 | "This is a one-sided test that compares two samples. To perform this test, we'll take two samples. One sample contains 100 grades for students who have previously studied math, and the other sample contains 100 grades for students with no math experience.\n", 237 | "\n", 238 | "We won't go into the test-statistic formula here, but it essentially the same as the one above, adapted to include information from both samples. We can easily test this in most software packages using the command for an \"independent samples\" t-test:\n" 239 | ] 240 | }, 241 | { 242 | "cell_type": "code", 243 | "execution_count": null, 244 | "metadata": {}, 245 | "outputs": [], 246 | "source": [ 247 | "import numpy as np\n", 248 | "import matplotlib.pyplot as plt\n", 249 | "from scipy import stats\n", 250 | "%matplotlib inline\n", 251 | "\n", 252 | "np.random.seed(123)\n", 253 | "nonMath = np.random.normal(66.0, 1.5, 100)\n", 254 | "math = np.random.normal(66.55, 1.5, 100)\n", 255 | "print(\"non-math sample mean:\" + str(nonMath.mean()))\n", 256 | "print(\"math sample mean:\" + str(math.mean()))\n", 257 | "\n", 258 | "# Independent T-Test\n", 259 | "t,p = stats.ttest_ind(math, nonMath)\n", 260 | "# ttest_ind is 2-tailed, so half the resulting p-value to get a 1-tailed p-value\n", 261 | "p1 = '%f' % (p/2)\n", 262 | "print(\"t-statistic:\" + str(t))\n", 263 | "print(\"p-value:\" + str(p1))\n", 264 | "\n", 265 | "pop = np.random.normal(nonMath.mean(), nonMath.std(), 100000)\n", 266 | "# calculate a 90% confidence interval. 10% of the probability is outside this, 5% in each tail\n", 267 | "ci = stats.norm.interval(0.90, nonMath.mean(), nonMath.std())\n", 268 | "plt.hist(pop, bins=100)\n", 269 | "# show the hypothesized population mean\n", 270 | "plt.axvline(pop.mean(), color='yellow', linestyle='dashed', linewidth=2)\n", 271 | "# show the right-tail confidence interval threshold - 5% of propbability is under the curve to the right of this.\n", 272 | "plt.axvline(ci[1], color='red', linestyle='dashed', linewidth=2)\n", 273 | "# show the t-statistic - the p-value is the area under the curve to the right of this\n", 274 | "plt.axvline(pop.mean() + t*pop.std(), color='magenta', linestyle='dashed', linewidth=2)\n", 275 | "plt.show()" 276 | ] 277 | }, 278 | { 279 | "cell_type": "markdown", 280 | "metadata": {}, 281 | "source": [ 282 | "You can interpret the results of this test the same way as for the previous single-sample, one-tailed test. If the p-value (the area under the curve to the right of the magenta line) is smaller than our critical value (**α**) of 0.05 (the area under the curve to the right of the red line), then the difference can't be explained by chance alone; so we can reject the null hypothesis and conclude that students with previous math experience perform better on average than students without.\n", 283 | "\n", 284 | "Alternatively, you could always compare two groups and *not* specify a direction (i.e., two-tailed). If you did this, as above, you could simply double the p-value (now .001), and you would see you could still reject the null hypothesis." 285 | ] 286 | }, 287 | { 288 | "cell_type": "markdown", 289 | "metadata": {}, 290 | "source": [ 291 | "## Paired Tests\n", 292 | "In the two-sample test we conduced previously, the samples were independent; in other words there was no relatioship between the observations in the first sample and the observations in the second sample. Sometimes you might want to compare statistical differences between related observations before and after some change that you believe might influence the data.\n", 293 | "\n", 294 | "For example, suppose our students took a mid-term exam, and later took and end-of-term exam. You might hypothesise that the students will improve their grades in the end-of-term exam, after they've undertaken additional study. We could test for a general improvement on average across all students with a two-sample independent test, but a more appropriate test would be to compare the two test scores for each individual student.\n", 295 | "\n", 296 | "To accomplish this, we need to create two samples; one for scores in the mid-term, exam, the other for scores in the end-of-term exam. Then we need to compare the samples in such a way that each pair of observations for the same student are compared to one another. \n", 297 | "\n", 298 | "This is known as a paired-samples t-test or a dependent-samples t-test. Technically, it tests whether the *changes* tend to be in the positive or negative direction." 299 | ] 300 | }, 301 | { 302 | "cell_type": "code", 303 | "execution_count": null, 304 | "metadata": {}, 305 | "outputs": [], 306 | "source": [ 307 | "import numpy as np\n", 308 | "import matplotlib.pyplot as plt\n", 309 | "from scipy import stats\n", 310 | "%matplotlib inline\n", 311 | "\n", 312 | "np.random.seed(123)\n", 313 | "midTerm = np.random.normal(59.45, 1.5, 100)\n", 314 | "endTerm = np.random.normal(60.05, 1.5, 100)\n", 315 | "\n", 316 | "# Paired (related) test\n", 317 | "t,p = stats.ttest_rel(endTerm, midTerm)\n", 318 | "# ttest_rel is 2-tailed, so half the resulting p-value to get a 1-tailed p-value\n", 319 | "p1 = '%f' % (p/2)\n", 320 | "print(\"t-statistic:\" + str(t))\n", 321 | "print(\"p-value:\" + str(p1))\n", 322 | "\n", 323 | "pop = np.random.normal(midTerm.mean(), midTerm.std(), 100000)\n", 324 | "# calculate a 90% confidence interval. 10% of the probability is outside this, 5% in each tail\n", 325 | "ci = stats.norm.interval(0.90, midTerm.mean(), midTerm.std())\n", 326 | "plt.hist(pop, bins=100)\n", 327 | "# show the hypothesized population mean\n", 328 | "plt.axvline(pop.mean(), color='yellow', linestyle='dashed', linewidth=2)\n", 329 | "# show the right-tail confidence interval threshold - 5% of propbability is under the curve to the right of this.\n", 330 | "plt.axvline(ci[1], color='red', linestyle='dashed', linewidth=2)\n", 331 | "# show the t-statistic - the p-value is the area under the curve to the right of this\n", 332 | "plt.axvline(pop.mean() + t*pop.std(), color='magenta', linestyle='dashed', linewidth=2)\n", 333 | "plt.show()" 334 | ] 335 | }, 336 | { 337 | "cell_type": "markdown", 338 | "metadata": {}, 339 | "source": [ 340 | "In our sample, we see that scores did in fact improve, so we can we reject the null hypothesis." 341 | ] 342 | } 343 | ], 344 | "metadata": { 345 | "kernelspec": { 346 | "display_name": "Python 3", 347 | "language": "python", 348 | "name": "python3" 349 | }, 350 | "language_info": { 351 | "codemirror_mode": { 352 | "name": "ipython", 353 | "version": 3 354 | }, 355 | "file_extension": ".py", 356 | "mimetype": "text/x-python", 357 | "name": "python", 358 | "nbconvert_exporter": "python", 359 | "pygments_lexer": "ipython3", 360 | "version": "3.5.4" 361 | } 362 | }, 363 | "nbformat": 4, 364 | "nbformat_minor": 2 365 | } 366 | -------------------------------------------------------------------------------- /Vector and Matrices by Hiren/03-01-Vectors.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Vectors\n", 8 | "Vectors, and vector spaces, are fundamental to *linear algebra*, and they're used in many machine learning models. Vectors describe spatial lines and planes, enabling you to perform calculations that explore relationships in multi-dimensional space.\n", 9 | "\n", 10 | "## What is a Vector\n", 11 | "At its simplest, a vector is a numeric element that has both *magnitude* and *direction*. The magnitude represents a distance (for example, \"2 miles\") and the direction indicates which way the vector is headed (for example, \"East\"). Vectors are defined by an n-dimensional coordinate that describe a point in space that can be connected by a line from an arbitrary origin.\n", 12 | "\n", 13 | "That all seems a bit complicated, so let's start with a simple, two-dimensional example. In this case, we'll have a vector that is defined by a point in a two-dimensional plane: A two dimensional coordinate consists of an *x* and a *y* value, and in this case we'll use **2** for *x* and **1** for *y*.\n", 14 | "\n", 15 | "Our vector can be written as **v**=(2,1), but more formally we would use the following notation, in which the dimensional coordinate values for the vector are shown as a matrix:\n", 16 | "\\begin{equation}\\vec{v} = \\begin{bmatrix}2 \\\\ 1 \\end{bmatrix}\\end{equation}\n", 17 | "\n", 18 | "So what exactly does that mean? Well, the coordinate is two-dimensional, and describes the movements required to get to the end point (of *head*) of the vector - in this case, we need to move 2 units in the *x* dimension, and 1 unit in the *y* dimension. Note that we don't specify a starting point for the vector - we're simply describing a destination coordinate that encapsulate the magnitide and direction of the vector. Think about it as the directions you need to follow to get to *there* from *here*, without specifying where *here* actually is!\n", 19 | "\n", 20 | "It can help to visualize the vector, and with a two-dimensional vector, that's pretty straightforward. We just define a two-dimensional plane, choose a starting point, and plot the coordinate described by the vector relative to the starting point.\n", 21 | "\n", 22 | "Run the code in the following cell to visualize the vector **v** (which remember is described by the coordinate (2,1))." 23 | ] 24 | }, 25 | { 26 | "cell_type": "code", 27 | "execution_count": null, 28 | "metadata": { 29 | "collapsed": true 30 | }, 31 | "outputs": [], 32 | "source": [ 33 | "%matplotlib inline\n", 34 | "\n", 35 | "import numpy as np\n", 36 | "import matplotlib.pyplot as plt\n", 37 | "\n", 38 | "# We'll use a numpy array for our vector\n", 39 | "v = np.array([2,1])\n", 40 | "\n", 41 | "# and we'll use a quiver plot to visualize it.\n", 42 | "origin = [0], [0]\n", 43 | "plt.axis('equal')\n", 44 | "plt.grid()\n", 45 | "plt.ticklabel_format(style='sci', axis='both', scilimits=(0,0))\n", 46 | "plt.quiver(*origin, *v, scale=10, color='r')\n", 47 | "plt.show()" 48 | ] 49 | }, 50 | { 51 | "cell_type": "markdown", 52 | "metadata": {}, 53 | "source": [ 54 | "Note that we can use a numpy array to define the vector in Python; so to create our (2,1) vector, we simply create a numpy array with the elements [2,1]. We've then used a quiver plot to visualize the vector, using the point 0,0 as the starting point (or *origin*). Our vector of (2,1) is shown as an arrow that starts at 0,0 and moves 2 units along the *x* axis (to the right) and 1 unit along the *y* axis (up)." 55 | ] 56 | }, 57 | { 58 | "cell_type": "markdown", 59 | "metadata": {}, 60 | "source": [ 61 | "## Calculating Vector Magnitude and Direction\n", 62 | "We tend to work with vectors by expressing their components as *cartesian coordinates*; that is, *x* and *y* (and other dimension) values that define the number of units travelled along each dimension. So the coordinates of our (2,1) vector indicate that we must travel 2 units along the *x* axis, and *1* unit along the *y* axis.\n", 63 | "\n", 64 | "However, you can also work with verctors in terms of their *polar coordinates*; that is coordinates that describe the magnitude and direction of the vector. The magnitude is the overall distance of the vector from tail to head, and the direction is the angle at which the vector is oriented.\n", 65 | "\n", 66 | "### Calculating Magnitude\n", 67 | "Calculating the magnitude of the vector from its cartesian coordinates requires measuring the distance between the arbitrary starting point and the vector head point. For a two-dimensional vector, we're actually just calculating the length of the hypotenuse in a right-angled triangle - so we could simply invoke Pythagorean theorum and calculate the square root of the sum of the squares of it's components, like this:\n", 68 | "\n", 69 | "\\begin{equation}\\|\\vec{v}\\| = \\sqrt{v_{1}\\;^{2} + v_{2}\\;^{2}}\\end{equation}\n", 70 | "\n", 71 | "The notation for a vector's magnitude is to surround the vector name with vertical bars - you can use single bars (for example, |**v**|) or double bars (||**v**||). Double-bars are often used to avoid confusion with absolute values. Note that the components of the vector are indicated by subscript indices (v1, v2,...v*n*),\n", 72 | "\n", 73 | "In this case, the vector **v** has two components with values **2** and **1**, so our magnitude calculation is:\n", 74 | "\n", 75 | "\\begin{equation}\\|\\vec{v}\\| = \\sqrt{2^{2} + 1^{2}}\\end{equation}\n", 76 | "\n", 77 | "Which is:\n", 78 | "\n", 79 | "\\begin{equation}\\|\\vec{v}\\| = \\sqrt{4 + 1}\\end{equation}\n", 80 | "\n", 81 | "So:\n", 82 | "\n", 83 | "\\begin{equation}\\|\\vec{v}\\| = \\sqrt{5} \\approx 2.24\\end{equation}\n", 84 | "\n", 85 | "You can run the following Python code to get a more precise result (note that the elements of a numpy array are zero-based)" 86 | ] 87 | }, 88 | { 89 | "cell_type": "code", 90 | "execution_count": null, 91 | "metadata": { 92 | "collapsed": true 93 | }, 94 | "outputs": [], 95 | "source": [ 96 | "import math\n", 97 | "\n", 98 | "vMag = math.sqrt(v[0]**2 + v[1]**2)\n", 99 | "print (vMag)" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "This calculation works for vectors of any dimensionality - you just take the square root of the sum of the squared components:\n", 107 | "\n", 108 | "\\begin{equation}\\|\\vec{v}\\| = \\sqrt{v_{1}\\;^{2} + v_{2}\\;^{2} ... + v_{n}\\;^{2}}\\end{equation}\n", 109 | "\n", 110 | "In Python, *numpy* provides a linear algebra library named **linalg** that makes it easier to work with vectors - you can use the **norm** function in the following code to calculate the magnitude of a vector:" 111 | ] 112 | }, 113 | { 114 | "cell_type": "code", 115 | "execution_count": null, 116 | "metadata": { 117 | "collapsed": true 118 | }, 119 | "outputs": [], 120 | "source": [ 121 | "import numpy as np\n", 122 | "\n", 123 | "vMag = np.linalg.norm(v)\n", 124 | "print (vMag)" 125 | ] 126 | }, 127 | { 128 | "cell_type": "markdown", 129 | "metadata": {}, 130 | "source": [ 131 | "### Calculating Direction\n", 132 | "To calculate the direction, or *amplitude*, of a vector from its cartesian coordinates, you must employ a little trigonometry. We can get the angle of the vector by calculating the *inverse tangent*; sometimes known as the *arctan* (the *tangent* calculates an angle as a ratio - the inverse tangent, or **tan-1**, expresses this in degrees).\n", 133 | "\n", 134 | "In any right-angled triangle, the tangent is calculated as the *opposite* over the *adjacent*. In a two dimensional vector, this is the *y* value over the *x* value, so for our **v** vector (2,1):\n", 135 | "\n", 136 | "\\begin{equation}tan(\\theta) = \\frac{1}{2}\\end{equation}\n", 137 | "\n", 138 | "This produces the result ***0.5***, from which we can use a calculator to calculate the inverse tangent to get the angle in degrees:\n", 139 | "\n", 140 | "\\begin{equation}\\theta = tan^{-1} (0.5) \\approx 26.57^{o}\\end{equation}\n", 141 | "\n", 142 | "Note that the direction angle is indicated as ***θ***.\n", 143 | "\n", 144 | "Run the following Python code to confirm this:" 145 | ] 146 | }, 147 | { 148 | "cell_type": "code", 149 | "execution_count": null, 150 | "metadata": { 151 | "collapsed": true 152 | }, 153 | "outputs": [], 154 | "source": [ 155 | "import math\n", 156 | "import numpy as np\n", 157 | "\n", 158 | "v = np.array([2,1])\n", 159 | "vTan = v[1] / v[0]\n", 160 | "print ('tan = ' + str(vTan))\n", 161 | "vAtan = math.atan(vTan)\n", 162 | "# atan returns the angle in radians, so convert to degrees\n", 163 | "print('inverse-tan = ' + str(math.degrees(vAtan)))" 164 | ] 165 | }, 166 | { 167 | "cell_type": "markdown", 168 | "metadata": {}, 169 | "source": [ 170 | "There is an added complication however, because if the value for *x* or *y* (or both) is negative, the orientation of the vector is not standard, and a calculator can give you the wrong tan-1 value. To ensure you get the correct direction for your vector, use the following rules:\n", 171 | "- Both *x* and *y* are positive: Use the tan-1 value.\n", 172 | "- *x* is negative, *y* is positive: Add 180 to the tan-1 value.\n", 173 | "- Both *x* and *y* are negative: Add 180 to the tan-1 value.\n", 174 | "- *x* is positive, *y* is negative: Add 360 to the tan-1 value.\n", 175 | "\n", 176 | "To understand why we need to do this, think of it this way. A vector can be pointing in any direction through a 360 degree arc. Let's break that circle into four quadrants with the x and y axis through the center. Angles can be measured from the x axis in both the positive (counter-clockwise) and negative (clockwise) directions. We'll number the quadrants in the positive (counter-clockwise) direction (which is how we measure the *positive* angle) like this:\n", 177 | "\n", 178 | " \n", 179 | "\n", 180 | " 2 | 1\n", 181 | " - o -\n", 182 | " 3 | 4\n", 183 | "\n", 184 | "\n", 185 | "OK, let's look at 4 example vectors\n", 186 | "\n", 187 | " 1. Vector [2,4] has positive values for both x and y. The line for this vector travels through the point 0,0 from quadrant 3 to quadrant 1. Tan-1 of 4/2 is around 63.4 degrees, which is the positive angle from the x axis to the vector line - so this is the direction of the vector.\n", 188 | " 2. Vector [-2,4] has a negative x and positive y. The line for this vector travels through point 0,0 from quadrant 4 to quadrant 2. Tan-1 of 4/-2 is around -64.4 degrees, which is the *negative* angle from x to the vector line; but in the wrong direction (as if the vector was travelling from quadrant 2 towards quadrant 4). So we need the opposite direction, which we get by adding 180.\n", 189 | " 3. Vector [-2,-4] has negative x and y. The line for the vector travels through 0,0 from quadrant 1 to quadrant 3. Tan-1 of -4/-2 is around 63.4 degrees, which is the angle between the x axis and the line, but again in the opposite direction, from quadrant 3 to quadrant 1; we need to go a further 180 degrees to reflect the correct direction.\n", 190 | " 4. Vector [2,-4] has positive x and negative y. It travels through 0,0 from quadrant 2 to quadrant 4. Tan-1 of -4/2 is around -64.4 degrees, which is the *negative* angle from the x axis to the vector line. Technically it's correct, the line is travelleing down and to the right at an angle of -63.4 degrees; but we want to express the *positive* (counter-clockwise) angle, so we add 360.\n", 191 | "\n", 192 | "\n", 193 | "In the previous Python code, we used the *math.**atan*** function to calculate the inverse tangent from a numeric tangent. The *numpy* library includes a similar ***arctan*** function. When working with numpy arrays, you can also use the *numpy.**arctan2*** function to return the inverse tangent of an array-based vector in *radians*, and you can use the *numpy.**degrees*** function to convert this to degrees. The ***arctan2*** function automatically makes the necessary adjustment for negative *x* and *y* values." 194 | ] 195 | }, 196 | { 197 | "cell_type": "code", 198 | "execution_count": null, 199 | "metadata": { 200 | "collapsed": true 201 | }, 202 | "outputs": [], 203 | "source": [ 204 | "import numpy as np\n", 205 | "\n", 206 | "v = np.array([2,1])\n", 207 | "print ('v: ' + str(np.degrees(np.arctan2(v[1], v[0]))))\n", 208 | "\n", 209 | "s = np.array([-3,2])\n", 210 | "print ('s: ' + str(np.degrees(np.arctan2(s[1], s[0]))))" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": {}, 216 | "source": [ 217 | "## Vector Addition\n", 218 | "So far, we've worked with one vector at a time. What happens when you need to add two vectors.\n", 219 | "\n", 220 | "Let's take a look at an example, we already have a vector named **v**, as defined here:\n", 221 | "\\begin{equation}\\vec{v} = \\begin{bmatrix}2 \\\\ 1 \\end{bmatrix}\\end{equation}\n", 222 | "Now let's create a second vector, and called **s** like this:\n", 223 | "\\begin{equation}\\vec{s} = \\begin{bmatrix}-3 \\\\ 2 \\end{bmatrix}\\end{equation}\n", 224 | "\n", 225 | "Run the cell below to create **s** and plot it together with **v**:" 226 | ] 227 | }, 228 | { 229 | "cell_type": "code", 230 | "execution_count": null, 231 | "metadata": { 232 | "collapsed": true 233 | }, 234 | "outputs": [], 235 | "source": [ 236 | "import math\n", 237 | "import numpy as np\n", 238 | "import matplotlib.pyplot as plt\n", 239 | "%matplotlib inline\n", 240 | "\n", 241 | "v = np.array([2,1])\n", 242 | "s = np.array([-3,2])\n", 243 | "print (s)\n", 244 | "\n", 245 | "# Plot v and s\n", 246 | "vecs = np.array([v,s])\n", 247 | "origin = [0], [0]\n", 248 | "plt.axis('equal')\n", 249 | "plt.grid()\n", 250 | "plt.ticklabel_format(style='sci', axis='both', scilimits=(0,0))\n", 251 | "plt.quiver(*origin, vecs[:,0], vecs[:,1], color=['r', 'b'], scale=10)\n", 252 | "plt.show()" 253 | ] 254 | }, 255 | { 256 | "cell_type": "markdown", 257 | "metadata": {}, 258 | "source": [ 259 | "You can see in the plot that the two vectors have different directions and magnitudes. So what happens when we add them together?\n", 260 | "\n", 261 | "Here's the formula:\n", 262 | "\\begin{equation}\\vec{z} = \\vec{v}+\\vec{s}\\end{equation}\n", 263 | "\n", 264 | "In terms of our vector matrices, this looks like this:\n", 265 | "\\begin{equation}\\vec{z} = \\begin{bmatrix}2 \\\\ 1 \\end{bmatrix} + \\begin{bmatrix}-3 \\\\ 2 \\end{bmatrix}\\end{equation}\n", 266 | "\n", 267 | "Which gives the following result:\n", 268 | "\\begin{equation}\\vec{z} = \\begin{bmatrix}2 \\\\ 1 \\end{bmatrix} + \\begin{bmatrix}-3 \\\\ 2 \\end{bmatrix} = \\begin{bmatrix}-1 \\\\ 3 \\end{bmatrix}\\end{equation}\n", 269 | "\n", 270 | "Let's verify that Python gives the same result:" 271 | ] 272 | }, 273 | { 274 | "cell_type": "code", 275 | "execution_count": null, 276 | "metadata": { 277 | "collapsed": true 278 | }, 279 | "outputs": [], 280 | "source": [ 281 | "z = v + s\n", 282 | "print(z)" 283 | ] 284 | }, 285 | { 286 | "cell_type": "markdown", 287 | "metadata": {}, 288 | "source": [ 289 | "So what does that look like on our plot?" 290 | ] 291 | }, 292 | { 293 | "cell_type": "code", 294 | "execution_count": null, 295 | "metadata": { 296 | "collapsed": true 297 | }, 298 | "outputs": [], 299 | "source": [ 300 | "vecs = np.array([v,s,z])\n", 301 | "origin = [0], [0]\n", 302 | "plt.axis('equal')\n", 303 | "plt.grid()\n", 304 | "plt.ticklabel_format(style='sci', axis='both', scilimits=(0,0))\n", 305 | "plt.quiver(*origin, vecs[:,0], vecs[:,1], color=['r', 'b', 'g'], scale=10)\n", 306 | "plt.show()" 307 | ] 308 | }, 309 | { 310 | "cell_type": "markdown", 311 | "metadata": {}, 312 | "source": [ 313 | "So what's going on here?\n", 314 | "Well, we added the dimensions of **s** to the dimensions of **v** to describe a new vector **z**. Let's break that down:\n", 315 | "- The dimensions of **v** are (2,1), so from our starting point we move 2 units in the *x* dimension (across to the right) and 1 unit in the *y* dimension (up). In the plot, if you start at the (0,0) position, this is shown as the red arrow.\n", 316 | "- Then we're adding **s**, which has dimension values (-3, 2), so we move -3 units in the *x* dimension (across to the left, because it's a negative number) and then 2 units in the *y* dimension (up). On the plot, if you start at the head of the red arrow and make these moves, you'll end up at the head of the green arrow, which represents **z**.\n", 317 | "\n", 318 | "The same is true if you perform the addition operation the other way around and add **v** to **s**, the steps to create **s** are described by the blue arrow, and if you use that as the starting point for **v**, you'll end up at the head of the green arrow, which represents **z**.\n", 319 | "\n", 320 | "Note on the plot that if you simply moved the tail of the blue arrow so that it started at the head of red arrow, its head would end up in the same place as the head of the green arrow; and the same would be true if you moved tail of the red arrow to the head of the blue arrow." 321 | ] 322 | } 323 | ], 324 | "metadata": { 325 | "kernelspec": { 326 | "display_name": "Python 3.6", 327 | "language": "python", 328 | "name": "python36" 329 | }, 330 | "language_info": { 331 | "codemirror_mode": { 332 | "name": "ipython", 333 | "version": 3 334 | }, 335 | "file_extension": ".py", 336 | "mimetype": "text/x-python", 337 | "name": "python", 338 | "nbconvert_exporter": "python", 339 | "pygments_lexer": "ipython3", 340 | "version": "3.6.3" 341 | } 342 | }, 343 | "nbformat": 4, 344 | "nbformat_minor": 2 345 | } 346 | -------------------------------------------------------------------------------- /Vector and Matrices by Hiren/03-02-Vector Multiplication.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Vector Multiplication\n", 8 | "Vector multiplication can be performed in three ways:\n", 9 | "\n", 10 | "- Scalar Multiplication\n", 11 | "- Dot Product Multiplication\n", 12 | "- Cross Product Multiplication\n", 13 | "\n", 14 | "## Scalar Multiplication\n", 15 | "Let's start with *scalar* multiplication - in other words, multiplying a vector by a single numeric value.\n", 16 | "\n", 17 | "Suppose I want to multiply my vector by 2, which I could write like this:\n", 18 | "\n", 19 | "\\begin{equation} \\vec{w} = 2\\vec{v}\\end{equation}\n", 20 | "\n", 21 | "Note that the result of this calculation is a new vector named **w**. So how would we calculate this?\n", 22 | "Recall that **v** is defined like this:\n", 23 | "\n", 24 | "\\begin{equation}\\vec{v} = \\begin{bmatrix}2 \\\\ 1 \\end{bmatrix}\\end{equation}\n", 25 | "\n", 26 | "To calculate 2v, we simply need to apply the operation to each dimension value in the vector matrix, like this:\n", 27 | "\n", 28 | "\\begin{equation}\\vec{w} = \\begin{bmatrix}2 \\cdot 2 \\\\ 2 \\cdot 1 \\end{bmatrix}\\end{equation}\n", 29 | "\n", 30 | "Which gives us the following result:\n", 31 | "\n", 32 | "\\begin{equation}\\vec{w} = \\begin{bmatrix}2 \\cdot 2 \\\\ 2 \\cdot 1 \\end{bmatrix} = \\begin{bmatrix}4 \\\\ 2 \\end{bmatrix}\\end{equation}\n", 33 | "\n", 34 | "In Python, you can apply these sort of matrix operations directly to numpy arrays, so we can simply calculate **w** like this:" 35 | ] 36 | }, 37 | { 38 | "cell_type": "code", 39 | "execution_count": null, 40 | "metadata": {}, 41 | "outputs": [], 42 | "source": [ 43 | "%matplotlib inline\n", 44 | "\n", 45 | "import numpy as np\n", 46 | "import matplotlib.pyplot as plt\n", 47 | "import math\n", 48 | "\n", 49 | "v = np.array([2,1])\n", 50 | "\n", 51 | "w = 2 * v\n", 52 | "print(w)\n", 53 | "\n", 54 | "# Plot w\n", 55 | "origin = [0], [0]\n", 56 | "plt.grid()\n", 57 | "plt.ticklabel_format(style='sci', axis='both', scilimits=(0,0))\n", 58 | "plt.quiver(*origin, *w, scale=10)\n", 59 | "plt.show()" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "The same approach is taken for scalar division.\n", 67 | "\n", 68 | "Try it for yourself - use the cell below to calculate a new vector named **b** based on the following definition:\n", 69 | "\n", 70 | "\\begin{equation}\\vec{b} = \\frac{\\vec{v}}{2}\\end{equation}" 71 | ] 72 | }, 73 | { 74 | "cell_type": "code", 75 | "execution_count": null, 76 | "metadata": {}, 77 | "outputs": [], 78 | "source": [ 79 | "b = v / 2\n", 80 | "print(b)\n", 81 | "\n", 82 | "# Plot b\n", 83 | "origin = [0], [0]\n", 84 | "plt.axis('equal')\n", 85 | "plt.grid()\n", 86 | "plt.ticklabel_format(style='sci', axis='both', scilimits=(0,0))\n", 87 | "plt.quiver(*origin, *b, scale=10)\n", 88 | "plt.show()" 89 | ] 90 | }, 91 | { 92 | "cell_type": "markdown", 93 | "metadata": {}, 94 | "source": [ 95 | "## Dot Product Multiplication\n", 96 | "So we've seen how to multiply a vector by a scalar. How about multiplying two vectors together? There are actually two ways to do this depending on whether you want the result to be a *scalar product* (in other words, a number) or a *vector product* (a vector).\n", 97 | "\n", 98 | "To get a scalar product, we calculate the *dot product*. This takes a similar approach to multiplying a vector by a scalar, except that it multiplies each component pair of the vectors and sums the results. To indicate that we are performing a dot product operation, we use the • operator:\n", 99 | "\n", 100 | "\\begin{equation} \\vec{v} \\cdot \\vec{s} = (v_{1} \\cdot s_{1}) + (v_{2} \\cdot s_{2}) ... + \\; (v_{n} \\cdot s_{n})\\end{equation}\n", 101 | "\n", 102 | "So for our vectors **v** (2,1) and **s** (-3,2), our calculation looks like this:\n", 103 | "\n", 104 | "\\begin{equation} \\vec{v} \\cdot \\vec{s} = (2 \\cdot -3) + (1 \\cdot 2) = -6 + 2 = -4\\end{equation}\n", 105 | "\n", 106 | "So the dot product, or scalar product, of **v** • **s** is **-4**.\n", 107 | "\n", 108 | "In Python, you can use the *numpy.**dot*** function to calculate the dot product of two vector arrays:" 109 | ] 110 | }, 111 | { 112 | "cell_type": "code", 113 | "execution_count": null, 114 | "metadata": {}, 115 | "outputs": [], 116 | "source": [ 117 | "import numpy as np\n", 118 | "\n", 119 | "v = np.array([2,1])\n", 120 | "s = np.array([-3,2])\n", 121 | "d = np.dot(v,s)\n", 122 | "print (d)" 123 | ] 124 | }, 125 | { 126 | "cell_type": "markdown", 127 | "metadata": {}, 128 | "source": [ 129 | "In Python 3.5 and later, you can also use the **@** operator to calculate the dot product:" 130 | ] 131 | }, 132 | { 133 | "cell_type": "code", 134 | "execution_count": null, 135 | "metadata": {}, 136 | "outputs": [], 137 | "source": [ 138 | "import numpy as np\n", 139 | "\n", 140 | "v = np.array([2,1])\n", 141 | "s = np.array([-3,2])\n", 142 | "d = v @ s\n", 143 | "print (d)" 144 | ] 145 | }, 146 | { 147 | "cell_type": "markdown", 148 | "metadata": {}, 149 | "source": [ 150 | "### The Cosine Rule\n", 151 | "An useful property of vector dot product multiplication is that we can use it to calculate the cosine of the angle between two vectors. We could write the dot products as:\n", 152 | "\n", 153 | "$$ \\vec{v} \\cdot \\vec{s} = \\|\\vec{v} \\|\\|\\vec{s}\\| \\cos (\\theta) $$ \n", 154 | "\n", 155 | "Which we can rearrange as:\n", 156 | "\n", 157 | "$$ \\cos(\\theta) = \\frac{\\vec{v} \\cdot \\vec{s}}{\\|\\vec{v} \\|\\|\\vec{s}\\|} $$\n", 158 | "\n", 159 | "So for our vectors **v** (2,1) and **s** (-3,2), our calculation looks like this:\n", 160 | "\n", 161 | "$$ \\cos(\\theta) = \\frac{(2 \\cdot-3) + (-3 \\cdot 2)}{\\sqrt{2^{2} + 1^{2}} \\times \\sqrt{-3^{2} + 2^{2}}} $$\n", 162 | "\n", 163 | "So:\n", 164 | "\n", 165 | "$$\\cos(\\theta) = \\frac{-4}{8.0622577483}$$\n", 166 | "\n", 167 | "Which calculates to:\n", 168 | "\n", 169 | "$$\\cos(\\theta) = -0.496138938357 $$\n", 170 | "\n", 171 | "So:\n", 172 | "\n", 173 | "$$\\theta \\approx 119.74 $$\n", 174 | "\n", 175 | "Here's that calculation in Python:" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": {}, 182 | "outputs": [], 183 | "source": [ 184 | "import math\n", 185 | "import numpy as np\n", 186 | "\n", 187 | "# define our vectors\n", 188 | "v = np.array([2,1])\n", 189 | "s = np.array([-3,2])\n", 190 | "\n", 191 | "# get the magnitudes\n", 192 | "vMag = np.linalg.norm(v)\n", 193 | "sMag = np.linalg.norm(s)\n", 194 | "\n", 195 | "# calculate the cosine of theta\n", 196 | "cos = (v @ s) / (vMag * sMag)\n", 197 | "\n", 198 | "# so theta (in degrees) is:\n", 199 | "theta = math.degrees(math.acos(cos))\n", 200 | "\n", 201 | "print(theta)\n" 202 | ] 203 | }, 204 | { 205 | "cell_type": "markdown", 206 | "metadata": { 207 | "collapsed": true 208 | }, 209 | "source": [ 210 | "## Cross Product Multiplication\n", 211 | "To get the *vector product* of multipying two vectors together, you must calculate the *cross product*. The result of this is a new vector that is at right angles to both the other vectors in 3D Euclidean space. This means that the cross-product only really makes sense when working with vectors that contain three components.\n", 212 | "\n", 213 | "For example, let's suppose we have the following vectors:\n", 214 | "\n", 215 | "\\begin{equation}\\vec{p} = \\begin{bmatrix}2 \\\\ 3 \\\\ 1 \\end{bmatrix}\\;\\; \\vec{q} = \\begin{bmatrix}1 \\\\ 2 \\\\ -2 \\end{bmatrix}\\end{equation}\n", 216 | "\n", 217 | "To calculate the cross product of these vectors, written as **p** x **q**, we need to create a new vector (let's call it **r**) with three components (r1, r2, and r3). The values for these components are calculated like this:\n", 218 | "\n", 219 | "\\begin{equation}r_{1} = p_{2}q_{3} - p_{3}q_{2}\\end{equation}\n", 220 | "\\begin{equation}r_{2} = p_{3}q_{1} - p_{1}q_{3}\\end{equation}\n", 221 | "\\begin{equation}r_{3} = p_{1}q_{2} - p_{2}q_{1}\\end{equation}\n", 222 | "\n", 223 | "So in our case:\n", 224 | "\n", 225 | "\\begin{equation}\\vec{r} = \\vec{p} \\times \\vec{q} = \\begin{bmatrix}(3 \\cdot -2) - (1 \\cdot 2) \\\\ (1 \\cdot 1) - (2 \\cdot -2) \\\\ (2 \\cdot 2) - (3 \\cdot 1) \\end{bmatrix} = \\begin{bmatrix}-6 - 2 \\\\ 1 - -4 \\\\ 4 - 3 \\end{bmatrix} = \\begin{bmatrix}-8 \\\\ 5 \\\\ 1 \\end{bmatrix}\\end{equation}\n", 226 | "\n", 227 | "In Python, you can use the *numpy.**cross*** function to calculate the cross product of two vector arrays:" 228 | ] 229 | }, 230 | { 231 | "cell_type": "code", 232 | "execution_count": null, 233 | "metadata": {}, 234 | "outputs": [], 235 | "source": [ 236 | "import numpy as np\n", 237 | "\n", 238 | "p = np.array([2,3,1])\n", 239 | "q = np.array([1,2,-2])\n", 240 | "r = np.cross(p,q)\n", 241 | "print (r)" 242 | ] 243 | } 244 | ], 245 | "metadata": { 246 | "kernelspec": { 247 | "display_name": "Python 3.6", 248 | "language": "python", 249 | "name": "python36" 250 | }, 251 | "language_info": { 252 | "codemirror_mode": { 253 | "name": "ipython", 254 | "version": 3 255 | }, 256 | "file_extension": ".py", 257 | "mimetype": "text/x-python", 258 | "name": "python", 259 | "nbconvert_exporter": "python", 260 | "pygments_lexer": "ipython3", 261 | "version": "3.6.3" 262 | } 263 | }, 264 | "nbformat": 4, 265 | "nbformat_minor": 2 266 | } 267 | -------------------------------------------------------------------------------- /Vector and Matrices by Hiren/03-03-Matrices.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "# Introduction to Matrices\n", 8 | "In general terms, a matrix is an array of numbers that are arranged into rows and columns.\n", 9 | "\n", 10 | "## Matrices and Matrix Notation\n", 11 | "A matrix arranges numbers into rows and columns, like this:\n", 12 | "\n", 13 | "\\begin{equation}A = \\begin{bmatrix}\n", 14 | " 1 & 2 & 3 \\\\\n", 15 | " 4 & 5 & 6\n", 16 | " \\end{bmatrix}\n", 17 | "\\end{equation}\n", 18 | "\n", 19 | "Note that matrices are generally named as a capital letter. We refer to the *elements* of the matrix using the lower case equivalent with a subscript row and column indicator, like this:\n", 20 | "\n", 21 | "\\begin{equation}A = \\begin{bmatrix}\n", 22 | " a_{1,1} & a_{1,2} & a_{1,3} \\\\\n", 23 | " a_{2,1} & a_{2,2} & a_{2,3}\n", 24 | " \\end{bmatrix}\n", 25 | "\\end{equation}\n", 26 | "\n", 27 | "In Python, you can define a matrix as a 2-dimensional *numpy.**array***, like this:" 28 | ] 29 | }, 30 | { 31 | "cell_type": "code", 32 | "execution_count": null, 33 | "metadata": {}, 34 | "outputs": [], 35 | "source": [ 36 | "import numpy as np\n", 37 | "\n", 38 | "A = np.array([[1,2,3],\n", 39 | " [4,5,6]])\n", 40 | "print (A)" 41 | ] 42 | }, 43 | { 44 | "cell_type": "markdown", 45 | "metadata": {}, 46 | "source": [ 47 | "You can also use the *numpy.**matrix*** type, which is a specialist subclass of ***array***:" 48 | ] 49 | }, 50 | { 51 | "cell_type": "code", 52 | "execution_count": null, 53 | "metadata": {}, 54 | "outputs": [], 55 | "source": [ 56 | "import numpy as np\n", 57 | "\n", 58 | "M = np.matrix([[1,2,3],\n", 59 | " [4,5,6]])\n", 60 | "print (M)" 61 | ] 62 | }, 63 | { 64 | "cell_type": "markdown", 65 | "metadata": {}, 66 | "source": [ 67 | "There are some differences in behavior between ***array*** and ***matrix*** types - particularly with regards to multiplication (which we'll explore later). You can use either, but most experienced Python programmers who need to work with both vectors and matrices tend to prefer the ***array*** type for consistency." 68 | ] 69 | }, 70 | { 71 | "cell_type": "markdown", 72 | "metadata": {}, 73 | "source": [ 74 | "## Matrix Operations\n", 75 | "Matrices support common arithmetic operations.\n", 76 | "\n", 77 | "### Adding Matrices\n", 78 | "To add two matrices of the same size together, just add the corresponding elements in each matrix:\n", 79 | "\n", 80 | "\\begin{equation}\\begin{bmatrix}1 & 2 & 3 \\\\4 & 5 & 6\\end{bmatrix}+ \\begin{bmatrix}6 & 5 & 4 \\\\3 & 2 & 1\\end{bmatrix} = \\begin{bmatrix}7 & 7 & 7 \\\\7 & 7 & 7\\end{bmatrix}\\end{equation}\n", 81 | "\n", 82 | "In this example, we're adding two matrices (let's call them ***A*** and ***B***). Each matrix has two rows of three columns (so we describe them as 2x3 matrices). Adding these will create a new matrix of the same dimensions with the values a1,1 + b1,1, a1,2 + b1,2, a1,3 + b1,3,a2,1 + b2,1, a2,2 + b2,2, and a2,3 + b2,3. In this instance, each pair of corresponding elements(1 and 6, 2, and 5, 3 and 4, etc.) adds up to 7.\n", 83 | "\n", 84 | "Let's try that with Python:" 85 | ] 86 | }, 87 | { 88 | "cell_type": "code", 89 | "execution_count": null, 90 | "metadata": {}, 91 | "outputs": [], 92 | "source": [ 93 | "import numpy as np\n", 94 | "\n", 95 | "A = np.array([[1,2,3],\n", 96 | " [4,5,6]])\n", 97 | "B = np.array([[6,5,4],\n", 98 | " [3,2,1]])\n", 99 | "print(A + B)" 100 | ] 101 | }, 102 | { 103 | "cell_type": "markdown", 104 | "metadata": {}, 105 | "source": [ 106 | "### Subtracting Matrices\n", 107 | "Matrix subtraction works similarly to matrix addition:\n", 108 | "\n", 109 | "\\begin{equation}\\begin{bmatrix}1 & 2 & 3 \\\\4 & 5 & 6\\end{bmatrix}- \\begin{bmatrix}6 & 5 & 4 \\\\3 & 2 & 1\\end{bmatrix} = \\begin{bmatrix}-5 & -3 & -1 \\\\1 & 3 & 5\\end{bmatrix}\\end{equation}\n", 110 | "\n", 111 | "Here's the Python code to do this:" 112 | ] 113 | }, 114 | { 115 | "cell_type": "code", 116 | "execution_count": null, 117 | "metadata": {}, 118 | "outputs": [], 119 | "source": [ 120 | "import numpy as np\n", 121 | "\n", 122 | "A = np.array([[1,2,3],\n", 123 | " [4,5,6]])\n", 124 | "B = np.array([[6,5,4],\n", 125 | " [3,2,1]])\n", 126 | "print (A - B)" 127 | ] 128 | }, 129 | { 130 | "cell_type": "markdown", 131 | "metadata": {}, 132 | "source": [ 133 | "#### Conformability\n", 134 | "In the previous examples, we were able to add and subtract the matrices, because the *operands* (the matrices we are operating on) are ***conformable*** for the specific operation (in this case, addition or subtraction). To be conformable for addition and subtraction, the operands must have the same number of rows and columns. There are different conformability requirements for other operations, such as multiplication; which we'll explore later." 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "### Negative Matrices\n", 142 | "The nagative of a matrix, is just a matrix with the sign of each element reversed:\n", 143 | "\n", 144 | "\\begin{equation}C = \\begin{bmatrix}-5 & -3 & -1 \\\\1 & 3 & 5\\end{bmatrix}\\end{equation}\n", 145 | "\n", 146 | "\\begin{equation}-C = \\begin{bmatrix}5 & 3 & 1 \\\\-1 & -3 & -5\\end{bmatrix}\\end{equation}\n", 147 | "\n", 148 | "Let's see that with Python:" 149 | ] 150 | }, 151 | { 152 | "cell_type": "code", 153 | "execution_count": null, 154 | "metadata": {}, 155 | "outputs": [], 156 | "source": [ 157 | "import numpy as np\n", 158 | "\n", 159 | "C = np.array([[-5,-3,-1],\n", 160 | " [1,3,5]])\n", 161 | "print (C)\n", 162 | "print (-C)" 163 | ] 164 | }, 165 | { 166 | "cell_type": "markdown", 167 | "metadata": {}, 168 | "source": [ 169 | "### Matrix Transposition\n", 170 | "You can *transpose* a matrix, that is switch the orientation of its rows and columns. You indicate this with a superscript **T**, like this:\n", 171 | "\n", 172 | "\\begin{equation}\\begin{bmatrix}1 & 2 & 3 \\\\4 & 5 & 6\\end{bmatrix}^{T} = \\begin{bmatrix}1 & 4\\\\2 & 5\\\\3 & 6 \\end{bmatrix}\\end{equation}\n", 173 | "\n", 174 | "In Python, both *numpy.**array*** and *numpy.**matrix*** have a **T** function:" 175 | ] 176 | }, 177 | { 178 | "cell_type": "code", 179 | "execution_count": null, 180 | "metadata": {}, 181 | "outputs": [], 182 | "source": [ 183 | "import numpy as np\n", 184 | "\n", 185 | "A = np.array([[1,2,3],\n", 186 | " [4,5,6]])\n", 187 | "print(A.T)" 188 | ] 189 | } 190 | ], 191 | "metadata": { 192 | "kernelspec": { 193 | "display_name": "Python 3.6", 194 | "language": "python", 195 | "name": "python36" 196 | }, 197 | "language_info": { 198 | "codemirror_mode": { 199 | "name": "ipython", 200 | "version": 3 201 | }, 202 | "file_extension": ".py", 203 | "mimetype": "text/x-python", 204 | "name": "python", 205 | "nbconvert_exporter": "python", 206 | "pygments_lexer": "ipython3", 207 | "version": "3.6.3" 208 | } 209 | }, 210 | "nbformat": 4, 211 | "nbformat_minor": 2 212 | } 213 | --------------------------------------------------------------------------------