Created
August 7, 2015 13:00
-
-
Save z-m-k/03e1f3f1452d3d9e9595 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"cells": [ | |
{ | |
"cell_type": "code", | |
"execution_count": 1, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [ | |
"using DataFrames" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 2, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"numerical_derivatives (generic function with 1 method)" | |
] | |
}, | |
"execution_count": 2, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"function numerical_derivatives(fun::Function, x::Array)\n", | |
" function derivative(f0::Array, f, x)\n", | |
" grad=fill(0.0, size(v)[1], length(x))\n", | |
" for i in 1:length(x)\n", | |
" h=sqrt(eps())*maximum((abs(x[i]),1))\n", | |
" xph = copy(x)\n", | |
" xph[i]+=h\n", | |
" dx = (xph[i] - x[i])#::Float64\n", | |
" f1 = fun(xph...)#::Float64\n", | |
" grad[:,i]=(f1 - f0) / dx\n", | |
" end\n", | |
" return [f0, grad...]\n", | |
" end\n", | |
" function derivative(f0::Number, f, x)\n", | |
" grad=fill(0.0, length(x))\n", | |
" for i in 1:length(x)\n", | |
" h=sqrt(eps())*maximum((abs(x[i]),1))\n", | |
" xph = copy(x)\n", | |
" xph[i]+=h\n", | |
" dx = (xph[i] - x[i])#::Float64\n", | |
" f1 = fun(xph...)#::Float64\n", | |
" grad[i]=(f1 - f0) / dx\n", | |
" end\n", | |
" return [f0, grad...]\n", | |
" end\n", | |
" f0=fun(x...)\n", | |
" return derivative(f0, fun, x)\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 3, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"autodiff_derivatives (generic function with 1 method)" | |
] | |
}, | |
"execution_count": 3, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"using DualNumbers\n", | |
"function autodiff_derivatives(f, x)\n", | |
" function derivative(v::Array, f, x)\n", | |
" grad=fill(0.0, size(v)[1], length(x))\n", | |
" for i=1:length(x)\n", | |
" xp=copy(xp0)\n", | |
" xp[i]=dual(x[i], 1)\n", | |
" grad[:,i]=epsilon(f(xp...))\n", | |
" end\n", | |
" return [v, grad...]\n", | |
" end\n", | |
" function derivative(v::Number, f, x)\n", | |
" grad=fill(0.0, length(x))\n", | |
" grad=fill(0.0, length(x))\n", | |
" for i=1:length(x)\n", | |
" xp=copy(xp0)\n", | |
" xp[i]=dual(x[i], 1)\n", | |
" grad[i]=epsilon(f(xp...))\n", | |
" end\n", | |
" return [v, grad...]\n", | |
" end\n", | |
" xp0=dual(x, 0)\n", | |
" v=f(x...)\n", | |
" return derivative(v, f, x)\n", | |
"end" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": { | |
"collapsed": false | |
}, | |
"source": [ | |
"#Example\n", | |
"Consider $f(x,y)=4.25x^2+xy^x$\n", | |
"\n", | |
"Then:\n", | |
"\n", | |
"$\\frac{\\partial f}{\\partial x}=8.5x+y^x+xy^x\\log{y}$\n", | |
"\n", | |
"$\\frac{\\partial f}{\\partial y}=x^2y^{x-1}$" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 4, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [], | |
"source": [ | |
"f(x,y) = 4.25*x^2 + x*y^x\n", | |
"∂f∂x(x,y) = 8.5x + y^x + x*y^x*log(y)\n", | |
"∂f∂y(x,y) = x^2*y^(x-1)\n", | |
"\n", | |
"x=2.5\n", | |
"y=3\n", | |
"hand_written=[f(x,y), ∂f∂x(x,y), ∂f∂y(x,y)]\n", | |
"auto_diff =autodiff_derivatives(f, [x, y])\n", | |
"nume_diff =numerical_derivatives(f, [x,y]);" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 5, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<table class=\"data-frame\"><tr><th></th><th>Index</th><th>Hand</th><th>Auto</th><th>Numerical</th></tr><tr><th>1</th><td>$f()$</td><td>65.53364317029974</td><td>65.53364317029974</td><td>65.53364317029974</td></tr><tr><th>2</th><td>$\\frac{∂f}{∂x}$</td><td>79.65263405845546</td><td>79.65263405845546</td><td>79.65263595581055</td></tr><tr><th>3</th><td>$\\frac{∂f}{∂y}$</td><td>32.47595264191645</td><td>32.47595264191645</td><td>32.475952784220375</td></tr></table>" | |
], | |
"text/plain": [ | |
"3x4 DataFrame\n", | |
"| Row | Index | Hand | Auto | Numerical |\n", | |
"|-----|-----------------|---------|---------|-----------|\n", | |
"| 1 | \"\\$f()\\$\" | 65.5336 | 65.5336 | 65.5336 |\n", | |
"| 2 | \"\\$\\\\frac{\\u2202f}{\\u2202x}\\$\" | 79.6526 | 79.6526 | 79.6526 |\n", | |
"| 3 | \"\\$\\\\frac{\\u2202f}{\\u2202y}\\$\" | 32.476 | 32.476 | 32.476 |" | |
] | |
}, | |
"execution_count": 5, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"data=DataFrame(Index=[\"\\$f()\\$\", \"\\$\\\\frac{∂f}{∂x}\\$\", \"\\$\\\\frac{∂f}{∂y}\\$\"], \n", | |
" Hand=hand_written, \n", | |
" Auto=auto_diff, \n", | |
" Numerical=nume_diff)" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Differences between them:" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 6, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<table class=\"data-frame\"><tr><th></th><th>Index</th><th>Auto</th><th>Numerical</th></tr><tr><th>1</th><td>$f()$</td><td>0.0</td><td>0.0</td></tr><tr><th>2</th><td>$\\frac{∂f}{∂x}$</td><td>0.0</td><td>-1.8973550908185643e-6</td></tr><tr><th>3</th><td>$\\frac{∂f}{∂y}$</td><td>0.0</td><td>-1.42303925088072e-7</td></tr></table>" | |
], | |
"text/plain": [ | |
"3x3 DataFrame\n", | |
"| Row | Index | Auto | Numerical |\n", | |
"|-----|-----------------|------|-------------|\n", | |
"| 1 | \"\\$f()\\$\" | 0.0 | 0.0 |\n", | |
"| 2 | \"\\$\\\\frac{\\u2202f}{\\u2202x}\\$\" | 0.0 | -1.89736e-6 |\n", | |
"| 3 | \"\\$\\\\frac{\\u2202f}{\\u2202y}\\$\" | 0.0 | -1.42304e-7 |" | |
] | |
}, | |
"execution_count": 6, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"DataFrame(Index=[\"\\$f()\\$\", \"\\$\\\\frac{∂f}{∂x}\\$\", \"\\$\\\\frac{∂f}{∂y}\\$\"], \n", | |
" Auto=data[:Hand]-data[:Auto], \n", | |
" Numerical=data[:Hand]-data[:Numerical])" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"So AutoDiff is __exact__." | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"#Works with more complex functions \n", | |
"\n", | |
"Let $f(x_{1..N},y_{1..N})=4.5a\\sum_{i=1}^N{x^{ia}_i}+ab\\sum_{i=1}^N{i x_i y_i^{\\frac{a}{b}x_i}}$" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 11, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/plain": [ | |
"(\n", | |
"1x3 Array{Float64,2}:\n", | |
" 0.355383 1.25013 0.376598,\n", | |
"\n", | |
"1x3 Array{Float64,2}:\n", | |
" 0.512889 0.467054 3.45291)" | |
] | |
}, | |
"execution_count": 11, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"a=2.5; b=3;\n", | |
"X=exp(randn(3))\n", | |
"Y=exp(randn(3))\n", | |
"X', Y'" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 12, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<table class=\"data-frame\"><tr><th></th><th>Index</th><th>Auto</th><th>Numerical</th></tr><tr><th>1</th><td>$f$</td><td>58.37780401230243</td><td>58.37780401230243</td></tr><tr><th>2</th><td>$\\frac{∂f}{∂a}$</td><td>36.87103006799046</td><td>36.87103042602539</td></tr><tr><th>3</th><td>$\\frac{∂f}{∂b}$</td><td>8.490680931708148</td><td>8.490681012471518</td></tr></table>" | |
], | |
"text/plain": [ | |
"3x3 DataFrame\n", | |
"| Row | Index | Auto | Numerical |\n", | |
"|-----|-----------------|---------|-----------|\n", | |
"| 1 | \"\\$f\\$\" | 58.3778 | 58.3778 |\n", | |
"| 2 | \"\\$\\\\frac{\\u2202f}{\\u2202a}\\$\" | 36.871 | 36.871 |\n", | |
"| 3 | \"\\$\\\\frac{\\u2202f}{\\u2202b}\\$\" | 8.49068 | 8.49068 |" | |
] | |
}, | |
"execution_count": 12, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"#One line...\n", | |
"f(a,b)=4.5*a*sum([x^(a*i) for (i,x) in enumerate(X)])+sum([a*b*i*xy[1]*xy[2]^(a/b*xy[1]) for (i,xy) in enumerate(zip(X,Y))])\n", | |
"one=DataFrame(Index=[\"\\$f\\$\", \"\\$\\\\frac{∂f}{∂a}\\$\", \"\\$\\\\frac{∂f}{∂b}\\$\"], \n", | |
" Auto=autodiff_derivatives(f, [a, b]), \n", | |
" Numerical=numerical_derivatives(f, [a, b]))" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 13, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<table class=\"data-frame\"><tr><th></th><th>Index</th><th>Auto</th><th>Numerical</th></tr><tr><th>1</th><td>$f$</td><td>58.37780401230242</td><td>58.37780401230242</td></tr><tr><th>2</th><td>$\\frac{∂f}{∂a}$</td><td>36.87103006799046</td><td>36.87103061676025</td></tr><tr><th>3</th><td>$\\frac{∂f}{∂b}$</td><td>8.490680931708148</td><td>8.490681171417236</td></tr></table>" | |
], | |
"text/plain": [ | |
"3x3 DataFrame\n", | |
"| Row | Index | Auto | Numerical |\n", | |
"|-----|-----------------|---------|-----------|\n", | |
"| 1 | \"\\$f\\$\" | 58.3778 | 58.3778 |\n", | |
"| 2 | \"\\$\\\\frac{\\u2202f}{\\u2202a}\\$\" | 36.871 | 36.871 |\n", | |
"| 3 | \"\\$\\\\frac{\\u2202f}{\\u2202b}\\$\" | 8.49068 | 8.49068 |" | |
] | |
}, | |
"execution_count": 13, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"#Of course this could be also written...\n", | |
"function f(a,b)\n", | |
" out=0.0\n", | |
" for i=1:endof(X)\n", | |
" @inbounds out+=4.5*a*X[i]^(a*i)+a*b*i*X[i]*Y[i]^(a/b*X[i])\n", | |
" end\n", | |
" out\n", | |
"end\n", | |
"long=DataFrame(Index=[\"\\$f\\$\", \"\\$\\\\frac{∂f}{∂a}\\$\", \"\\$\\\\frac{∂f}{∂b}\\$\"], \n", | |
" Auto=autodiff_derivatives(f, [a, b]), \n", | |
" Numerical=numerical_derivatives(f, [a, b]))" | |
] | |
}, | |
{ | |
"cell_type": "markdown", | |
"metadata": {}, | |
"source": [ | |
"Differences (due to order of operations on floats)" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": 14, | |
"metadata": { | |
"collapsed": false | |
}, | |
"outputs": [ | |
{ | |
"data": { | |
"text/html": [ | |
"<table class=\"data-frame\"><tr><th></th><th>Index</th><th>Auto</th><th>Numerical</th></tr><tr><th>1</th><td>$f$</td><td>7.105427357601002e-15</td><td>7.105427357601002e-15</td></tr><tr><th>2</th><td>$\\frac{∂f}{∂a}$</td><td>0.0</td><td>-1.9073485901799359e-7</td></tr><tr><th>3</th><td>$\\frac{∂f}{∂b}$</td><td>0.0</td><td>-1.5894571880892272e-7</td></tr></table>" | |
], | |
"text/plain": [ | |
"3x3 DataFrame\n", | |
"| Row | Index | Auto | Numerical |\n", | |
"|-----|-----------------|-------------|-------------|\n", | |
"| 1 | \"\\$f\\$\" | 7.10543e-15 | 7.10543e-15 |\n", | |
"| 2 | \"\\$\\\\frac{\\u2202f}{\\u2202a}\\$\" | 0.0 | -1.90735e-7 |\n", | |
"| 3 | \"\\$\\\\frac{\\u2202f}{\\u2202b}\\$\" | 0.0 | -1.58946e-7 |" | |
] | |
}, | |
"execution_count": 14, | |
"metadata": {}, | |
"output_type": "execute_result" | |
} | |
], | |
"source": [ | |
"DataFrame(Index=[\"\\$f\\$\", \"\\$\\\\frac{∂f}{∂a}\\$\", \"\\$\\\\frac{∂f}{∂b}\\$\"], \n", | |
" Auto=one[:Auto]-long[:Auto], \n", | |
" Numerical=one[:Numerical]-long[:Numerical])" | |
] | |
}, | |
{ | |
"cell_type": "code", | |
"execution_count": null, | |
"metadata": { | |
"collapsed": true | |
}, | |
"outputs": [], | |
"source": [] | |
} | |
], | |
"metadata": { | |
"kernelspec": { | |
"display_name": "Julia 0.3.9", | |
"language": "julia", | |
"name": "julia-0.3" | |
}, | |
"language_info": { | |
"name": "julia", | |
"version": "0.3.9" | |
} | |
}, | |
"nbformat": 4, | |
"nbformat_minor": 0 | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment