{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Illustrations for Gradient Descent\n",
"Author: Joerg Kienitz (finciraptor.de, https://github.com/Lapsilago) for the workshop Machine Learning for Option Pricing, Calibration and Hedging Workshop with Nikolai Nowaczyk ( https://github.com/niknow; https://github.com/niknow/machine-learning-examples )"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {},
"outputs": [],
"source": [
"%matplotlib inline\n",
"import numpy as np\n",
"import scipy as sp\n",
"import matplotlib.pyplot as plt\n",
"import random\n",
"from scipy import stats\n",
"from scipy.optimize import fmin"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Gradient Descent"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Gradient descent, also known as steepest descent, is an optimization technique that finds a local minimum of a function. \n",
"To find it, the function \"steps\" in the direction of the steepest negative direction of the gradient.\n",
"The algorithm of gradient descent can be outlined as follows:\n",
"\n",
" 1: Choose initial guess $x_0$
\n",
" 2: for k = 0, 1, 2, ... do
\n",
" 3: $grad_k$ = -$grad f(x_k)$
\n",
" 4: choose $\\alpha_k$ to minimize $f(x_k+\\alpha_k grad_k)$
\n",
" 5: $x_{k+1} = x_k + \\alpha_k grad_k$
\n",
" 6: end for"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"As a simple example, let's find a local minimum for the function $f(x) = x^4-2x^2 - 0.5 x+2 + \\sin(x)^2$"
]
},
{
"cell_type": "code",
"execution_count": 4,
"metadata": {},
"outputs": [],
"source": [
"f = lambda x: x**4-2*x**2 - 0.5*x + 2 + np.sin(x)**2"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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\n",
"text/plain": [
"