{ "cells": [ { "cell_type": "code", "execution_count": 13, "metadata": { "tags": [ "hide-cell" ] }, "outputs": [], "source": [ "# Install the necessary dependencies\n", "\n", "import sys\n", "import os\n", "!{sys.executable} -m pip install --quiet matplotlib numpy pandas ipython jupyterlab_myst scikit-learn" ] }, { "cell_type": "code", "execution_count": 14, "metadata": {}, "outputs": [], "source": [ "import matplotlib\n", "import numpy as np\n", "import pandas as pd\n", "import sklearn\n", "import matplotlib.pyplot as plt\n", "from sklearn.model_selection import train_test_split\n", "from IPython.display import HTML" ] }, { "cell_type": "markdown", "metadata": { "tags": [ "remove-cell" ] }, "source": [ "---\n", "license:\n", " code: MIT\n", " content: CC-BY-4.0\n", "github: https://github.com/ocademy-ai/machine-learning\n", "venue: By Ocademy\n", "open_access: true\n", "bibliography:\n", " - https://raw.githubusercontent.com/ocademy-ai/machine-learning/main/open-machine-learning-jupyter-book/references.bib\n", "---" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "# Gradient descent" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Objective of this session\n", "\n", "We have already learnt how to use Linear Regression and Logistic Regression models.\n", "\n", "The code might seem quite easy and intuitive for you. And you might naturally ask:\n", "- What's behind the ```.fit()``` function?\n", "- Why sometimes it takes quite a bit for this ```.fit()``` function to finish running?\n", "\n", "In this session, you will learn that the ```.fit()``` is the training of ML models, \n", "i.e. tuning of parameters for ML models. And the technique behind is called \"Gradient Descent\"." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Video\n", "\n", "The corresponding video (in Chinese) for this notebook is [👉 available here on Bilibili](https://www.bilibili.com/video/BV1SY4y1G7o9/).\n", "You can (and should) watch the video before diving into the details of gradient descent:" ] }, { "cell_type": "code", "execution_count": 15, "metadata": { "tags": [ "hide-input" ] }, "outputs": [ { "data": { "text/html": [ "\n", "
\n", "\n", "video. [source]\n", "
\n" ], "text/plain": [ "\n", "\n", "video. [source]\n", "
\n", "\"\"\"\n", " )\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Let's be playful ... to gain some intuition\n", "\n", "- [Tensorflow Playground](https://playground.tensorflow.org/#activation=sigmoid&batchSize=10&dataset=circle®Dataset=reg-plane&learningRate=0.00001®ularizationRate=0&noise=0&networkShape=&seed=0.71864&showTestData=false&discretize=false&percTrainData=50&x=true&y=true&xTimesY=true&xSquared=true&ySquared=true&cosX=false&sinX=false&cosY=false&sinY=false&collectStats=false&problem=classification&initZero=false&hideText=false)\n", "- [Gradient Descent Visualization](https://github.com/lilipads/gradient_descent_viz)\n", "- [Optimization Algorithms Visualization](https://bl.ocks.org/EmilienDupont/aaf429be5705b219aaaf8d691e27ca87)" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Some mathematics ... to gain more insight" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Abstract\n", "\n", "The idea behind gradient descent is simple - by gradually tuning parameters, such as slope ($m$) and the intercept ($b$) in our regression function $y = mx + b$, we minimize cost. \n", "By cost, we usually mean some kind of a function that tells us how far off our model predicted result. For regression problems we often use `mean squared error` (MSE) cost function. If we use gradient descent for the classification problem, we will have a different set of parameters to tune.\n", "\n", "$$ MSE = \\frac{1}{n}\\sum_{i=1}^{n} (y_i - \\hat{y_i})^2 \\quad \\textrm{where} \\quad \\hat{y_i} = mx_i + b $$\n", "\n", "Now we have to figure out how to tweak parameters $m$ and $b$ to reduce MSE.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Partial derivatives\n", "\n", "We use partial derivatives to find how each individual parameter affects MSE, so that's where word _partial_ comes from. In simple words, we take the derivative with respect to $m$ and $b$ **separately**. Take a look at the formula below. It looks almost exactly the same as MSE, but this time we added f(m, b) to it. It essentially changes nothing, except now we can plug $m$ and $b$ numbers into it and calculate the result.\n", "\n", "$$𝑓(𝑚,𝑏)= \\frac{1}{n}\\sum_{i=1}^{n}(y_i - (mx_i+b))^2$$\n", "\n", "This formula (or better say function) is better representation for further calculations of partial derivatives. We can ignore sum for now and what comes before that and focus only on $y - (mx + b)^2$." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Partial derivative with respect to $m$\n", "\n", "With respect to $m$ means we derive parameter $m$ and basically ignore what is going on with $b$, or we can say its 0. To derive with respect to $m$ we will use chain rule.\n", "\n", "$$ [f(g(x))]' = f'(g(x)) * g(x)' \\: - \\textrm{chain rule}$$\n", "\n", "Chain rule applies when one function sits inside of another. If you're new to this, you'd be surprised that $()^2$ is outside function, and $y-(\\boldsymbol{m}x+b)$ sits inside it. So, the chain rule says that we should take a derivative of outside function, keep inside function unchanged and then multiply by derivative of the inside function. Lets write these steps down:\n", "\n", "$$ (y - (mx + b))^2 $$\n", "\n", "1. Derivative of $()^2$ is $2()$, same as $x^2$ becomes $2x$\n", "2. We do nothing with $y - (mx + b)$, so it stays the same\n", "3. Derivative of $y - (mx + b)$ with respect to **_m_** is $(0 - (x + 0))$ or $-x$, because **_y_** and **_b_** are constants, they become 0, and derivative of **_mx_** is **_x_**\n", " \n", "Multiply all parts we get following: $2 * (y - (mx+b)) * -x$. \n", "\n", "Looks nicer if we move -x to the left: $-2x *(y-(mx+b))$. There we have it. The final version of our derivative is the following:\n", "\n", "$$\\frac{\\partial f}{\\partial m} = \\frac{1}{n}\\sum_{i=1}^{n}-2x_i(y_i - (mx_i+b))$$\n", "\n", "Here, $\\frac{df}{dm}$ means we find partial derivative of function f (we mentioned it earlier) with respect to m. We plug our derivative to the summation and we're done.\n" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Partial derivative with respect to $b$\n", "\n", "Same rules apply to the derivative with respect to b.\n", "\n", "1. $()^2$ becomes $2()$, same as $x^2$ becomes $2x$\n", "2. $y - (mx + b)$ stays the same\n", "3. $y - (mx + b)$ becomes $(0 - (0 + 1))$ or $-1$, because **_y_** and **_mx_** are constants, they become 0, and derivative of **_b_** is 1\n", "\n", "Multiply all the parts together and we get $-2(y-(mx+b))$\n", "\n", "$$\\frac{\\partial f}{\\partial b} = \\frac{1}{n}\\sum_{i=1}^{n}-2(y_i - (mx_i+b))$$" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Final function\n", "\n", "Few details we should discuss before jumping into code:\n", "\n", "1. Gradient descent is an iterative process and with each iteration ($epoch$) we slightly minimizing MSE, so each time we use our derived functions to update parameters $m$ and $b$.\n", "2. Because it's iterative, we should choose how many iterations we take, or make algorithm stop when we approach minima of MSE. In other words when algorithm is no longer improving MSE, we know it reached minimum.\n", "3. Gradient descent has an additional parameter learning rate ($lr$), which helps control how fast or slow algorithm going towards minima of MSE\n", "\n", "That's about it. So you can already understand that Gradient Descent for the most part is just process of taking derivatives and using them over and over to minimize function." ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Time to code!" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "### Linear regression With gradient descent" ] }, { "cell_type": "code", "execution_count": 16, "metadata": {}, "outputs": [], "source": [ "class LinearRegression:\n", " def __init__(self, learning_rate=0.0003, n_iters=3000):\n", " self.lr = learning_rate\n", " self.n_iters = n_iters\n", " self.weights = None\n", " self.bias = None\n", "\n", " def fit(self, X, y):\n", " n_samples, n_features = X.shape\n", "\n", " # init parameters\n", " self.weights = np.zeros(n_features)\n", " self.bias = 0\n", "\n", " # gradient descent\n", " for _ in range(self.n_iters):\n", " # approximate y with linear combination of weights and x, plus bias\n", " y_predicted = np.dot(X, self.weights) + self.bias\n", "\n", " # compute gradients\n", " dw = (1 / n_samples) * np.dot(X.T, (y_predicted - y))\n", " db = (1 / n_samples) * np.sum(y_predicted - y)\n", " # update parameters\n", " self.weights -= self.lr * dw\n", " self.bias -= self.lr * db\n", "\n", " def predict(self, X):\n", " y_predicted = np.dot(X, self.weights) + self.bias\n", " return y_predicted" ] }, { "cell_type": "code", "execution_count": 17, "metadata": {}, "outputs": [ { "name": "stdout", "output_type": "stream", "text": [ "{'lr': 0.0003, 'n_iters': 3000, 'weights': array([0.36114314, 0.15172482, 0.01138062, 0.07103796, 0.10143793,\n", " 0.14812986, 0.09146885, 0.00270041]), 'bias': 0.014542612245156487}\n", "0 -1.470137\n", "1 -1.226722\n", "2 -1.633534\n", "3 -1.145394\n", "4 -1.385705\n", " ... \n", "92 0.985388\n", "93 1.125408\n", "94 1.936285\n", "95 1.776223\n", "96 1.680470\n", "Name: lpsa, Length: 97, dtype: float64\n" ] }, { "data": { "image/png": "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", "text/plain": [ "\n", "\n", "video. [source]\n", "
\n" ], "text/plain": [ "\n", "\n", "video. [source]\n", "
\n", "\"\"\"\n", " )\n", ")" ] }, { "cell_type": "markdown", "metadata": {}, "source": [ "## Bibliography\n", "\n", "- [Gradient Descent, Step-by-Step - StatQuest](https://www.youtube.com/watch?v=sDv4f4s2SB8)\n", "- [Stochastic Gradient Descent, Clearly Explained!!! - StatQuest](https://www.youtube.com/watch?v=vMh0zPT0tLI) \n", "- http://43.142.12.204:12345/05-ML_04-Under-the-Hood.html\n", "- http://43.142.12.204:9999/GradientDescentAnimation.html" ] } ], "metadata": { "kernelspec": { "display_name": "myconda1", "language": "python", "name": "python3" }, "language_info": { "codemirror_mode": { "name": "ipython", "version": 3 }, "file_extension": ".py", "mimetype": "text/x-python", "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", "version": "3.11.5" } }, "nbformat": 4, "nbformat_minor": 2 }