diff --git a/doc/pub/Splines/html/._Splines-bs000.html b/doc/pub/Splines/html/._Splines-bs000.html index c216dd1d9..eb965b485 100644 --- a/doc/pub/Splines/html/._Splines-bs000.html +++ b/doc/pub/Splines/html/._Splines-bs000.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -234,7 +266,7 @@ MathJax.Hub.Config({
  • 9
  • 10
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs001.html b/doc/pub/Splines/html/._Splines-bs001.html index e621c87b3..b2483d189 100644 --- a/doc/pub/Splines/html/._Splines-bs001.html +++ b/doc/pub/Splines/html/._Splines-bs001.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -220,7 +252,7 @@ some approximative/numerical method to compute the minimum.
  • 10
  • 11
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs002.html b/doc/pub/Splines/html/._Splines-bs002.html index 8c76c24e2..7aa52ca1a 100644 --- a/doc/pub/Splines/html/._Splines-bs002.html +++ b/doc/pub/Splines/html/._Splines-bs002.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -228,7 +260,7 @@ where \( \hat{\beta} \) are the weights we wish to extract from data, in our cas
  • 11
  • 12
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs003.html b/doc/pub/Splines/html/._Splines-bs003.html index c631ad132..85363b56e 100644 --- a/doc/pub/Splines/html/._Splines-bs003.html +++ b/doc/pub/Splines/html/._Splines-bs003.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -233,7 +265,7 @@ This defines what we call the Hessian.
  • 12
  • 13
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs004.html b/doc/pub/Splines/html/._Splines-bs004.html index df245e3c2..ddf626455 100644 --- a/doc/pub/Splines/html/._Splines-bs004.html +++ b/doc/pub/Splines/html/._Splines-bs004.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -234,7 +266,7 @@ If we can compute these matrices, in particular the Hessian, the above is often
  • 13
  • 14
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs005.html b/doc/pub/Splines/html/._Splines-bs005.html index 2c2088fdc..3cd5f3f8a 100644 --- a/doc/pub/Splines/html/._Splines-bs005.html +++ b/doc/pub/Splines/html/._Splines-bs005.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -228,7 +260,7 @@ discourage the use of this method.
  • 14
  • 15
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs006.html b/doc/pub/Splines/html/._Splines-bs006.html index 97c27747b..ee9b0ff05 100644 --- a/doc/pub/Splines/html/._Splines-bs006.html +++ b/doc/pub/Splines/html/._Splines-bs006.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -246,7 +278,7 @@ $$
  • 15
  • 16
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs007.html b/doc/pub/Splines/html/._Splines-bs007.html index 93c540229..7bdfd6ee1 100644 --- a/doc/pub/Splines/html/._Splines-bs007.html +++ b/doc/pub/Splines/html/._Splines-bs007.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -229,7 +261,7 @@ vanishes, then Newton-Raphson may fail totally
  • 16
  • 17
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs008.html b/doc/pub/Splines/html/._Splines-bs008.html index 3aab78db6..8ea01bac2 100644 --- a/doc/pub/Splines/html/._Splines-bs008.html +++ b/doc/pub/Splines/html/._Splines-bs008.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -267,7 +299,7 @@ more than two non-linear equations. In our case, the Jacobian matrix is given by
  • 17
  • 18
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs009.html b/doc/pub/Splines/html/._Splines-bs009.html index d5cf8f1fe..b222ff857 100644 --- a/doc/pub/Splines/html/._Splines-bs009.html +++ b/doc/pub/Splines/html/._Splines-bs009.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -237,7 +269,7 @@ we are always moving towards smaller function values, i.e a minimum.
  • 18
  • 19
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs010.html b/doc/pub/Splines/html/._Splines-bs010.html index a8d1d1e3f..f92deb50c 100644 --- a/doc/pub/Splines/html/._Splines-bs010.html +++ b/doc/pub/Splines/html/._Splines-bs010.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -233,7 +265,7 @@ the learning rate within the context of Machine Learning.
  • 19
  • 20
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs011.html b/doc/pub/Splines/html/._Splines-bs011.html index 4fab036d3..cf8ea973d 100644 --- a/doc/pub/Splines/html/._Splines-bs011.html +++ b/doc/pub/Splines/html/._Splines-bs011.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -240,7 +272,7 @@ Note that the gradient is a function of \( \mathbf{x} =
  • 20
  • 21
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs012.html b/doc/pub/Splines/html/._Splines-bs012.html index 77ef7c405..0101a3f47 100644 --- a/doc/pub/Splines/html/._Splines-bs012.html +++ b/doc/pub/Splines/html/._Splines-bs012.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -233,7 +265,7 @@ randomness. One such method is that of Stochastic Gradient Descent
  • 21
  • 22
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs013.html b/doc/pub/Splines/html/._Splines-bs013.html index 4396ca41d..1270578c7 100644 --- a/doc/pub/Splines/html/._Splines-bs013.html +++ b/doc/pub/Splines/html/._Splines-bs013.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -234,7 +266,7 @@ regular polygons (triangles, rectangles, pentagons, etc...).
  • 22
  • 23
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs014.html b/doc/pub/Splines/html/._Splines-bs014.html index 3bd25ac38..3ef745a29 100644 --- a/doc/pub/Splines/html/._Splines-bs014.html +++ b/doc/pub/Splines/html/._Splines-bs014.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -222,7 +254,7 @@ MathJax.Hub.Config({
  • 23
  • 24
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs015.html b/doc/pub/Splines/html/._Splines-bs015.html index 2d6c4040e..f96a3a59d 100644 --- a/doc/pub/Splines/html/._Splines-bs015.html +++ b/doc/pub/Splines/html/._Splines-bs015.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -258,7 +290,7 @@ This condition is particularly useful since it gives us an procedure for determi
  • 24
  • 25
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs016.html b/doc/pub/Splines/html/._Splines-bs016.html index c5244bd66..c495cb57f 100644 --- a/doc/pub/Splines/html/._Splines-bs016.html +++ b/doc/pub/Splines/html/._Splines-bs016.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -245,7 +277,7 @@ This result means that if we know that the cost/loss function is convex and we a
  • 25
  • 26
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs017.html b/doc/pub/Splines/html/._Splines-bs017.html index 12414cfc1..aadf5ae5f 100644 --- a/doc/pub/Splines/html/._Splines-bs017.html +++ b/doc/pub/Splines/html/._Splines-bs017.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -241,7 +273,7 @@ Using the definition of convexity, try to show that a function satisfying the pr
  • 26
  • 27
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs018.html b/doc/pub/Splines/html/._Splines-bs018.html index d9c239863..f71607f7f 100644 --- a/doc/pub/Splines/html/._Splines-bs018.html +++ b/doc/pub/Splines/html/._Splines-bs018.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -248,7 +280,7 @@ When we have found the exact solution, \( \hat{r}=0 \).
  • 27
  • 28
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs019.html b/doc/pub/Splines/html/._Splines-bs019.html index c55d6ae22..fdca46ebd 100644 --- a/doc/pub/Splines/html/._Splines-bs019.html +++ b/doc/pub/Splines/html/._Splines-bs019.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -234,7 +266,7 @@ This quantity is always positive definite.
  • 28
  • 29
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs020.html b/doc/pub/Splines/html/._Splines-bs020.html index 30fecb335..8ee9b869b 100644 --- a/doc/pub/Splines/html/._Splines-bs020.html +++ b/doc/pub/Splines/html/._Splines-bs020.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -237,7 +269,7 @@ instead.
  • 29
  • 30
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs021.html b/doc/pub/Splines/html/._Splines-bs021.html index 84576198a..317308e08 100644 --- a/doc/pub/Splines/html/._Splines-bs021.html +++ b/doc/pub/Splines/html/._Splines-bs021.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -245,7 +277,7 @@ and
  • 30
  • 31
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs022.html b/doc/pub/Splines/html/._Splines-bs022.html index e79c9ffd1..d09d08b38 100644 --- a/doc/pub/Splines/html/._Splines-bs022.html +++ b/doc/pub/Splines/html/._Splines-bs022.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -241,7 +273,7 @@ $$
  • 31
  • 32
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs023.html b/doc/pub/Splines/html/._Splines-bs023.html index 5fbfa7fb8..6d4ad5c74 100644 --- a/doc/pub/Splines/html/._Splines-bs023.html +++ b/doc/pub/Splines/html/._Splines-bs023.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -253,7 +285,7 @@ $$
  • 32
  • 33
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs024.html b/doc/pub/Splines/html/._Splines-bs024.html index e68f417f4..6f14752a5 100644 --- a/doc/pub/Splines/html/._Splines-bs024.html +++ b/doc/pub/Splines/html/._Splines-bs024.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -191,7 +223,43 @@ MathJax.Hub.Config({ -

    The Steepest descent algorithm

    +

    Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come

    +
    +
    +

    +

    + + +

    #include <cmath>
    +#include <iostream>
    +#include <fstream>
    +#include <iomanip>
    +#include "vectormatrixclass.h"
    +using namespace  std;
    +//   Main function begins here
    +int main(int  argc, char * argv[]){
    +  int dim = 2;
    +  Vector x(dim),xsd(dim), b(dim),x0(dim);
    +  Matrix A(dim,dim);
    +
    +  // Set our initial guess
    +  x0(0) = x0(1) = 0;
    +  // Set the matrix
    +  A(0,0) =  3;    A(1,0) =  2;   A(0,1) =  2;   A(1,1) =  6;
    +  b(0) = 2; b(1) = -8;
    +  cout << "The Matrix A that we are using: " << endl;
    +  A.Print();
    +  cout << endl;
    +  xsd = SteepestDescent(A,b,x0);
    +  cout << "The approximate solution using Steepest Descent is: " << endl;
    +  xsd.Print();
    +  cout << endl;
    +}
    +
    +

    +

    +
    +

    @@ -219,7 +287,7 @@ MathJax.Hub.Config({

  • 33
  • 34
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs025.html b/doc/pub/Splines/html/._Splines-bs025.html index e166ae0cf..1262485a7 100644 --- a/doc/pub/Splines/html/._Splines-bs025.html +++ b/doc/pub/Splines/html/._Splines-bs025.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -191,37 +223,33 @@ MathJax.Hub.Config({ -

    Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come

    +

    The routine for the steepest descent method

    -

    #include <cmath>
    -#include <iostream>
    -#include <fstream>
    -#include <iomanip>
    -#include "vectormatrixclass.h"
    -using namespace  std;
    -//   Main function begins here
    -int main(int  argc, char * argv[]){
    -  int dim = 2;
    -  Vector x(dim),xsd(dim), b(dim),x0(dim);
    -  Matrix A(dim,dim);
    -
    -  // Set our initial guess
    -  x0(0) = x0(1) = 0;
    -  // Set the matrix
    -  A(0,0) =  3;    A(1,0) =  2;   A(0,1) =  2;   A(1,1) =  6;
    -  b(0) = 2; b(1) = -8;
    -  cout << "The Matrix A that we are using: " << endl;
    -  A.Print();
    -  cout << endl;
    -  xsd = SteepestDescent(A,b,x0);
    -  cout << "The approximate solution using Steepest Descent is: " << endl;
    -  xsd.Print();
    -  cout << endl;
    +
    Vector SteepestDescent(Matrix A, Vector b, Vector x0){
    +  int IterMax, i;
    +  int dim = x0.Dimension();
    +  const double tolerance = 1.0e-14;
    +  Vector x(dim),f(dim),z(dim);
    +  double c,alpha,d;
    +  IterMax = 30;
    +  x = x0;
    +  f = A*x-b;
    +  i = 0;
    +  while (i <= IterMax){
    +    z = A*f;
    +    c = dot(f,f);
    +    alpha = c/dot(f,z);
    +    x = x - alpha*f;
    +    f =  A*x-b;
    +    if(sqrt(dot(f,f)) < tolerance) break;
    +    i++;
    +  }
    +  return x;
     }
     

    @@ -255,7 +283,7 @@ MathJax.Hub.Config({

  • 34
  • 35
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs026.html b/doc/pub/Splines/html/._Splines-bs026.html index b0bd26ee6..6a4091784 100644 --- a/doc/pub/Splines/html/._Splines-bs026.html +++ b/doc/pub/Splines/html/._Splines-bs026.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -191,40 +223,72 @@ MathJax.Hub.Config({ -

    The routine for the steepest descent method

    -
    -
    -

    +

    Steepest descent example

    +

    - -

    Vector SteepestDescent(Matrix A, Vector b, Vector x0){
    -  int IterMax, i;
    -  int dim = x0.Dimension();
    -  const double tolerance = 1.0e-14;
    -  Vector x(dim),f(dim),z(dim);
    -  double c,alpha,d;
    -  IterMax = 30;
    -  x = x0;
    -  f = A*x-b;
    -  i = 0;
    -  while (i <= IterMax){
    -    z = A*f;
    -    c = dot(f,f);
    -    alpha = c/dot(f,z);
    -    x = x - alpha*f;
    -    f =  A*x-b;
    -    if(sqrt(dot(f,f)) < tolerance) break;
    -    i++;
    -  }
    -  return x;
    -}
    +
    +
    import numpy as np
    +import numpy.linalg as la
    +
    +import scipy.optimize as sopt
    +
    +import matplotlib.pyplot as pt
    +from mpl_toolkits.mplot3d import axes3d
    +
    +def f(x):
    +    return 0.5*x[0]**2 + 2.5*x[1]**2
    +
    +def df(x):
    +    return np.array([x[0], 5*x[1]])
    +
    +fig = pt.figure()
    +ax = fig.gca(projection="3d")
    +
    +xmesh, ymesh = np.mgrid[-2:2:50j,-2:2:50j]
    +fmesh = f(np.array([xmesh, ymesh]))
    +ax.plot_surface(xmesh, ymesh, fmesh)
     

    -

    -
    +And then as countor plot +

    + +

    pt.axis("equal")
    +pt.contour(xmesh, ymesh, fmesh)
    +guesses = [np.array([2, 2./5])]
    +
    +

    +Find guesses +

    + +

    x = guesses[-1]
    +s = -df(x)
    +
    +

    +Run it! +

    + + +

    def f1d(alpha):
    +    return f(x + alpha*s)
    +
    +alpha_opt = sopt.golden(f1d)
    +next_guess = x + alpha_opt * s
    +guesses.append(next_guess)
    +print(next_guess)
    +
    +

    +What happened? +

    + + +

    pt.axis("equal")
    +pt.contour(xmesh, ymesh, fmesh, 50)
    +it_array = np.array(guesses)
    +pt.plot(it_array.T[0], it_array.T[1], "x-")
    +

    @@ -251,7 +315,7 @@ MathJax.Hub.Config({

  • 35
  • 36
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs027.html b/doc/pub/Splines/html/._Splines-bs027.html index ca1d578bc..fd7aad1de 100644 --- a/doc/pub/Splines/html/._Splines-bs027.html +++ b/doc/pub/Splines/html/._Splines-bs027.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -247,7 +279,7 @@ $$
  • 36
  • 37
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs028.html b/doc/pub/Splines/html/._Splines-bs028.html index 0221d826d..d7eb316cc 100644 --- a/doc/pub/Splines/html/._Splines-bs028.html +++ b/doc/pub/Splines/html/._Splines-bs028.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -239,7 +271,7 @@ and we want to find \( \beta \) such that \( C(\beta) \) is minimized.
  • 37
  • 38
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs029.html b/doc/pub/Splines/html/._Splines-bs029.html index 1f913575d..50fc19fac 100644 --- a/doc/pub/Splines/html/._Splines-bs029.html +++ b/doc/pub/Splines/html/._Splines-bs029.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -229,7 +261,7 @@ where \( X \) is the design matrix defined above.
  • 38
  • 39
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs030.html b/doc/pub/Splines/html/._Splines-bs030.html index cd86c0601..670f5b681 100644 --- a/doc/pub/Splines/html/._Splines-bs030.html +++ b/doc/pub/Splines/html/._Splines-bs030.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -228,7 +260,7 @@ This result implies that \( C(\beta) \) is a convex function since the matrix \(
  • 39
  • 40
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs031.html b/doc/pub/Splines/html/._Splines-bs031.html index ef3d3335f..08c341ca9 100644 --- a/doc/pub/Splines/html/._Splines-bs031.html +++ b/doc/pub/Splines/html/._Splines-bs031.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -255,7 +287,7 @@ beta_NE = np.40
  • 41
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs032.html b/doc/pub/Splines/html/._Splines-bs032.html index 42591f222..442c13c53 100644 --- a/doc/pub/Splines/html/._Splines-bs032.html +++ b/doc/pub/Splines/html/._Splines-bs032.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -262,6 +294,8 @@ plt.show()
  • 40
  • 41
  • 42
  • +
  • ...
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs033.html b/doc/pub/Splines/html/._Splines-bs033.html index 21dff141e..f84ec47ca 100644 --- a/doc/pub/Splines/html/._Splines-bs033.html +++ b/doc/pub/Splines/html/._Splines-bs033.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -236,6 +268,9 @@ sgdreg.fit(x,y.
  • 40
  • 41
  • 42
  • +
  • 43
  • +
  • ...
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs034.html b/doc/pub/Splines/html/._Splines-bs034.html index 28adb0597..476360c47 100644 --- a/doc/pub/Splines/html/._Splines-bs034.html +++ b/doc/pub/Splines/html/._Splines-bs034.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -268,6 +300,10 @@ beta_ridge = np
  • 40
  • 41
  • 42
  • +
  • 43
  • +
  • 44
  • +
  • ...
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs035.html b/doc/pub/Splines/html/._Splines-bs035.html index 5ec6ed1ec..df7160e8f 100644 --- a/doc/pub/Splines/html/._Splines-bs035.html +++ b/doc/pub/Splines/html/._Splines-bs035.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -191,21 +223,58 @@ MathJax.Hub.Config({ -

    Stochastic Gradient Descent

    - -

    -Stochastic gradient descent (SGD) and variants thereof address some of -the shortcomings of the Gradient descent method discussed above. - -

    -The underlying idea of SGD comes from the observation that the cost -function, which we want to minimize, can almost always be written as a -sum over \( n \) data points \( \{\mathbf{x}_i\}_{i=1}^n \), +

    Automatic differentiation

    +Python has tools for so-called automatic differentiation. +Consider the following example $$ -C(\mathbf{\beta}) = \sum_{i=1}^n c_i(\mathbf{x}_i, -\mathbf{\beta}). +f(x) = \sin\left(2\pi x + x^2\right) $$ +which has the following derivative +$$ +f'(x) = \cos\left(2\pi x + x^2\right)\left(2\pi + 2x\right) +$$ + +Using autograd we have + +

    + + +

    import autograd.numpy as np
    +
    +# To do elementwise differentiation:
    +from autograd import elementwise_grad as egrad 
    +
    +# To plot:
    +import matplotlib.pyplot as plt 
    +
    +
    +def f(x):
    +    return np.sin(2*np.pi*x + x**2)
    +
    +def f_grad_analytic(x):
    +    return np.cos(2*np.pi*x + x**2)*(2*np.pi + 2*x)
    +
    +# Do the comparison:
    +x = np.linspace(0,1,1000)
    +
    +f_grad = egrad(f)
    +
    +computed = f_grad(x)
    +analytic = f_grad_analytic(x)
    +
    +plt.title('Derivative computed from Autograd compared with the analytical derivative')
    +plt.plot(x,computed,label='autograd')
    +plt.plot(x,analytic,label='analytic')
    +
    +plt.xlabel('x')
    +plt.ylabel('y')
    +plt.legend()
    +
    +plt.show()
    +
    +print("The max absolute difference is: %g"%(np.max(np.abs(computed - analytic))))
    +

    @@ -228,6 +297,11 @@ $$

  • 40
  • 41
  • 42
  • +
  • 43
  • +
  • 44
  • +
  • 45
  • +
  • ...
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs036.html b/doc/pub/Splines/html/._Splines-bs036.html index a04c611a6..8a3ee3b05 100644 --- a/doc/pub/Splines/html/._Splines-bs036.html +++ b/doc/pub/Splines/html/._Splines-bs036.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -189,25 +221,38 @@ MathJax.Hub.Config({

     

     

     

    - + -

    Computation of gradients

    +

    Using autograd

    -This in turn means that the gradient can be -computed as a sum over \( i \)-gradients -$$ -\nabla_\beta C(\mathbf{\beta}) = \sum_i^n \nabla_\beta c_i(\mathbf{x}_i, -\mathbf{\beta}). -$$ +Here we +experiment with what kind of functions Autograd is capable +of finding the gradient of. The following Python functions are just +meant to illustrate what Autograd can do, but please feel free to +experiment with other, possibly more complicated, functions as well.

    -Stochasticity/randomness is introduced by only taking the -gradient on a subset of the data called minibatches. If there are \( n \) -data points and the size of each minibatch is \( M \), there will be \( n/M \) -minibatches. We denote these minibatches by \( B_k \) where -\( k=1,\cdots,n/M \). + +

    import autograd.numpy as np
    +from autograd import grad
    +
    +def f1(x):
    +    return x**3 + 1
    +
    +f1_grad = grad(f1)
    +
    +# Remember to send in float as argument to the computed gradient from Autograd!
    +a = 1.0
    +
    +# See the evaluated gradient at a using autograd:
    +print("The gradient of f1 evaluated at a = %g using autograd is: %g"%(a,f1_grad(a)))
    +
    +# Compare with the analytical derivative, that is f1'(x) = 3*x**2 
    +grad_analytical = 3*a**2
    +print("The gradient of f1 evaluated at a = %g by finding the analytic expression is: %g"%(a,grad_analytical))
    +

    @@ -229,6 +274,12 @@ minibatches. We denote these minibatches by \( B_k \) where

  • 40
  • 41
  • 42
  • +
  • 43
  • +
  • 44
  • +
  • 45
  • +
  • 46
  • +
  • ...
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/._Splines-bs037.html b/doc/pub/Splines/html/._Splines-bs037.html new file mode 100644 index 000000000..cc5dac4df --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs037.html @@ -0,0 +1,324 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +

     

     

     

    + + + + +

    Autograd with more complicated functions

    + +

    +To differentiate with respect to two (or more) arguments of a Python +function, Autograd need to know at which variable the function if +being differentiated with respect to. + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f2(x1,x2):
    +    return 3*x1**3 + x2*(x1 - 5) + 1
    +
    +# By sending the argument 0, Autograd will compute the derivative w.r.t the first variable, in this case x1
    +f2_grad_x1 = grad(f2,0)
    +
    +# ... and differentiate w.r.t x2 by sending 1 as an additional arugment to grad
    +f2_grad_x2 = grad(f2,1)
    +
    +x1 = 1.0
    +x2 = 3.0 
    +
    +print("Evaluating at x1 = %g, x2 = %g"%(x1,x2))
    +print("-"*30)
    +
    +# Compare with the analytical derivatives:
    +
    +# Derivative of f2 w.r.t x1 is: 9*x1**2 + x2:
    +f2_grad_x1_analytical = 9*x1**2 + x2
    +
    +# Derivative of f2 w.r.t x2 is: x1 - 5:
    +f2_grad_x2_analytical = x1 - 5
    +
    +# See the evaluated derivations:
    +print("The derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) ))
    +print("The analytical derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) ))
    +
    +print()
    +
    +print("The derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) ))
    +print("The analytical derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) ))
    +
    +

    +Note that the grad function will not produce the true gradient of the function. The true gradient of a function with two or more variables will produce a vector, where each element is the function differentiated w.r.t a variable. + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs038.html b/doc/pub/Splines/html/._Splines-bs038.html new file mode 100644 index 000000000..07991fdf0 --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs038.html @@ -0,0 +1,308 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +

     

     

     

    + + + + +

    More complicated functions using the elements of their arguments directly

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f3(x): # Assumes x is an array of length 5 or higher
    +    return 2*x[0] + 3*x[1] + 5*x[2] + 7*x[3] + 11*x[4]**2
    +
    +f3_grad = grad(f3)
    +
    +x = np.linspace(0,4,5)
    +
    +# Print the computed gradient:
    +print("The computed gradient of f3 is: ", f3_grad(x))
    +
    +# The analytical gradient is: (2, 3, 5, 7, 22*x[4])
    +f3_grad_analytical = np.array([2, 3, 5, 7, 22*x[4]])
    +
    +# Print the analytical gradient:
    +print("The analytical gradient of f3 is: ", f3_grad_analytical)
    +
    +

    +Note that in this case, when sending an array as input argument, the +output from Autograd is another array. This is the true gradient of +the function, as opposed to the function in the previous example. By +using arrays to represent the variables, the output from Autograd +might be easier to work with, as the output is closer to what one +could expect form a gradient-evaluting function. + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs039.html b/doc/pub/Splines/html/._Splines-bs039.html new file mode 100644 index 000000000..046ce035e --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs039.html @@ -0,0 +1,300 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +

     

     

     

    + + + + +

    Functions using mathematical functions from Numpy

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f4(x):
    +    return np.sqrt(1+x**2) + np.exp(x) + np.sin(2*np.pi*x)
    +
    +f4_grad = grad(f4)
    +
    +x = 2.7
    +
    +# Print the computed derivative:
    +print("The computed derivative of f4 at x = %g is: %g"%(x,f4_grad(x)))
    +
    +# The analytical derivative is: x/sqrt(1 + x**2) + exp(x) + cos(2*pi*x)*2*pi
    +f4_grad_analytical = x/np.sqrt(1 + x**2) + np.exp(x) + np.cos(2*np.pi*x)*2*np.pi
    +
    +# Print the analytical gradient:
    +print("The analytical gradient of f4 at x = %g is: %g"%(x,f4_grad_analytical))
    +
    +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs040.html b/doc/pub/Splines/html/._Splines-bs040.html new file mode 100644 index 000000000..95c9e987c --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs040.html @@ -0,0 +1,297 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + +
    + +
    + +

     

     

     

    + + + + +

    More autograd

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f5(x):
    +    if x >= 0:
    +        return x**2
    +    else:
    +        return -3*x + 1
    +
    +f5_grad = grad(f5)
    +
    +x = 2.7
    +
    +# Print the computed derivative:
    +print("The computed derivative of f5 at x = %g is: %g"%(x,f5_grad(x)))
    +
    +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs041.html b/doc/pub/Splines/html/._Splines-bs041.html new file mode 100644 index 000000000..1e1c62f1a --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs041.html @@ -0,0 +1,320 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    And with loops

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f6_for(x):
    +    val = 0
    +    for i in range(10):
    +        val = val + x**i
    +    return val
    +
    +def f6_while(x):
    +    val = 0
    +    i = 0
    +    while i < 10:
    +        val = val + x**i
    +        i = i + 1
    +    return val
    +
    +f6_for_grad = grad(f6_for)
    +f6_while_grad = grad(f6_while)
    +
    +x = 0.5
    +
    +# Print the computed derivaties of f6_for and f6_while
    +print("The computed derivative of f6_for at x = %g is: %g"%(x,f6_for_grad(x)))
    +print("The computed derivative of f6_while at x = %g is: %g"%(x,f6_while_grad(x)))
    +
    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +# Both of the functions are implementation of the sum: sum(x**i) for i = 0, ..., 9
    +# The analytical derivative is: sum(i*x**(i-1)) 
    +f6_grad_analytical = 0
    +for i in range(10):
    +    f6_grad_analytical += i*x**(i-1)
    +
    +print("The analytical derivative of f6 at x = %g is: %g"%(x,f6_grad_analytical))
    +
    +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs042.html b/doc/pub/Splines/html/._Splines-bs042.html new file mode 100644 index 000000000..ad3f9b5c0 --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs042.html @@ -0,0 +1,312 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    Using recursion

    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +
    +def f7(n): # Assume that n is an integer
    +    if n == 1 or n == 0:
    +        return 1
    +    else:
    +        return n*f7(n-1)
    +
    +f7_grad = grad(f7)
    +
    +n = 2.0
    +
    +print("The computed derivative of f7 at n = %d is: %g"%(n,f7_grad(n)))
    +
    +# The function f7 is an implementation of the factorial of n.
    +# By using the product rule, one can find that the derivative is:
    +
    +f7_grad_analytical = 0
    +for i in range(int(n)-1):
    +    tmp = 1
    +    for k in range(int(n)-1):
    +        if k != i:
    +            tmp *= (n - k)
    +    f7_grad_analytical += tmp
    +
    +print("The analytical derivative of f7 at n = %d is: %g"%(n,f7_grad_analytical))
    +
    +

    +Note that if n is equal to zero or one, Autograd will give an error message. This message appears when the output is independent on input. + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs043.html b/doc/pub/Splines/html/._Splines-bs043.html new file mode 100644 index 000000000..5ed7ba8cc --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs043.html @@ -0,0 +1,298 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    Unsupported functions

    +Autograd supports many features. However, there are some functions that is not supported (yet) by Autograd. + +

    +Assigning a value to the variable being differentiated with respect to +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f8(x): # Assume x is an array
    +    x[2] = 3
    +    return x*2
    +
    +f8_grad = grad(f8)
    +
    +x = 8.4
    +
    +print("The derivative of f8 is:",f8_grad(x))
    +
    +

    +Here, Autograd tells us that an 'ArrayBox' does not support item assignment. The item assignment is done when the program tries to assign x[2] to the value 3. However, Autograd has implemented the computation of the derivative such that this assignment is not possible. + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs044.html b/doc/pub/Splines/html/._Splines-bs044.html new file mode 100644 index 000000000..ef4880e16 --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs044.html @@ -0,0 +1,313 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    The syntax a.dot(b) when finding the dot product

    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f9(a): # Assume a is an array with 2 elements
    +    b = np.array([1.0,2.0])
    +    return a.dot(b)
    +
    +f9_grad = grad(f9)
    +
    +x = np.array([1.0,0.0])
    +
    +print("The derivative of f9 is:",f9_grad(x))
    +
    +

    +Here we are told that the 'dot' function does not belong to Autograd's +version of a Numpy array. To overcome this, an alternative syntax +which also computed the dot product can be used: + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f9_alternative(x): # Assume a is an array with 2 elements
    +    b = np.array([1.0,2.0])
    +    return np.dot(x,b) # The same as x_1*b_1 + x_2*b_2
    +
    +f9_alternative_grad = grad(f9_alternative)
    +
    +x = np.array([3.0,0.0])
    +
    +print("The gradient of f9 is:",f9_alternative_grad(x))
    +
    +# The analytical gradient of the dot product of vectors x and b with two elements (x_1,x_2) and (b_1, b_2) respectively
    +# w.r.t x is (b_1, b_2).
    +
    +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs045.html b/doc/pub/Splines/html/._Splines-bs045.html new file mode 100644 index 000000000..2d0455a7f --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs045.html @@ -0,0 +1,283 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    Recommended to avoid

    +The documentation recommends to avoid inplace operations such as +

    + + +

    a += b
    +a -= b
    +a*= b
    +a /=b
    +
    +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs046.html b/doc/pub/Splines/html/._Splines-bs046.html new file mode 100644 index 000000000..b157aa647 --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs046.html @@ -0,0 +1,287 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    Stochastic Gradient Descent

    + +

    +Stochastic gradient descent (SGD) and variants thereof address some of +the shortcomings of the Gradient descent method discussed above. + +

    +The underlying idea of SGD comes from the observation that the cost +function, which we want to minimize, can almost always be written as a +sum over \( n \) data points \( \{\mathbf{x}_i\}_{i=1}^n \), +$$ +C(\mathbf{\beta}) = \sum_{i=1}^n c_i(\mathbf{x}_i, +\mathbf{\beta}). +$$ + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs047.html b/doc/pub/Splines/html/._Splines-bs047.html new file mode 100644 index 000000000..c844607a6 --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs047.html @@ -0,0 +1,288 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    Computation of gradients

    + +

    +This in turn means that the gradient can be +computed as a sum over \( i \)-gradients +$$ +\nabla_\beta C(\mathbf{\beta}) = \sum_i^n \nabla_\beta c_i(\mathbf{x}_i, +\mathbf{\beta}). +$$ + +

    +Stochasticity/randomness is introduced by only taking the +gradient on a subset of the data called minibatches. If there are \( n \) +data points and the size of each minibatch is \( M \), there will be \( n/M \) +minibatches. We denote these minibatches by \( B_k \) where +\( k=1,\cdots,n/M \). + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs048.html b/doc/pub/Splines/html/._Splines-bs048.html new file mode 100644 index 000000000..3f1b4ba5b --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs048.html @@ -0,0 +1,291 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    SGD example

    +As an example, suppose we have \( 10 \) data points \( (\mathbf{x}_1,\cdots, \mathbf{x}_{10}) \) +and we choose to have \( M=5 \) minibathces, +then each minibatch contains two data points. In particular we have +\( B_1 = (\mathbf{x}_1,\mathbf{x}_2), \cdots, B_5 = +(\mathbf{x}_9,\mathbf{x}_{10}) \). Note that if you choose \( M=1 \) you +have only a single batch with all data points and on the other extreme, +you may choose \( M=n \) resulting in a minibatch for each datapoint, i.e +\( B_k = \mathbf{x}_k \). + +

    +The idea is now to approximate the gradient by replacing the sum over +all data points with a sum over the data points in one the minibatches +picked at random in each gradient descent step +$$ +\nabla_{\beta} +C(\mathbf{\beta}) = \sum_{i=1}^n \nabla_\beta c_i(\mathbf{x}_i, +\mathbf{\beta}) \rightarrow \sum_{i \in B_k}^n \nabla_\beta +c_i(\mathbf{x}_i, \mathbf{\beta}). +$$ + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs049.html b/doc/pub/Splines/html/._Splines-bs049.html new file mode 100644 index 000000000..01af73eb0 --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs049.html @@ -0,0 +1,285 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    The gradient step

    + +

    +Thus a gradient descent step now looks like +$$ +\beta_{j+1} = \beta_j - \gamma_j \sum_{i \in B_k}^n \nabla_\beta c_i(\mathbf{x}_i, +\mathbf{\beta}) +$$ + +

    +where \( k \) is picked at random with equal +probability from \( [1,n/M] \). An iteration over the number of +minibathces (n/M) is commonly referred to as an epoch. Thus it is +typical to choose a number of epochs and for each epoch iterate over +the number of minibatches, as exemplified in the code below. + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs050.html b/doc/pub/Splines/html/._Splines-bs050.html new file mode 100644 index 000000000..550fe3e88 --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs050.html @@ -0,0 +1,297 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    Simple example code

    + +

    + + +

    import numpy as np 
    +
    +n = 100 #100 datapoints 
    +M = 5   #size of each minibatch
    +m = int(n/M) #number of minibatches
    +n_epochs = 10 #number of epochs
    +
    +j = 0
    +for epoch in range(1,n_epochs+1):
    +    for i in range(m):
    +        k = np.random.randint(m) #Pick the k-th minibatch at random
    +        #Compute the gradient using the data in minibatch Bk
    +        #Compute new suggestion for 
    +        j += 1
    +
    +

    +Taking the gradient only on a subset of the data has two important +benefits. First, it introduces randomness which decreases the chance +that our opmization scheme gets stuck in a local minima. Second, if +the size of the minibatches are small relative to the number of +datapoints (\( M < n \)), the computation of the gradient is much +cheaper since we sum over the datapoints in the \( k-th \) minibatch and not +all \( n \) datapoints. + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs051.html b/doc/pub/Splines/html/._Splines-bs051.html new file mode 100644 index 000000000..301a7792b --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs051.html @@ -0,0 +1,281 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    When do we stop?

    + +

    +A natural question is when do we stop the search for a new minimum? +One possibility is to compute the full gradient after a given number +of epochs and check if the norm of the gradient is smaller than some +threshold and stop if true. However, the condition that the gradient +is zero is valid also for local minima, so this would only tell us +that we are close to a local/global minimum. However, we could also +evaluate the cost function at this point, store the result and +continue the search. If the test kicks in at a later stage we can +compare the values of the cost function and keep the \( \beta \) that +gave the lowest value. + +

    +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/._Splines-bs052.html b/doc/pub/Splines/html/._Splines-bs052.html new file mode 100644 index 000000000..7c61f2b94 --- /dev/null +++ b/doc/pub/Splines/html/._Splines-bs052.html @@ -0,0 +1,311 @@ + + + + + + + +Data Analysis and Machine Learning Lectures: Optimization and Gradient Methods + + + + + + + + + + + + + + + + + + + + + + + + + + +
    + +

     

     

     

    + + + + +

    Slightly different approach

    + +

    +Another approach is to let the step length \( \gamma_j \) depend on the +number of epochs in such a way that it becomes very small after a +reasonable time such that we do not move at all. + +

    +As an example, let \( e = 0,1,2,3,\cdots \) denote the current epoch and let \( t_0, t_1 > 0 \) be two fixed numbers. Furthermore, let \( t = e \cdot m + i \) where \( m \) is the number of minibatches and \( i=0,\cdots,m-1 \). Then the function $$\gamma_j(t; t_0, t_1) = \frac{t_0}{t+t_1} $$ goes to zero as the number of epochs gets large. I.e. we start with a step length \( \gamma_j (0; t_0, t_1) = t_0/t_1 \) which decays in time \( t \). + +

    +In this way we can fix the number of epochs, compute \( \beta \) and +evaluate the cost function at the end. Repeating the computation will +give a different result since the scheme is random by design. Then we +pick the final \( \beta \) that gives the lowest value of the cost +function. + +

    + + +

    import numpy as np 
    +
    +def step_length(t,t0,t1):
    +    return t0/(t+t1)
    +
    +n = 100 #100 datapoints 
    +M = 5   #size of each minibatch
    +m = int(n/M) #number of minibatches
    +n_epochs = 500 #number of epochs
    +t0 = 1.0
    +t1 = 10
    +
    +gamma_j = t0/t1
    +j = 0
    +for epoch in range(1,n_epochs+1):
    +    for i in range(m):
    +        k = np.random.randint(m) #Pick the k-th minibatch at random
    +        #Compute the gradient using the data in minibatch Bk
    +        #Compute new suggestion for beta
    +        t = epoch*m+i
    +        gamma_j = step_length(t,t0,t1)
    +        j += 1
    +
    +print("gamma_j after %d epochs: %g" % (n_epochs,gamma_j))
    +
    +

    + +

    + +

    + + +
    + + + + + + + +
    + +
    + + + + + + diff --git a/doc/pub/Splines/html/Splines-bs.html b/doc/pub/Splines/html/Splines-bs.html index c216dd1d9..eb965b485 100644 --- a/doc/pub/Splines/html/Splines-bs.html +++ b/doc/pub/Splines/html/Splines-bs.html @@ -70,16 +70,16 @@ Automatically generated HTML file from DocOnce source ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -91,13 +91,34 @@ Automatically generated HTML file from DocOnce source None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -158,9 +179,9 @@ MathJax.Hub.Config({
  • Steepest descent method
  • Gradient descent method
  • Final expressions
  • -
  • The Steepest descent algorithm
  • -
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • -
  • The routine for the steepest descent method
  • +
  • Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come
  • +
  • The routine for the steepest descent method
  • +
  • Steepest descent example
  • Revisiting our first homework
  • Gradient descent example
  • The derivative of the cost/loss function
  • @@ -169,13 +190,24 @@ MathJax.Hub.Config({
  • Gradient Descent Example
  • And a corresponding example using scikit-learn
  • Gradient descent and Ridge
  • -
  • Stochastic Gradient Descent
  • -
  • Computation of gradients
  • -
  • SGD example
  • -
  • The gradient step
  • -
  • Simple example code
  • -
  • When do we stop?
  • -
  • Slightly different approach
  • +
  • Automatic differentiation
  • +
  • Using autograd
  • +
  • Autograd with more complicated functions
  • +
  • More complicated functions using the elements of their arguments directly
  • +
  • Functions using mathematical functions from Numpy
  • +
  • More autograd
  • +
  • And with loops
  • +
  • Using recursion
  • +
  • Unsupported functions
  • +
  • The syntax a.dot(b) when finding the dot product
  • +
  • Recommended to avoid
  • +
  • Stochastic Gradient Descent
  • +
  • Computation of gradients
  • +
  • SGD example
  • +
  • The gradient step
  • +
  • Simple example code
  • +
  • When do we stop?
  • +
  • Slightly different approach
  • @@ -234,7 +266,7 @@ MathJax.Hub.Config({
  • 9
  • 10
  • ...
  • -
  • 42
  • +
  • 53
  • »
  • diff --git a/doc/pub/Splines/html/Splines-reveal.html b/doc/pub/Splines/html/Splines-reveal.html index 37fcca28c..7e0d32494 100644 --- a/doc/pub/Splines/html/Splines-reveal.html +++ b/doc/pub/Splines/html/Splines-reveal.html @@ -818,12 +818,7 @@ $$
    -

    The Steepest descent algorithm

    -
    - - -
    -

    Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come

    +

    Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come

    @@ -861,7 +856,7 @@ $$

    -

    The routine for the steepest descent method

    +

    The routine for the steepest descent method

    @@ -894,6 +889,76 @@ $$

    +
    +

    Steepest descent example

    + +

    + + +

    import numpy as np
    +import numpy.linalg as la
    +
    +import scipy.optimize as sopt
    +
    +import matplotlib.pyplot as pt
    +from mpl_toolkits.mplot3d import axes3d
    +
    +def f(x):
    +    return 0.5*x[0]**2 + 2.5*x[1]**2
    +
    +def df(x):
    +    return np.array([x[0], 5*x[1]])
    +
    +fig = pt.figure()
    +ax = fig.gca(projection="3d")
    +
    +xmesh, ymesh = np.mgrid[-2:2:50j,-2:2:50j]
    +fmesh = f(np.array([xmesh, ymesh]))
    +ax.plot_surface(xmesh, ymesh, fmesh)
    +
    +

    +And then as countor plot +

    + + +

    pt.axis("equal")
    +pt.contour(xmesh, ymesh, fmesh)
    +guesses = [np.array([2, 2./5])]
    +
    +

    +Find guesses +

    + + +

    x = guesses[-1]
    +s = -df(x)
    +
    +

    +Run it! +

    + + +

    def f1d(alpha):
    +    return f(x + alpha*s)
    +
    +alpha_opt = sopt.golden(f1d)
    +next_guess = x + alpha_opt * s
    +guesses.append(next_guess)
    +print(next_guess)
    +
    +

    +What happened? +

    + + +

    pt.axis("equal")
    +pt.contour(xmesh, ymesh, fmesh, 50)
    +it_array = np.array(guesses)
    +pt.plot(it_array.T[0], it_array.T[1], "x-")
    +
    +
    + +

    Revisiting our first homework

    @@ -1180,7 +1245,404 @@ beta_ridge = np.dot(Z,np.dot(X.T,y))
    -

    Stochastic Gradient Descent

    +

    Automatic differentiation

    +Python has tools for so-called automatic differentiation. +Consider the following example +

     
    +$$ +f(x) = \sin\left(2\pi x + x^2\right) +$$ +

     
    + +which has the following derivative +

     
    +$$ +f'(x) = \cos\left(2\pi x + x^2\right)\left(2\pi + 2x\right) +$$ +

     
    + +Using autograd we have + +

    + + +

    import autograd.numpy as np
    +
    +# To do elementwise differentiation:
    +from autograd import elementwise_grad as egrad 
    +
    +# To plot:
    +import matplotlib.pyplot as plt 
    +
    +
    +def f(x):
    +    return np.sin(2*np.pi*x + x**2)
    +
    +def f_grad_analytic(x):
    +    return np.cos(2*np.pi*x + x**2)*(2*np.pi + 2*x)
    +
    +# Do the comparison:
    +x = np.linspace(0,1,1000)
    +
    +f_grad = egrad(f)
    +
    +computed = f_grad(x)
    +analytic = f_grad_analytic(x)
    +
    +plt.title('Derivative computed from Autograd compared with the analytical derivative')
    +plt.plot(x,computed,label='autograd')
    +plt.plot(x,analytic,label='analytic')
    +
    +plt.xlabel('x')
    +plt.ylabel('y')
    +plt.legend()
    +
    +plt.show()
    +
    +print("The max absolute difference is: %g"%(np.max(np.abs(computed - analytic))))
    +
    +
    + + +
    +

    Using autograd

    + +

    +Here we +experiment with what kind of functions Autograd is capable +of finding the gradient of. The following Python functions are just +meant to illustrate what Autograd can do, but please feel free to +experiment with other, possibly more complicated, functions as well. + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +
    +def f1(x):
    +    return x**3 + 1
    +
    +f1_grad = grad(f1)
    +
    +# Remember to send in float as argument to the computed gradient from Autograd!
    +a = 1.0
    +
    +# See the evaluated gradient at a using autograd:
    +print("The gradient of f1 evaluated at a = %g using autograd is: %g"%(a,f1_grad(a)))
    +
    +# Compare with the analytical derivative, that is f1'(x) = 3*x**2 
    +grad_analytical = 3*a**2
    +print("The gradient of f1 evaluated at a = %g by finding the analytic expression is: %g"%(a,grad_analytical))
    +
    +
    + + +
    +

    Autograd with more complicated functions

    + +

    +To differentiate with respect to two (or more) arguments of a Python +function, Autograd need to know at which variable the function if +being differentiated with respect to. + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f2(x1,x2):
    +    return 3*x1**3 + x2*(x1 - 5) + 1
    +
    +# By sending the argument 0, Autograd will compute the derivative w.r.t the first variable, in this case x1
    +f2_grad_x1 = grad(f2,0)
    +
    +# ... and differentiate w.r.t x2 by sending 1 as an additional arugment to grad
    +f2_grad_x2 = grad(f2,1)
    +
    +x1 = 1.0
    +x2 = 3.0 
    +
    +print("Evaluating at x1 = %g, x2 = %g"%(x1,x2))
    +print("-"*30)
    +
    +# Compare with the analytical derivatives:
    +
    +# Derivative of f2 w.r.t x1 is: 9*x1**2 + x2:
    +f2_grad_x1_analytical = 9*x1**2 + x2
    +
    +# Derivative of f2 w.r.t x2 is: x1 - 5:
    +f2_grad_x2_analytical = x1 - 5
    +
    +# See the evaluated derivations:
    +print("The derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) ))
    +print("The analytical derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) ))
    +
    +print()
    +
    +print("The derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) ))
    +print("The analytical derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) ))
    +
    +

    +Note that the grad function will not produce the true gradient of the function. The true gradient of a function with two or more variables will produce a vector, where each element is the function differentiated w.r.t a variable. +

    + + +
    +

    More complicated functions using the elements of their arguments directly

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f3(x): # Assumes x is an array of length 5 or higher
    +    return 2*x[0] + 3*x[1] + 5*x[2] + 7*x[3] + 11*x[4]**2
    +
    +f3_grad = grad(f3)
    +
    +x = np.linspace(0,4,5)
    +
    +# Print the computed gradient:
    +print("The computed gradient of f3 is: ", f3_grad(x))
    +
    +# The analytical gradient is: (2, 3, 5, 7, 22*x[4])
    +f3_grad_analytical = np.array([2, 3, 5, 7, 22*x[4]])
    +
    +# Print the analytical gradient:
    +print("The analytical gradient of f3 is: ", f3_grad_analytical)
    +
    +

    +Note that in this case, when sending an array as input argument, the +output from Autograd is another array. This is the true gradient of +the function, as opposed to the function in the previous example. By +using arrays to represent the variables, the output from Autograd +might be easier to work with, as the output is closer to what one +could expect form a gradient-evaluting function. +

    + + +
    +

    Functions using mathematical functions from Numpy

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f4(x):
    +    return np.sqrt(1+x**2) + np.exp(x) + np.sin(2*np.pi*x)
    +
    +f4_grad = grad(f4)
    +
    +x = 2.7
    +
    +# Print the computed derivative:
    +print("The computed derivative of f4 at x = %g is: %g"%(x,f4_grad(x)))
    +
    +# The analytical derivative is: x/sqrt(1 + x**2) + exp(x) + cos(2*pi*x)*2*pi
    +f4_grad_analytical = x/np.sqrt(1 + x**2) + np.exp(x) + np.cos(2*np.pi*x)*2*np.pi
    +
    +# Print the analytical gradient:
    +print("The analytical gradient of f4 at x = %g is: %g"%(x,f4_grad_analytical))
    +
    +
    + + +
    +

    More autograd

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f5(x):
    +    if x >= 0:
    +        return x**2
    +    else:
    +        return -3*x + 1
    +
    +f5_grad = grad(f5)
    +
    +x = 2.7
    +
    +# Print the computed derivative:
    +print("The computed derivative of f5 at x = %g is: %g"%(x,f5_grad(x)))
    +
    +
    + + +
    +

    And with loops

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f6_for(x):
    +    val = 0
    +    for i in range(10):
    +        val = val + x**i
    +    return val
    +
    +def f6_while(x):
    +    val = 0
    +    i = 0
    +    while i < 10:
    +        val = val + x**i
    +        i = i + 1
    +    return val
    +
    +f6_for_grad = grad(f6_for)
    +f6_while_grad = grad(f6_while)
    +
    +x = 0.5
    +
    +# Print the computed derivaties of f6_for and f6_while
    +print("The computed derivative of f6_for at x = %g is: %g"%(x,f6_for_grad(x)))
    +print("The computed derivative of f6_while at x = %g is: %g"%(x,f6_while_grad(x)))
    +
    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +# Both of the functions are implementation of the sum: sum(x**i) for i = 0, ..., 9
    +# The analytical derivative is: sum(i*x**(i-1)) 
    +f6_grad_analytical = 0
    +for i in range(10):
    +    f6_grad_analytical += i*x**(i-1)
    +
    +print("The analytical derivative of f6 at x = %g is: %g"%(x,f6_grad_analytical))
    +
    +
    + + +
    +

    Using recursion

    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +
    +def f7(n): # Assume that n is an integer
    +    if n == 1 or n == 0:
    +        return 1
    +    else:
    +        return n*f7(n-1)
    +
    +f7_grad = grad(f7)
    +
    +n = 2.0
    +
    +print("The computed derivative of f7 at n = %d is: %g"%(n,f7_grad(n)))
    +
    +# The function f7 is an implementation of the factorial of n.
    +# By using the product rule, one can find that the derivative is:
    +
    +f7_grad_analytical = 0
    +for i in range(int(n)-1):
    +    tmp = 1
    +    for k in range(int(n)-1):
    +        if k != i:
    +            tmp *= (n - k)
    +    f7_grad_analytical += tmp
    +
    +print("The analytical derivative of f7 at n = %d is: %g"%(n,f7_grad_analytical))
    +
    +

    +Note that if n is equal to zero or one, Autograd will give an error message. This message appears when the output is independent on input. +

    + + +
    +

    Unsupported functions

    +Autograd supports many features. However, there are some functions that is not supported (yet) by Autograd. + +

    +Assigning a value to the variable being differentiated with respect to +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f8(x): # Assume x is an array
    +    x[2] = 3
    +    return x*2
    +
    +f8_grad = grad(f8)
    +
    +x = 8.4
    +
    +print("The derivative of f8 is:",f8_grad(x))
    +
    +

    +Here, Autograd tells us that an 'ArrayBox' does not support item assignment. The item assignment is done when the program tries to assign x[2] to the value 3. However, Autograd has implemented the computation of the derivative such that this assignment is not possible. +

    + + +
    +

    The syntax a.dot(b) when finding the dot product

    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f9(a): # Assume a is an array with 2 elements
    +    b = np.array([1.0,2.0])
    +    return a.dot(b)
    +
    +f9_grad = grad(f9)
    +
    +x = np.array([1.0,0.0])
    +
    +print("The derivative of f9 is:",f9_grad(x))
    +
    +

    +Here we are told that the 'dot' function does not belong to Autograd's +version of a Numpy array. To overcome this, an alternative syntax +which also computed the dot product can be used: + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f9_alternative(x): # Assume a is an array with 2 elements
    +    b = np.array([1.0,2.0])
    +    return np.dot(x,b) # The same as x_1*b_1 + x_2*b_2
    +
    +f9_alternative_grad = grad(f9_alternative)
    +
    +x = np.array([3.0,0.0])
    +
    +print("The gradient of f9 is:",f9_alternative_grad(x))
    +
    +# The analytical gradient of the dot product of vectors x and b with two elements (x_1,x_2) and (b_1, b_2) respectively
    +# w.r.t x is (b_1, b_2).
    +
    +
    + + +
    +

    Recommended to avoid

    +The documentation recommends to avoid inplace operations such as +

    + + +

    a += b
    +a -= b
    +a*= b
    +a /=b
    +
    +
    + + +
    +

    Stochastic Gradient Descent

    Stochastic gradient descent (SGD) and variants thereof address some of @@ -1200,7 +1662,7 @@ $$

    -

    Computation of gradients

    +

    Computation of gradients

    This in turn means that the gradient can be @@ -1222,7 +1684,7 @@ minibatches. We denote these minibatches by \( B_k \) where

    -

    SGD example

    +

    SGD example

    As an example, suppose we have \( 10 \) data points \( (\mathbf{x}_1,\cdots, \mathbf{x}_{10}) \) and we choose to have \( M=5 \) minibathces, then each minibatch contains two data points. In particular we have @@ -1248,7 +1710,7 @@ $$
    -

    The gradient step

    +

    The gradient step

    Thus a gradient descent step now looks like @@ -1269,7 +1731,7 @@ the number of minibatches, as exemplified in the code below.

    -

    Simple example code

    +

    Simple example code

    @@ -1301,7 +1763,7 @@ all \( n \) datapoints.

    -

    When do we stop?

    +

    When do we stop?

    A natural question is when do we stop the search for a new minimum? @@ -1318,7 +1780,7 @@ gave the lowest value.

    -

    Slightly different approach

    +

    Slightly different approach

    Another approach is to let the step length \( \gamma_j \) depend on the diff --git a/doc/pub/Splines/html/Splines-solarized.html b/doc/pub/Splines/html/Splines-solarized.html index 663120f72..03500a8a5 100644 --- a/doc/pub/Splines/html/Splines-solarized.html +++ b/doc/pub/Splines/html/Splines-solarized.html @@ -90,16 +90,16 @@ div { text-align: justify; text-justify: inter-word; } ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -111,13 +111,34 @@ div { text-align: justify; text-justify: inter-word; } None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -767,12 +788,7 @@ $$











    -

    The Steepest descent algorithm

    - -

    -









    - -

    Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come

    +

    Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come

    @@ -812,7 +828,7 @@ $$











    -

    The routine for the steepest descent method

    +

    The routine for the steepest descent method

    @@ -845,6 +861,75 @@ $$

    +

    +









    + +

    Steepest descent example

    + +

    + + +

    import numpy as np
    +import numpy.linalg as la
    +
    +import scipy.optimize as sopt
    +
    +import matplotlib.pyplot as pt
    +from mpl_toolkits.mplot3d import axes3d
    +
    +def f(x):
    +    return 0.5*x[0]**2 + 2.5*x[1]**2
    +
    +def df(x):
    +    return np.array([x[0], 5*x[1]])
    +
    +fig = pt.figure()
    +ax = fig.gca(projection="3d")
    +
    +xmesh, ymesh = np.mgrid[-2:2:50j,-2:2:50j]
    +fmesh = f(np.array([xmesh, ymesh]))
    +ax.plot_surface(xmesh, ymesh, fmesh)
    +
    +

    +And then as countor plot +

    + + +

    pt.axis("equal")
    +pt.contour(xmesh, ymesh, fmesh)
    +guesses = [np.array([2, 2./5])]
    +
    +

    +Find guesses +

    + + +

    x = guesses[-1]
    +s = -df(x)
    +
    +

    +Run it! +

    + + +

    def f1d(alpha):
    +    return f(x + alpha*s)
    +
    +alpha_opt = sopt.golden(f1d)
    +next_guess = x + alpha_opt * s
    +guesses.append(next_guess)
    +print(next_guess)
    +
    +

    +What happened? +

    + + +

    pt.axis("equal")
    +pt.contour(xmesh, ymesh, fmesh, 50)
    +it_array = np.array(guesses)
    +pt.plot(it_array.T[0], it_array.T[1], "x-")
    +

    @@ -1106,7 +1191,393 @@ beta_ridge = np.dot(Z,np.dot(X.T,y))











    -

    Stochastic Gradient Descent

    +

    Automatic differentiation

    +Python has tools for so-called automatic differentiation. +Consider the following example +$$ +f(x) = \sin\left(2\pi x + x^2\right) +$$ + +which has the following derivative +$$ +f'(x) = \cos\left(2\pi x + x^2\right)\left(2\pi + 2x\right) +$$ + +Using autograd we have + +

    + + +

    import autograd.numpy as np
    +
    +# To do elementwise differentiation:
    +from autograd import elementwise_grad as egrad 
    +
    +# To plot:
    +import matplotlib.pyplot as plt 
    +
    +
    +def f(x):
    +    return np.sin(2*np.pi*x + x**2)
    +
    +def f_grad_analytic(x):
    +    return np.cos(2*np.pi*x + x**2)*(2*np.pi + 2*x)
    +
    +# Do the comparison:
    +x = np.linspace(0,1,1000)
    +
    +f_grad = egrad(f)
    +
    +computed = f_grad(x)
    +analytic = f_grad_analytic(x)
    +
    +plt.title('Derivative computed from Autograd compared with the analytical derivative')
    +plt.plot(x,computed,label='autograd')
    +plt.plot(x,analytic,label='analytic')
    +
    +plt.xlabel('x')
    +plt.ylabel('y')
    +plt.legend()
    +
    +plt.show()
    +
    +print("The max absolute difference is: %g"%(np.max(np.abs(computed - analytic))))
    +
    +

    + + +

    Using autograd

    + +

    +Here we +experiment with what kind of functions Autograd is capable +of finding the gradient of. The following Python functions are just +meant to illustrate what Autograd can do, but please feel free to +experiment with other, possibly more complicated, functions as well. + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +
    +def f1(x):
    +    return x**3 + 1
    +
    +f1_grad = grad(f1)
    +
    +# Remember to send in float as argument to the computed gradient from Autograd!
    +a = 1.0
    +
    +# See the evaluated gradient at a using autograd:
    +print("The gradient of f1 evaluated at a = %g using autograd is: %g"%(a,f1_grad(a)))
    +
    +# Compare with the analytical derivative, that is f1'(x) = 3*x**2 
    +grad_analytical = 3*a**2
    +print("The gradient of f1 evaluated at a = %g by finding the analytic expression is: %g"%(a,grad_analytical))
    +
    +

    +









    + +

    Autograd with more complicated functions

    + +

    +To differentiate with respect to two (or more) arguments of a Python +function, Autograd need to know at which variable the function if +being differentiated with respect to. + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f2(x1,x2):
    +    return 3*x1**3 + x2*(x1 - 5) + 1
    +
    +# By sending the argument 0, Autograd will compute the derivative w.r.t the first variable, in this case x1
    +f2_grad_x1 = grad(f2,0)
    +
    +# ... and differentiate w.r.t x2 by sending 1 as an additional arugment to grad
    +f2_grad_x2 = grad(f2,1)
    +
    +x1 = 1.0
    +x2 = 3.0 
    +
    +print("Evaluating at x1 = %g, x2 = %g"%(x1,x2))
    +print("-"*30)
    +
    +# Compare with the analytical derivatives:
    +
    +# Derivative of f2 w.r.t x1 is: 9*x1**2 + x2:
    +f2_grad_x1_analytical = 9*x1**2 + x2
    +
    +# Derivative of f2 w.r.t x2 is: x1 - 5:
    +f2_grad_x2_analytical = x1 - 5
    +
    +# See the evaluated derivations:
    +print("The derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) ))
    +print("The analytical derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) ))
    +
    +print()
    +
    +print("The derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) ))
    +print("The analytical derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) ))
    +
    +

    +Note that the grad function will not produce the true gradient of the function. The true gradient of a function with two or more variables will produce a vector, where each element is the function differentiated w.r.t a variable. + +

    +









    + +

    More complicated functions using the elements of their arguments directly

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f3(x): # Assumes x is an array of length 5 or higher
    +    return 2*x[0] + 3*x[1] + 5*x[2] + 7*x[3] + 11*x[4]**2
    +
    +f3_grad = grad(f3)
    +
    +x = np.linspace(0,4,5)
    +
    +# Print the computed gradient:
    +print("The computed gradient of f3 is: ", f3_grad(x))
    +
    +# The analytical gradient is: (2, 3, 5, 7, 22*x[4])
    +f3_grad_analytical = np.array([2, 3, 5, 7, 22*x[4]])
    +
    +# Print the analytical gradient:
    +print("The analytical gradient of f3 is: ", f3_grad_analytical)
    +
    +

    +Note that in this case, when sending an array as input argument, the +output from Autograd is another array. This is the true gradient of +the function, as opposed to the function in the previous example. By +using arrays to represent the variables, the output from Autograd +might be easier to work with, as the output is closer to what one +could expect form a gradient-evaluting function. + +

    + + +

    Functions using mathematical functions from Numpy

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f4(x):
    +    return np.sqrt(1+x**2) + np.exp(x) + np.sin(2*np.pi*x)
    +
    +f4_grad = grad(f4)
    +
    +x = 2.7
    +
    +# Print the computed derivative:
    +print("The computed derivative of f4 at x = %g is: %g"%(x,f4_grad(x)))
    +
    +# The analytical derivative is: x/sqrt(1 + x**2) + exp(x) + cos(2*pi*x)*2*pi
    +f4_grad_analytical = x/np.sqrt(1 + x**2) + np.exp(x) + np.cos(2*np.pi*x)*2*np.pi
    +
    +# Print the analytical gradient:
    +print("The analytical gradient of f4 at x = %g is: %g"%(x,f4_grad_analytical))
    +
    +

    +









    + +

    More autograd

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f5(x):
    +    if x >= 0:
    +        return x**2
    +    else:
    +        return -3*x + 1
    +
    +f5_grad = grad(f5)
    +
    +x = 2.7
    +
    +# Print the computed derivative:
    +print("The computed derivative of f5 at x = %g is: %g"%(x,f5_grad(x)))
    +
    +

    +









    + +

    And with loops

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f6_for(x):
    +    val = 0
    +    for i in range(10):
    +        val = val + x**i
    +    return val
    +
    +def f6_while(x):
    +    val = 0
    +    i = 0
    +    while i < 10:
    +        val = val + x**i
    +        i = i + 1
    +    return val
    +
    +f6_for_grad = grad(f6_for)
    +f6_while_grad = grad(f6_while)
    +
    +x = 0.5
    +
    +# Print the computed derivaties of f6_for and f6_while
    +print("The computed derivative of f6_for at x = %g is: %g"%(x,f6_for_grad(x)))
    +print("The computed derivative of f6_while at x = %g is: %g"%(x,f6_while_grad(x)))
    +
    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +# Both of the functions are implementation of the sum: sum(x**i) for i = 0, ..., 9
    +# The analytical derivative is: sum(i*x**(i-1)) 
    +f6_grad_analytical = 0
    +for i in range(10):
    +    f6_grad_analytical += i*x**(i-1)
    +
    +print("The analytical derivative of f6 at x = %g is: %g"%(x,f6_grad_analytical))
    +
    +

    +









    + +

    Using recursion

    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +
    +def f7(n): # Assume that n is an integer
    +    if n == 1 or n == 0:
    +        return 1
    +    else:
    +        return n*f7(n-1)
    +
    +f7_grad = grad(f7)
    +
    +n = 2.0
    +
    +print("The computed derivative of f7 at n = %d is: %g"%(n,f7_grad(n)))
    +
    +# The function f7 is an implementation of the factorial of n.
    +# By using the product rule, one can find that the derivative is:
    +
    +f7_grad_analytical = 0
    +for i in range(int(n)-1):
    +    tmp = 1
    +    for k in range(int(n)-1):
    +        if k != i:
    +            tmp *= (n - k)
    +    f7_grad_analytical += tmp
    +
    +print("The analytical derivative of f7 at n = %d is: %g"%(n,f7_grad_analytical))
    +
    +

    +Note that if n is equal to zero or one, Autograd will give an error message. This message appears when the output is independent on input. + +

    +









    + +

    Unsupported functions

    +Autograd supports many features. However, there are some functions that is not supported (yet) by Autograd. + +

    +Assigning a value to the variable being differentiated with respect to +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f8(x): # Assume x is an array
    +    x[2] = 3
    +    return x*2
    +
    +f8_grad = grad(f8)
    +
    +x = 8.4
    +
    +print("The derivative of f8 is:",f8_grad(x))
    +
    +

    +Here, Autograd tells us that an 'ArrayBox' does not support item assignment. The item assignment is done when the program tries to assign x[2] to the value 3. However, Autograd has implemented the computation of the derivative such that this assignment is not possible. + +

    +









    + +

    The syntax a.dot(b) when finding the dot product

    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f9(a): # Assume a is an array with 2 elements
    +    b = np.array([1.0,2.0])
    +    return a.dot(b)
    +
    +f9_grad = grad(f9)
    +
    +x = np.array([1.0,0.0])
    +
    +print("The derivative of f9 is:",f9_grad(x))
    +
    +

    +Here we are told that the 'dot' function does not belong to Autograd's +version of a Numpy array. To overcome this, an alternative syntax +which also computed the dot product can be used: + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f9_alternative(x): # Assume a is an array with 2 elements
    +    b = np.array([1.0,2.0])
    +    return np.dot(x,b) # The same as x_1*b_1 + x_2*b_2
    +
    +f9_alternative_grad = grad(f9_alternative)
    +
    +x = np.array([3.0,0.0])
    +
    +print("The gradient of f9 is:",f9_alternative_grad(x))
    +
    +# The analytical gradient of the dot product of vectors x and b with two elements (x_1,x_2) and (b_1, b_2) respectively
    +# w.r.t x is (b_1, b_2).
    +
    +

    +









    + +

    Recommended to avoid

    +The documentation recommends to avoid inplace operations such as +

    + + +

    a += b
    +a -= b
    +a*= b
    +a /=b
    +
    +

    +









    + +

    Stochastic Gradient Descent

    Stochastic gradient descent (SGD) and variants thereof address some of @@ -1124,7 +1595,7 @@ $$











    -

    Computation of gradients

    +

    Computation of gradients

    This in turn means that the gradient can be @@ -1144,7 +1615,7 @@ minibatches. We denote these minibatches by \( B_k \) where











    -

    SGD example

    +

    SGD example

    As an example, suppose we have \( 10 \) data points \( (\mathbf{x}_1,\cdots, \mathbf{x}_{10}) \) and we choose to have \( M=5 \) minibathces, then each minibatch contains two data points. In particular we have @@ -1168,7 +1639,7 @@ $$











    -

    The gradient step

    +

    The gradient step

    Thus a gradient descent step now looks like @@ -1187,7 +1658,7 @@ the number of minibatches, as exemplified in the code below.











    -

    Simple example code

    +

    Simple example code

    @@ -1219,7 +1690,7 @@ all \( n \) datapoints.











    -

    When do we stop?

    +

    When do we stop?

    A natural question is when do we stop the search for a new minimum? @@ -1236,7 +1707,7 @@ gave the lowest value.











    -

    Slightly different approach

    +

    Slightly different approach

    Another approach is to let the step length \( \gamma_j \) depend on the diff --git a/doc/pub/Splines/html/Splines.html b/doc/pub/Splines/html/Splines.html index 30682d1e4..732af37d2 100644 --- a/doc/pub/Splines/html/Splines.html +++ b/doc/pub/Splines/html/Splines.html @@ -95,16 +95,16 @@ div { text-align: justify; text-justify: inter-word; } ('Steepest descent method', 2, None, '___sec20'), ('Gradient descent method', 2, None, '___sec21'), ('Final expressions', 2, None, '___sec22'), - ('The Steepest descent algorithm', 2, None, '___sec23'), ('Simple codes for steepest descent and conjugate gradient ' 'using a $2\\times 2$ matrix, in c++, Python code to come', 2, None, - '___sec24'), + '___sec23'), ('The routine for the steepest descent method', 2, None, - '___sec25'), + '___sec24'), + ('Steepest descent example', 2, None, '___sec25'), ('Revisiting our first homework', 2, None, '___sec26'), ('Gradient descent example', 2, None, '___sec27'), ('The derivative of the cost/loss function', 2, None, '___sec28'), @@ -116,13 +116,34 @@ div { text-align: justify; text-justify: inter-word; } None, '___sec32'), ('Gradient descent and Ridge', 2, None, '___sec33'), - ('Stochastic Gradient Descent', 2, None, '___sec34'), - ('Computation of gradients', 2, None, '___sec35'), - ('SGD example', 2, None, '___sec36'), - ('The gradient step', 2, None, '___sec37'), - ('Simple example code', 2, None, '___sec38'), - ('When do we stop?', 2, None, '___sec39'), - ('Slightly different approach', 2, None, '___sec40')]} + ('Automatic differentiation', 2, None, '___sec34'), + ('Using autograd', 2, None, '___sec35'), + ('Autograd with more complicated functions', 2, None, '___sec36'), + ('More complicated functions using the elements of their ' + 'arguments directly', + 2, + None, + '___sec37'), + ('Functions using mathematical functions from Numpy', + 2, + None, + '___sec38'), + ('More autograd', 2, None, '___sec39'), + ('And with loops', 2, None, '___sec40'), + ('Using recursion', 2, None, '___sec41'), + ('Unsupported functions', 2, None, '___sec42'), + ('The syntax a.dot(b) when finding the dot product', + 2, + None, + '___sec43'), + ('Recommended to avoid', 2, None, '___sec44'), + ('Stochastic Gradient Descent', 2, None, '___sec45'), + ('Computation of gradients', 2, None, '___sec46'), + ('SGD example', 2, None, '___sec47'), + ('The gradient step', 2, None, '___sec48'), + ('Simple example code', 2, None, '___sec49'), + ('When do we stop?', 2, None, '___sec50'), + ('Slightly different approach', 2, None, '___sec51')]} end of tocinfo --> @@ -772,12 +793,7 @@ $$











    -

    The Steepest descent algorithm

    - -

    -









    - -

    Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come

    +

    Simple codes for steepest descent and conjugate gradient using a \( 2\times 2 \) matrix, in c++, Python code to come

    @@ -817,7 +833,7 @@ $$











    -

    The routine for the steepest descent method

    +

    The routine for the steepest descent method

    @@ -850,6 +866,75 @@ $$

    +

    +









    + +

    Steepest descent example

    + +

    + + +

    import numpy as np
    +import numpy.linalg as la
    +
    +import scipy.optimize as sopt
    +
    +import matplotlib.pyplot as pt
    +from mpl_toolkits.mplot3d import axes3d
    +
    +def f(x):
    +    return 0.5*x[0]**2 + 2.5*x[1]**2
    +
    +def df(x):
    +    return np.array([x[0], 5*x[1]])
    +
    +fig = pt.figure()
    +ax = fig.gca(projection="3d")
    +
    +xmesh, ymesh = np.mgrid[-2:2:50j,-2:2:50j]
    +fmesh = f(np.array([xmesh, ymesh]))
    +ax.plot_surface(xmesh, ymesh, fmesh)
    +
    +

    +And then as countor plot +

    + + +

    pt.axis("equal")
    +pt.contour(xmesh, ymesh, fmesh)
    +guesses = [np.array([2, 2./5])]
    +
    +

    +Find guesses +

    + + +

    x = guesses[-1]
    +s = -df(x)
    +
    +

    +Run it! +

    + + +

    def f1d(alpha):
    +    return f(x + alpha*s)
    +
    +alpha_opt = sopt.golden(f1d)
    +next_guess = x + alpha_opt * s
    +guesses.append(next_guess)
    +print(next_guess)
    +
    +

    +What happened? +

    + + +

    pt.axis("equal")
    +pt.contour(xmesh, ymesh, fmesh, 50)
    +it_array = np.array(guesses)
    +pt.plot(it_array.T[0], it_array.T[1], "x-")
    +

    @@ -1111,7 +1196,393 @@ beta_ridge = np











    -

    Stochastic Gradient Descent

    +

    Automatic differentiation

    +Python has tools for so-called automatic differentiation. +Consider the following example +$$ +f(x) = \sin\left(2\pi x + x^2\right) +$$ + +which has the following derivative +$$ +f'(x) = \cos\left(2\pi x + x^2\right)\left(2\pi + 2x\right) +$$ + +Using autograd we have + +

    + + +

    import autograd.numpy as np
    +
    +# To do elementwise differentiation:
    +from autograd import elementwise_grad as egrad 
    +
    +# To plot:
    +import matplotlib.pyplot as plt 
    +
    +
    +def f(x):
    +    return np.sin(2*np.pi*x + x**2)
    +
    +def f_grad_analytic(x):
    +    return np.cos(2*np.pi*x + x**2)*(2*np.pi + 2*x)
    +
    +# Do the comparison:
    +x = np.linspace(0,1,1000)
    +
    +f_grad = egrad(f)
    +
    +computed = f_grad(x)
    +analytic = f_grad_analytic(x)
    +
    +plt.title('Derivative computed from Autograd compared with the analytical derivative')
    +plt.plot(x,computed,label='autograd')
    +plt.plot(x,analytic,label='analytic')
    +
    +plt.xlabel('x')
    +plt.ylabel('y')
    +plt.legend()
    +
    +plt.show()
    +
    +print("The max absolute difference is: %g"%(np.max(np.abs(computed - analytic))))
    +
    +

    + + +

    Using autograd

    + +

    +Here we +experiment with what kind of functions Autograd is capable +of finding the gradient of. The following Python functions are just +meant to illustrate what Autograd can do, but please feel free to +experiment with other, possibly more complicated, functions as well. + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +
    +def f1(x):
    +    return x**3 + 1
    +
    +f1_grad = grad(f1)
    +
    +# Remember to send in float as argument to the computed gradient from Autograd!
    +a = 1.0
    +
    +# See the evaluated gradient at a using autograd:
    +print("The gradient of f1 evaluated at a = %g using autograd is: %g"%(a,f1_grad(a)))
    +
    +# Compare with the analytical derivative, that is f1'(x) = 3*x**2 
    +grad_analytical = 3*a**2
    +print("The gradient of f1 evaluated at a = %g by finding the analytic expression is: %g"%(a,grad_analytical))
    +
    +

    +









    + +

    Autograd with more complicated functions

    + +

    +To differentiate with respect to two (or more) arguments of a Python +function, Autograd need to know at which variable the function if +being differentiated with respect to. + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f2(x1,x2):
    +    return 3*x1**3 + x2*(x1 - 5) + 1
    +
    +# By sending the argument 0, Autograd will compute the derivative w.r.t the first variable, in this case x1
    +f2_grad_x1 = grad(f2,0)
    +
    +# ... and differentiate w.r.t x2 by sending 1 as an additional arugment to grad
    +f2_grad_x2 = grad(f2,1)
    +
    +x1 = 1.0
    +x2 = 3.0 
    +
    +print("Evaluating at x1 = %g, x2 = %g"%(x1,x2))
    +print("-"*30)
    +
    +# Compare with the analytical derivatives:
    +
    +# Derivative of f2 w.r.t x1 is: 9*x1**2 + x2:
    +f2_grad_x1_analytical = 9*x1**2 + x2
    +
    +# Derivative of f2 w.r.t x2 is: x1 - 5:
    +f2_grad_x2_analytical = x1 - 5
    +
    +# See the evaluated derivations:
    +print("The derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) ))
    +print("The analytical derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) ))
    +
    +print()
    +
    +print("The derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) ))
    +print("The analytical derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) ))
    +
    +

    +Note that the grad function will not produce the true gradient of the function. The true gradient of a function with two or more variables will produce a vector, where each element is the function differentiated w.r.t a variable. + +

    +









    + +

    More complicated functions using the elements of their arguments directly

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f3(x): # Assumes x is an array of length 5 or higher
    +    return 2*x[0] + 3*x[1] + 5*x[2] + 7*x[3] + 11*x[4]**2
    +
    +f3_grad = grad(f3)
    +
    +x = np.linspace(0,4,5)
    +
    +# Print the computed gradient:
    +print("The computed gradient of f3 is: ", f3_grad(x))
    +
    +# The analytical gradient is: (2, 3, 5, 7, 22*x[4])
    +f3_grad_analytical = np.array([2, 3, 5, 7, 22*x[4]])
    +
    +# Print the analytical gradient:
    +print("The analytical gradient of f3 is: ", f3_grad_analytical)
    +
    +

    +Note that in this case, when sending an array as input argument, the +output from Autograd is another array. This is the true gradient of +the function, as opposed to the function in the previous example. By +using arrays to represent the variables, the output from Autograd +might be easier to work with, as the output is closer to what one +could expect form a gradient-evaluting function. + +

    + + +

    Functions using mathematical functions from Numpy

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f4(x):
    +    return np.sqrt(1+x**2) + np.exp(x) + np.sin(2*np.pi*x)
    +
    +f4_grad = grad(f4)
    +
    +x = 2.7
    +
    +# Print the computed derivative:
    +print("The computed derivative of f4 at x = %g is: %g"%(x,f4_grad(x)))
    +
    +# The analytical derivative is: x/sqrt(1 + x**2) + exp(x) + cos(2*pi*x)*2*pi
    +f4_grad_analytical = x/np.sqrt(1 + x**2) + np.exp(x) + np.cos(2*np.pi*x)*2*np.pi
    +
    +# Print the analytical gradient:
    +print("The analytical gradient of f4 at x = %g is: %g"%(x,f4_grad_analytical))
    +
    +

    +









    + +

    More autograd

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f5(x):
    +    if x >= 0:
    +        return x**2
    +    else:
    +        return -3*x + 1
    +
    +f5_grad = grad(f5)
    +
    +x = 2.7
    +
    +# Print the computed derivative:
    +print("The computed derivative of f5 at x = %g is: %g"%(x,f5_grad(x)))
    +
    +

    +









    + +

    And with loops

    + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f6_for(x):
    +    val = 0
    +    for i in range(10):
    +        val = val + x**i
    +    return val
    +
    +def f6_while(x):
    +    val = 0
    +    i = 0
    +    while i < 10:
    +        val = val + x**i
    +        i = i + 1
    +    return val
    +
    +f6_for_grad = grad(f6_for)
    +f6_while_grad = grad(f6_while)
    +
    +x = 0.5
    +
    +# Print the computed derivaties of f6_for and f6_while
    +print("The computed derivative of f6_for at x = %g is: %g"%(x,f6_for_grad(x)))
    +print("The computed derivative of f6_while at x = %g is: %g"%(x,f6_while_grad(x)))
    +
    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +# Both of the functions are implementation of the sum: sum(x**i) for i = 0, ..., 9
    +# The analytical derivative is: sum(i*x**(i-1)) 
    +f6_grad_analytical = 0
    +for i in range(10):
    +    f6_grad_analytical += i*x**(i-1)
    +
    +print("The analytical derivative of f6 at x = %g is: %g"%(x,f6_grad_analytical))
    +
    +

    +









    + +

    Using recursion

    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +
    +def f7(n): # Assume that n is an integer
    +    if n == 1 or n == 0:
    +        return 1
    +    else:
    +        return n*f7(n-1)
    +
    +f7_grad = grad(f7)
    +
    +n = 2.0
    +
    +print("The computed derivative of f7 at n = %d is: %g"%(n,f7_grad(n)))
    +
    +# The function f7 is an implementation of the factorial of n.
    +# By using the product rule, one can find that the derivative is:
    +
    +f7_grad_analytical = 0
    +for i in range(int(n)-1):
    +    tmp = 1
    +    for k in range(int(n)-1):
    +        if k != i:
    +            tmp *= (n - k)
    +    f7_grad_analytical += tmp
    +
    +print("The analytical derivative of f7 at n = %d is: %g"%(n,f7_grad_analytical))
    +
    +

    +Note that if n is equal to zero or one, Autograd will give an error message. This message appears when the output is independent on input. + +

    +









    + +

    Unsupported functions

    +Autograd supports many features. However, there are some functions that is not supported (yet) by Autograd. + +

    +Assigning a value to the variable being differentiated with respect to +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f8(x): # Assume x is an array
    +    x[2] = 3
    +    return x*2
    +
    +f8_grad = grad(f8)
    +
    +x = 8.4
    +
    +print("The derivative of f8 is:",f8_grad(x))
    +
    +

    +Here, Autograd tells us that an 'ArrayBox' does not support item assignment. The item assignment is done when the program tries to assign x[2] to the value 3. However, Autograd has implemented the computation of the derivative such that this assignment is not possible. + +

    +









    + +

    The syntax a.dot(b) when finding the dot product

    +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f9(a): # Assume a is an array with 2 elements
    +    b = np.array([1.0,2.0])
    +    return a.dot(b)
    +
    +f9_grad = grad(f9)
    +
    +x = np.array([1.0,0.0])
    +
    +print("The derivative of f9 is:",f9_grad(x))
    +
    +

    +Here we are told that the 'dot' function does not belong to Autograd's +version of a Numpy array. To overcome this, an alternative syntax +which also computed the dot product can be used: + +

    + + +

    import autograd.numpy as np
    +from autograd import grad
    +def f9_alternative(x): # Assume a is an array with 2 elements
    +    b = np.array([1.0,2.0])
    +    return np.dot(x,b) # The same as x_1*b_1 + x_2*b_2
    +
    +f9_alternative_grad = grad(f9_alternative)
    +
    +x = np.array([3.0,0.0])
    +
    +print("The gradient of f9 is:",f9_alternative_grad(x))
    +
    +# The analytical gradient of the dot product of vectors x and b with two elements (x_1,x_2) and (b_1, b_2) respectively
    +# w.r.t x is (b_1, b_2).
    +
    +

    +









    + +

    Recommended to avoid

    +The documentation recommends to avoid inplace operations such as +

    + + +

    a += b
    +a -= b
    +a*= b
    +a /=b
    +
    +

    +









    + +

    Stochastic Gradient Descent

    Stochastic gradient descent (SGD) and variants thereof address some of @@ -1129,7 +1600,7 @@ $$











    -

    Computation of gradients

    +

    Computation of gradients

    This in turn means that the gradient can be @@ -1149,7 +1620,7 @@ minibatches. We denote these minibatches by \( B_k \) where











    -

    SGD example

    +

    SGD example

    As an example, suppose we have \( 10 \) data points \( (\mathbf{x}_1,\cdots, \mathbf{x}_{10}) \) and we choose to have \( M=5 \) minibathces, then each minibatch contains two data points. In particular we have @@ -1173,7 +1644,7 @@ $$











    -

    The gradient step

    +

    The gradient step

    Thus a gradient descent step now looks like @@ -1192,7 +1663,7 @@ the number of minibatches, as exemplified in the code below.











    -

    Simple example code

    +

    Simple example code

    @@ -1224,7 +1695,7 @@ all \( n \) datapoints.











    -

    When do we stop?

    +

    When do we stop?

    A natural question is when do we stop the search for a new minimum? @@ -1241,7 +1712,7 @@ gave the lowest value.











    -

    Slightly different approach

    +

    Slightly different approach

    Another approach is to let the step length \( \gamma_j \) depend on the diff --git a/doc/pub/Splines/ipynb/Splines.ipynb b/doc/pub/Splines/ipynb/Splines.ipynb index b6216c22c..add625871 100644 --- a/doc/pub/Splines/ipynb/Splines.ipynb +++ b/doc/pub/Splines/ipynb/Splines.ipynb @@ -790,9 +790,6 @@ "cell_type": "markdown", "metadata": {}, "source": [ - "## The Steepest descent algorithm\n", - "\n", - "\n", "## Simple codes for steepest descent and conjugate gradient using a $2\\times 2$ matrix, in c++, Python code to come" ] }, @@ -861,6 +858,181 @@ " }\n" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Steepest descent example" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "" + ] + }, + "execution_count": 1, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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09HRwfDw8IyHupows26fz8eKFSsmvWqQZdmarrJlyxaKior41a9+RSQSYevWrbz77rsHLSAnc/4899xz3HLLLZx00kmoqspxxx2HEILbbrvNOubuu++2qIw0jtKAHIuf/exnXHTRRWNuT7YCfKwhPz+f73//+9bvdrudVatWsWrVKq666iqEEHi9XrZt28bmzZu54447LI45VnoX2wQR6/g2uhNOkiRcLhculyuhYqKrq4uGhoa4UVlmoSvW32Pfvn10dXUdFE107ATvWKlcrPa4ra0tjpKZqmOb2aBSUlJCVVVV0ln31q1b+da3vsVFF13EG2+8YRVSD/ZopWTOn9hjFEUhNzeXgYGBT5JH8ScOR2xAPv300+nu7h5z+5133sk///M/W/9XFMXylJgKfve733HLLbdQX19PXV3duEL00tJSK4NTFIWtW7dO+bmOJJgeGZ/97Gf57Gc/CxgBq7Oz0zL4/+lPf0pfX5819mnr1q2WmD+ZDDKRYiI2+LW2tlqjslwuFx6Ph4KCAmpqalIu4TLNehwOxxipnM1mY9asWXH1iVhXud7e3oSucrGt06qq0tjYSDAYnJI/RygU4q677qK2tpZf/vKXLFmyJHUvOo3DhiM2IL/66qsT3v/UU0/x4osv8tprryXMNoqLi9m/f7/1e3t7O8XFxdbvy5cv5w9/+APr16+fdC2vv/76Mb3rS5JEcXExF1xwARdccAFgFGsuvfRSOjs7Wbt2Ld/4xjfQNG2MwX+yAXR08FNVlYaGBoaGhigoKCAYDLJlyxZcLldKRmXFNnhMZYLHeK5yJh9tusq53W4URWFwcJDS0lIWL16cdFZsDvC9+OKLef311w+ajngiTHb+xB5TUlJi+T+nehLK0YYjNiBPhFdeeYUf/OAHvPnmm+PycGvXrqWxsZGWlhaKi4t55pln+PWvf23dn844Zga3282NN94Y54YXCATYvn07dXV1PPDAA1YTRSzVkcwklL6+Ppqampg/fz5LliwZY01qaqZbWlqmNSrL5LpHN3hMF06nk8LCQssUKRKJUF9fj8/no6CggO7ubjo6OiZdZzAY5I477mD79u386le/OqzFr8nOH4DzzjuPn//855x00kk8++yznHbaaZ+kCR6fSByVKouKigrC4bC1G69bt45HH32Uzs5OrrjiCjZt2gQYkwi++c1vomkal19+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\n", + "text/plain": [ + "

    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "%matplotlib inline\n", + "\n", + "import numpy as np\n", + "import numpy.linalg as la\n", + "\n", + "import scipy.optimize as sopt\n", + "\n", + "import matplotlib.pyplot as pt\n", + "from mpl_toolkits.mplot3d import axes3d\n", + "\n", + "def f(x):\n", + " return 0.5*x[0]**2 + 2.5*x[1]**2\n", + "\n", + "def df(x):\n", + " return np.array([x[0], 5*x[1]])\n", + "\n", + "fig = pt.figure()\n", + "ax = fig.gca(projection=\"3d\")\n", + "\n", + "xmesh, ymesh = np.mgrid[-2:2:50j,-2:2:50j]\n", + "fmesh = f(np.array([xmesh, ymesh]))\n", + "ax.plot_surface(xmesh, ymesh, fmesh)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "And then as countor plot" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [ + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pt.axis(\"equal\")\n", + "pt.contour(xmesh, ymesh, fmesh)\n", + "guesses = [np.array([2, 2./5])]" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Find guesses" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "guesses = [np.array([2.0, 2./5])]\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Run it!" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "[ 1.33333333 -0.26666667]\n" + ] + } + ], + "source": [ + "x = guesses[-1]\n", + "s = -df(x)\n", + "def f1d(alpha):\n", + " return f(x + alpha*s)\n", + "\n", + "alpha_opt = sopt.golden(f1d)\n", + "next_guess = x + alpha_opt * s\n", + "guesses.append(next_guess)\n", + "print(next_guess)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "What happened?" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [ + { + "data": { + "text/plain": [ + "[]" + ] + }, + "execution_count": 14, + "metadata": {}, + "output_type": "execute_result" + }, + { + "data": { + "image/png": "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\n", + "text/plain": [ + "
    " + ] + }, + "metadata": {}, + "output_type": "display_data" + } + ], + "source": [ + "pt.axis(\"equal\")\n", + "pt.contour(xmesh, ymesh, fmesh, 50)\n", + "it_array = np.array(guesses)\n", + "pt.plot(it_array.T[0], it_array.T[1], \"x-\")" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -1043,10 +1215,8 @@ }, { "cell_type": "code", - "execution_count": 1, - "metadata": { - "collapsed": false - }, + "execution_count": 6, + "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", @@ -1080,14 +1250,10 @@ }, { "cell_type": "code", - "execution_count": 2, - "metadata": { - "collapsed": false - }, + "execution_count": 7, + "metadata": {}, "outputs": [], "source": [ - "%matplotlib inline\n", - "\n", "\n", "# Importing various packages\n", "from random import random, seed\n", @@ -1138,10 +1304,8 @@ }, { "cell_type": "code", - "execution_count": 3, - "metadata": { - "collapsed": false - }, + "execution_count": 8, + "metadata": {}, "outputs": [], "source": [ "# Importing various packages\n", @@ -1224,10 +1388,8 @@ }, { "cell_type": "code", - "execution_count": 4, - "metadata": { - "collapsed": false - }, + "execution_count": 9, + "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", @@ -1257,6 +1419,491 @@ "print(np.linalg.norm(beta_ridge)) #||beta||" ] }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Automatic differentiation\n", + "Python has tools for so-called **automatic differentiation**.\n", + "Consider the following example" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "f(x) = \\sin\\left(2\\pi x + x^2\\right)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "which has the following derivative" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "$$\n", + "f'(x) = \\cos\\left(2\\pi x + x^2\\right)\\left(2\\pi + 2x\\right)\n", + "$$" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Using **autograd** we have" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "\n", + "# To do elementwise differentiation:\n", + "from autograd import elementwise_grad as egrad \n", + "\n", + "# To plot:\n", + "import matplotlib.pyplot as plt \n", + "\n", + "\n", + "def f(x):\n", + " return np.sin(2*np.pi*x + x**2)\n", + "\n", + "def f_grad_analytic(x):\n", + " return np.cos(2*np.pi*x + x**2)*(2*np.pi + 2*x)\n", + "\n", + "# Do the comparison:\n", + "x = np.linspace(0,1,1000)\n", + "\n", + "f_grad = egrad(f)\n", + "\n", + "computed = f_grad(x)\n", + "analytic = f_grad_analytic(x)\n", + "\n", + "plt.title('Derivative computed from Autograd compared with the analytical derivative')\n", + "plt.plot(x,computed,label='autograd')\n", + "plt.plot(x,analytic,label='analytic')\n", + "\n", + "plt.xlabel('x')\n", + "plt.ylabel('y')\n", + "plt.legend()\n", + "\n", + "plt.show()\n", + "\n", + "print(\"The max absolute difference is: %g\"%(np.max(np.abs(computed - analytic))))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "\n", + "## Using autograd\n", + "\n", + "Here we\n", + "experiment with what kind of functions Autograd is capable\n", + "of finding the gradient of. The following Python functions are just\n", + "meant to illustrate what Autograd can do, but please feel free to\n", + "experiment with other, possibly more complicated, functions as well." + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "\n", + "def f1(x):\n", + " return x**3 + 1\n", + "\n", + "f1_grad = grad(f1)\n", + "\n", + "# Remember to send in float as argument to the computed gradient from Autograd!\n", + "a = 1.0\n", + "\n", + "# See the evaluated gradient at a using autograd:\n", + "print(\"The gradient of f1 evaluated at a = %g using autograd is: %g\"%(a,f1_grad(a)))\n", + "\n", + "# Compare with the analytical derivative, that is f1'(x) = 3*x**2 \n", + "grad_analytical = 3*a**2\n", + "print(\"The gradient of f1 evaluated at a = %g by finding the analytic expression is: %g\"%(a,grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Autograd with more complicated functions\n", + "\n", + "To differentiate with respect to two (or more) arguments of a Python\n", + "function, Autograd need to know at which variable the function if\n", + "being differentiated with respect to." + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "def f2(x1,x2):\n", + " return 3*x1**3 + x2*(x1 - 5) + 1\n", + "\n", + "# By sending the argument 0, Autograd will compute the derivative w.r.t the first variable, in this case x1\n", + "f2_grad_x1 = grad(f2,0)\n", + "\n", + "# ... and differentiate w.r.t x2 by sending 1 as an additional arugment to grad\n", + "f2_grad_x2 = grad(f2,1)\n", + "\n", + "x1 = 1.0\n", + "x2 = 3.0 \n", + "\n", + "print(\"Evaluating at x1 = %g, x2 = %g\"%(x1,x2))\n", + "print(\"-\"*30)\n", + "\n", + "# Compare with the analytical derivatives:\n", + "\n", + "# Derivative of f2 w.r.t x1 is: 9*x1**2 + x2:\n", + "f2_grad_x1_analytical = 9*x1**2 + x2\n", + "\n", + "# Derivative of f2 w.r.t x2 is: x1 - 5:\n", + "f2_grad_x2_analytical = x1 - 5\n", + "\n", + "# See the evaluated derivations:\n", + "print(\"The derivative of f2 w.r.t x1: %g\"%( f2_grad_x1(x1,x2) ))\n", + "print(\"The analytical derivative of f2 w.r.t x1: %g\"%( f2_grad_x1(x1,x2) ))\n", + "\n", + "print()\n", + "\n", + "print(\"The derivative of f2 w.r.t x2: %g\"%( f2_grad_x2(x1,x2) ))\n", + "print(\"The analytical derivative of f2 w.r.t x2: %g\"%( f2_grad_x2(x1,x2) ))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the grad function will not produce the true gradient of the function. The true gradient of a function with two or more variables will produce a vector, where each element is the function differentiated w.r.t a variable.\n", + "\n", + "\n", + "## More complicated functions using the elements of their arguments directly" + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "def f3(x): # Assumes x is an array of length 5 or higher\n", + " return 2*x[0] + 3*x[1] + 5*x[2] + 7*x[3] + 11*x[4]**2\n", + "\n", + "f3_grad = grad(f3)\n", + "\n", + "x = np.linspace(0,4,5)\n", + "\n", + "# Print the computed gradient:\n", + "print(\"The computed gradient of f3 is: \", f3_grad(x))\n", + "\n", + "# The analytical gradient is: (2, 3, 5, 7, 22*x[4])\n", + "f3_grad_analytical = np.array([2, 3, 5, 7, 22*x[4]])\n", + "\n", + "# Print the analytical gradient:\n", + "print(\"The analytical gradient of f3 is: \", f3_grad_analytical)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that in this case, when sending an array as input argument, the\n", + "output from Autograd is another array. This is the true gradient of\n", + "the function, as opposed to the function in the previous example. By\n", + "using arrays to represent the variables, the output from Autograd\n", + "might be easier to work with, as the output is closer to what one\n", + "could expect form a gradient-evaluting function.\n", + "\n", + "\n", + "## Functions using mathematical functions from Numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "def f4(x):\n", + " return np.sqrt(1+x**2) + np.exp(x) + np.sin(2*np.pi*x)\n", + "\n", + "f4_grad = grad(f4)\n", + "\n", + "x = 2.7\n", + "\n", + "# Print the computed derivative:\n", + "print(\"The computed derivative of f4 at x = %g is: %g\"%(x,f4_grad(x)))\n", + "\n", + "# The analytical derivative is: x/sqrt(1 + x**2) + exp(x) + cos(2*pi*x)*2*pi\n", + "f4_grad_analytical = x/np.sqrt(1 + x**2) + np.exp(x) + np.cos(2*np.pi*x)*2*np.pi\n", + "\n", + "# Print the analytical gradient:\n", + "print(\"The analytical gradient of f4 at x = %g is: %g\"%(x,f4_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## More autograd" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "def f5(x):\n", + " if x >= 0:\n", + " return x**2\n", + " else:\n", + " return -3*x + 1\n", + "\n", + "f5_grad = grad(f5)\n", + "\n", + "x = 2.7\n", + "\n", + "# Print the computed derivative:\n", + "print(\"The computed derivative of f5 at x = %g is: %g\"%(x,f5_grad(x)))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## And with loops" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "1\n", + "7\n", + " \n", + "<\n", + "<\n", + "<\n", + "!\n", + "!\n", + "C\n", + "O\n", + "D\n", + "E\n", + "_\n", + "B\n", + "L\n", + "O\n", + "C\n", + "K\n", + " \n", + " \n", + "p\n", + "y\n", + "c\n", + "o\n", + "d" + ] + }, + { + "cell_type": "code", + "execution_count": 16, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "# Both of the functions are implementation of the sum: sum(x**i) for i = 0, ..., 9\n", + "# The analytical derivative is: sum(i*x**(i-1)) \n", + "f6_grad_analytical = 0\n", + "for i in range(10):\n", + " f6_grad_analytical += i*x**(i-1)\n", + "\n", + "print(\"The analytical derivative of f6 at x = %g is: %g\"%(x,f6_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Using recursion" + ] + }, + { + "cell_type": "code", + "execution_count": 17, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "\n", + "def f7(n): # Assume that n is an integer\n", + " if n == 1 or n == 0:\n", + " return 1\n", + " else:\n", + " return n*f7(n-1)\n", + "\n", + "f7_grad = grad(f7)\n", + "\n", + "n = 2.0\n", + "\n", + "print(\"The computed derivative of f7 at n = %d is: %g\"%(n,f7_grad(n)))\n", + "\n", + "# The function f7 is an implementation of the factorial of n.\n", + "# By using the product rule, one can find that the derivative is:\n", + "\n", + "f7_grad_analytical = 0\n", + "for i in range(int(n)-1):\n", + " tmp = 1\n", + " for k in range(int(n)-1):\n", + " if k != i:\n", + " tmp *= (n - k)\n", + " f7_grad_analytical += tmp\n", + "\n", + "print(\"The analytical derivative of f7 at n = %d is: %g\"%(n,f7_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that if n is equal to zero or one, Autograd will give an error message. This message appears when the output is independent on input.\n", + "\n", + "## Unsupported functions\n", + "Autograd supports many features. However, there are some functions that is not supported (yet) by Autograd.\n", + "\n", + "Assigning a value to the variable being differentiated with respect to" + ] + }, + { + "cell_type": "code", + "execution_count": 18, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "def f8(x): # Assume x is an array\n", + " x[2] = 3\n", + " return x*2\n", + "\n", + "f8_grad = grad(f8)\n", + "\n", + "x = 8.4\n", + "\n", + "print(\"The derivative of f8 is:\",f8_grad(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here, Autograd tells us that an 'ArrayBox' does not support item assignment. The item assignment is done when the program tries to assign x[2] to the value 3. However, Autograd has implemented the computation of the derivative such that this assignment is not possible.\n", + "\n", + "## The syntax a.dot(b) when finding the dot product" + ] + }, + { + "cell_type": "code", + "execution_count": 19, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "def f9(a): # Assume a is an array with 2 elements\n", + " b = np.array([1.0,2.0])\n", + " return a.dot(b)\n", + "\n", + "f9_grad = grad(f9)\n", + "\n", + "x = np.array([1.0,0.0])\n", + "\n", + "print(\"The derivative of f9 is:\",f9_grad(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we are told that the 'dot' function does not belong to Autograd's\n", + "version of a Numpy array. To overcome this, an alternative syntax\n", + "which also computed the dot product can be used:" + ] + }, + { + "cell_type": "code", + "execution_count": 20, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad\n", + "def f9_alternative(x): # Assume a is an array with 2 elements\n", + " b = np.array([1.0,2.0])\n", + " return np.dot(x,b) # The same as x_1*b_1 + x_2*b_2\n", + "\n", + "f9_alternative_grad = grad(f9_alternative)\n", + "\n", + "x = np.array([3.0,0.0])\n", + "\n", + "print(\"The gradient of f9 is:\",f9_alternative_grad(x))\n", + "\n", + "# The analytical gradient of the dot product of vectors x and b with two elements (x_1,x_2) and (b_1, b_2) respectively\n", + "# w.r.t x is (b_1, b_2)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Recommended to avoid\n", + "The documentation recommends to avoid inplace operations such as" + ] + }, + { + "cell_type": "code", + "execution_count": 21, + "metadata": {}, + "outputs": [], + "source": [ + "a += b\n", + "a -= b\n", + "a*= b\n", + "a /=b" + ] + }, { "cell_type": "markdown", "metadata": {}, @@ -1372,10 +2019,8 @@ }, { "cell_type": "code", - "execution_count": 5, - "metadata": { - "collapsed": false - }, + "execution_count": 22, + "metadata": {}, "outputs": [], "source": [ "import numpy as np \n", @@ -1436,10 +2081,8 @@ }, { "cell_type": "code", - "execution_count": 6, - "metadata": { - "collapsed": false - }, + "execution_count": 23, + "metadata": {}, "outputs": [], "source": [ "import numpy as np \n", @@ -1469,7 +2112,25 @@ ] } ], - "metadata": {}, + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.0" + } + }, "nbformat": 4, "nbformat_minor": 2 } diff --git a/doc/pub/Splines/ipynb/ipynb-Splines-src.tar.gz b/doc/pub/Splines/ipynb/ipynb-Splines-src.tar.gz index b478c41fa..ebf527628 100644 Binary files a/doc/pub/Splines/ipynb/ipynb-Splines-src.tar.gz and b/doc/pub/Splines/ipynb/ipynb-Splines-src.tar.gz differ diff --git a/doc/pub/Splines/pdf/Splines-minted.pdf b/doc/pub/Splines/pdf/Splines-minted.pdf index c83605159..5f32f6be0 100644 Binary files a/doc/pub/Splines/pdf/Splines-minted.pdf and b/doc/pub/Splines/pdf/Splines-minted.pdf differ diff --git a/doc/src/Splines/Splines.do.txt b/doc/src/Splines/Splines.do.txt index acf8e10b2..d3fba4f49 100644 --- a/doc/src/Splines/Splines.do.txt +++ b/doc/src/Splines/Splines.do.txt @@ -515,9 +515,6 @@ which gives -!split -===== The Steepest descent algorithm ===== - !split ===== Simple codes for steepest descent and conjugate gradient using a $2\times 2$ matrix, in c++, Python code to come ===== @@ -580,6 +577,60 @@ Vector SteepestDescent(Matrix A, Vector b, Vector x0){ !eblock +!split +===== Steepest descent example ===== + +!bc pycod +import numpy as np +import numpy.linalg as la + +import scipy.optimize as sopt + +import matplotlib.pyplot as pt +from mpl_toolkits.mplot3d import axes3d + +def f(x): + return 0.5*x[0]**2 + 2.5*x[1]**2 + +def df(x): + return np.array([x[0], 5*x[1]]) + +fig = pt.figure() +ax = fig.gca(projection="3d") + +xmesh, ymesh = np.mgrid[-2:2:50j,-2:2:50j] +fmesh = f(np.array([xmesh, ymesh])) +ax.plot_surface(xmesh, ymesh, fmesh) +!ec +And then as countor plot +!bc pycod +pt.axis("equal") +pt.contour(xmesh, ymesh, fmesh) +guesses = [np.array([2, 2./5])] +!ec +Find guesses +!bc pycod +x = guesses[-1] +s = -df(x) +!ec +Run it! +!bc pycod +def f1d(alpha): + return f(x + alpha*s) + +alpha_opt = sopt.golden(f1d) +next_guess = x + alpha_opt * s +guesses.append(next_guess) +print(next_guess) +!ec +What happened? +!bc pycod +pt.axis("equal") +pt.contour(xmesh, ymesh, fmesh, 50) +it_array = np.array(guesses) +pt.plot(it_array.T[0], it_array.T[1], "x-") +!ec + !split ===== Revisiting our first homework ===== @@ -825,8 +876,352 @@ print(beta_ridge) print(np.linalg.norm(beta_ridge)) #||beta|| !ec +!split +===== Automatic differentiation ===== +Python has tools for so-called _automatic differentiation_. +Consider the following example +!bt +\[ +f(x) = \sin\left(2\pi x + x^2\right) +\] +!et +which has the following derivative +!bt +\[ +f'(x) = \cos\left(2\pi x + x^2\right)\left(2\pi + 2x\right) +\] +!et +Using _autograd_ we have + +!bc pycod +import autograd.numpy as np + +# To do elementwise differentiation: +from autograd import elementwise_grad as egrad + +# To plot: +import matplotlib.pyplot as plt +def f(x): + return np.sin(2*np.pi*x + x**2) + +def f_grad_analytic(x): + return np.cos(2*np.pi*x + x**2)*(2*np.pi + 2*x) + +# Do the comparison: +x = np.linspace(0,1,1000) + +f_grad = egrad(f) + +computed = f_grad(x) +analytic = f_grad_analytic(x) + +plt.title('Derivative computed from Autograd compared with the analytical derivative') +plt.plot(x,computed,label='autograd') +plt.plot(x,analytic,label='analytic') + +plt.xlabel('x') +plt.ylabel('y') +plt.legend() + +plt.show() + +print("The max absolute difference is: %g"%(np.max(np.abs(computed - analytic)))) +!ec + +!split +===== Using autograd ===== + +Here we +experiment with what kind of functions Autograd is capable +of finding the gradient of. The following Python functions are just +meant to illustrate what Autograd can do, but please feel free to +experiment with other, possibly more complicated, functions as well. + +!bc pycod +import autograd.numpy as np +from autograd import grad + +def f1(x): + return x**3 + 1 + +f1_grad = grad(f1) + +# Remember to send in float as argument to the computed gradient from Autograd! +a = 1.0 + +# See the evaluated gradient at a using autograd: +print("The gradient of f1 evaluated at a = %g using autograd is: %g"%(a,f1_grad(a))) + +# Compare with the analytical derivative, that is f1'(x) = 3*x**2 +grad_analytical = 3*a**2 +print("The gradient of f1 evaluated at a = %g by finding the analytic expression is: %g"%(a,grad_analytical)) +!ec + + +!split +===== Autograd with more complicated functions ===== + +To differentiate with respect to two (or more) arguments of a Python +function, Autograd need to know at which variable the function if +being differentiated with respect to. + +!bc pycod +import autograd.numpy as np +from autograd import grad +def f2(x1,x2): + return 3*x1**3 + x2*(x1 - 5) + 1 + +# By sending the argument 0, Autograd will compute the derivative w.r.t the first variable, in this case x1 +f2_grad_x1 = grad(f2,0) + +# ... and differentiate w.r.t x2 by sending 1 as an additional arugment to grad +f2_grad_x2 = grad(f2,1) + +x1 = 1.0 +x2 = 3.0 + +print("Evaluating at x1 = %g, x2 = %g"%(x1,x2)) +print("-"*30) + +# Compare with the analytical derivatives: + +# Derivative of f2 w.r.t x1 is: 9*x1**2 + x2: +f2_grad_x1_analytical = 9*x1**2 + x2 + +# Derivative of f2 w.r.t x2 is: x1 - 5: +f2_grad_x2_analytical = x1 - 5 + +# See the evaluated derivations: +print("The derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) )) +print("The analytical derivative of f2 w.r.t x1: %g"%( f2_grad_x1(x1,x2) )) + +print() + +print("The derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) )) +print("The analytical derivative of f2 w.r.t x2: %g"%( f2_grad_x2(x1,x2) )) +!ec + +Note that the grad function will not produce the true gradient of the function. The true gradient of a function with two or more variables will produce a vector, where each element is the function differentiated w.r.t a variable. + + +!split +===== More complicated functions using the elements of their arguments directly ===== + +!bc pycod +import autograd.numpy as np +from autograd import grad +def f3(x): # Assumes x is an array of length 5 or higher + return 2*x[0] + 3*x[1] + 5*x[2] + 7*x[3] + 11*x[4]**2 + +f3_grad = grad(f3) + +x = np.linspace(0,4,5) + +# Print the computed gradient: +print("The computed gradient of f3 is: ", f3_grad(x)) + +# The analytical gradient is: (2, 3, 5, 7, 22*x[4]) +f3_grad_analytical = np.array([2, 3, 5, 7, 22*x[4]]) + +# Print the analytical gradient: +print("The analytical gradient of f3 is: ", f3_grad_analytical) +!ec + +Note that in this case, when sending an array as input argument, the +output from Autograd is another array. This is the true gradient of +the function, as opposed to the function in the previous example. By +using arrays to represent the variables, the output from Autograd +might be easier to work with, as the output is closer to what one +could expect form a gradient-evaluting function. + +!split +===== Functions using mathematical functions from Numpy ===== + +!bc pycod +import autograd.numpy as np +from autograd import grad +def f4(x): + return np.sqrt(1+x**2) + np.exp(x) + np.sin(2*np.pi*x) + +f4_grad = grad(f4) + +x = 2.7 + +# Print the computed derivative: +print("The computed derivative of f4 at x = %g is: %g"%(x,f4_grad(x))) + +# The analytical derivative is: x/sqrt(1 + x**2) + exp(x) + cos(2*pi*x)*2*pi +f4_grad_analytical = x/np.sqrt(1 + x**2) + np.exp(x) + np.cos(2*np.pi*x)*2*np.pi + +# Print the analytical gradient: +print("The analytical gradient of f4 at x = %g is: %g"%(x,f4_grad_analytical)) +!ec + + +!split +===== More autograd ===== + +!bc pycod +import autograd.numpy as np +from autograd import grad +def f5(x): + if x >= 0: + return x**2 + else: + return -3*x + 1 + +f5_grad = grad(f5) + +x = 2.7 + +# Print the computed derivative: +print("The computed derivative of f5 at x = %g is: %g"%(x,f5_grad(x))) +!ec + + +!split +===== And with loops ===== + +!bc pycod +import autograd.numpy as np +from autograd import grad +def f6_for(x): + val = 0 + for i in range(10): + val = val + x**i + return val + +def f6_while(x): + val = 0 + i = 0 + while i < 10: + val = val + x**i + i = i + 1 + return val + +f6_for_grad = grad(f6_for) +f6_while_grad = grad(f6_while) + +x = 0.5 + +# Print the computed derivaties of f6_for and f6_while +print("The computed derivative of f6_for at x = %g is: %g"%(x,f6_for_grad(x))) +print("The computed derivative of f6_while at x = %g is: %g"%(x,f6_while_grad(x))) +!ec +!bc pycod +import autograd.numpy as np +from autograd import grad +# Both of the functions are implementation of the sum: sum(x**i) for i = 0, ..., 9 +# The analytical derivative is: sum(i*x**(i-1)) +f6_grad_analytical = 0 +for i in range(10): + f6_grad_analytical += i*x**(i-1) + +print("The analytical derivative of f6 at x = %g is: %g"%(x,f6_grad_analytical)) +!ec + +!split +===== Using recursion ===== +!bc pycod +import autograd.numpy as np +from autograd import grad + +def f7(n): # Assume that n is an integer + if n == 1 or n == 0: + return 1 + else: + return n*f7(n-1) + +f7_grad = grad(f7) + +n = 2.0 + +print("The computed derivative of f7 at n = %d is: %g"%(n,f7_grad(n))) + +# The function f7 is an implementation of the factorial of n. +# By using the product rule, one can find that the derivative is: + +f7_grad_analytical = 0 +for i in range(int(n)-1): + tmp = 1 + for k in range(int(n)-1): + if k != i: + tmp *= (n - k) + f7_grad_analytical += tmp + +print("The analytical derivative of f7 at n = %d is: %g"%(n,f7_grad_analytical)) + +!ec +Note that if n is equal to zero or one, Autograd will give an error message. This message appears when the output is independent on input. + +!split +===== Unsupported functions ===== +Autograd supports many features. However, there are some functions that is not supported (yet) by Autograd. + +Assigning a value to the variable being differentiated with respect to +!bc pycod +import autograd.numpy as np +from autograd import grad +def f8(x): # Assume x is an array + x[2] = 3 + return x*2 + +f8_grad = grad(f8) + +x = 8.4 + +print("The derivative of f8 is:",f8_grad(x)) +!ec +Here, Autograd tells us that an 'ArrayBox' does not support item assignment. The item assignment is done when the program tries to assign x[2] to the value 3. However, Autograd has implemented the computation of the derivative such that this assignment is not possible. + +!split +===== The syntax a.dot(b) when finding the dot product ===== +!bc pycod +import autograd.numpy as np +from autograd import grad +def f9(a): # Assume a is an array with 2 elements + b = np.array([1.0,2.0]) + return a.dot(b) + +f9_grad = grad(f9) + +x = np.array([1.0,0.0]) + +print("The derivative of f9 is:",f9_grad(x)) +!ec + +Here we are told that the 'dot' function does not belong to Autograd's +version of a Numpy array. To overcome this, an alternative syntax +which also computed the dot product can be used: + +!bc pycod +import autograd.numpy as np +from autograd import grad +def f9_alternative(x): # Assume a is an array with 2 elements + b = np.array([1.0,2.0]) + return np.dot(x,b) # The same as x_1*b_1 + x_2*b_2 + +f9_alternative_grad = grad(f9_alternative) + +x = np.array([3.0,0.0]) + +print("The gradient of f9 is:",f9_alternative_grad(x)) + +# The analytical gradient of the dot product of vectors x and b with two elements (x_1,x_2) and (b_1, b_2) respectively +# w.r.t x is (b_1, b_2). +!ec + +!split +===== Recommended to avoid ===== +The documentation recommends to avoid inplace operations such as +!bc pycod +a += b +a -= b +a*= b +a /=b +!ec !split ===== Stochastic Gradient Descent ===== diff --git a/doc/src/Splines/autodiff/.ipynb_checkpoints/examples_allowed_functions-Copy1-checkpoint.ipynb b/doc/src/Splines/autodiff/.ipynb_checkpoints/examples_allowed_functions-Copy1-checkpoint.ipynb new file mode 100644 index 000000000..c128b8714 --- /dev/null +++ b/doc/src/Splines/autodiff/.ipynb_checkpoints/examples_allowed_functions-Copy1-checkpoint.ipynb @@ -0,0 +1,680 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Examples of the supported features in Autograd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before using Autograd for more complicated calculations, it might be useful to experiment with what kind of functions Autograd is capable of finding the gradient of. The following Python functions are just meant to illustrate what Autograd can do, but please feel free to experiment with other, possibly more complicated, functions as well! " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Supported functions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here are some examples of supported function implementations that Autograd can differentiate. Keep in mind that this list over examples is not comprehensive, but rather explores which basic constructions one might often use. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using simple arithmetics" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f1(x):\n", + " return x**3 + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The gradient of f1 evaluated at a = 1 using autograd is: 3\n", + "The gradient of f1 evaluated at a = 1 by finding the analytic expression is: 3\n" + ] + } + ], + "source": [ + "f1_grad = grad(f1)\n", + "\n", + "# Remember to send in float as argument to the computed gradient from Autograd!\n", + "a = 1.0\n", + "\n", + "# See the evaluated gradient at a using autograd:\n", + "print(\"The gradient of f1 evaluated at a = %g using autograd is: %g\"%(a,f1_grad(a)))\n", + "\n", + "# Compare with the analytical derivative, that is f1'(x) = 3*x**2 \n", + "grad_analytical = 3*a**2\n", + "print(\"The gradient of f1 evaluated at a = %g by finding the analytic expression is: %g\"%(a,grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions with two (or more) arguments" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To differentiate with respect to two (or more) arguments of a Python function, Autograd need to know at which variable the function if being differentiated with respect to. " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f2(x1,x2):\n", + " return 3*x1**3 + x2*(x1 - 5) + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Evaluating at x1 = 1, x2 = 3\n", + "------------------------------\n", + "The derivative of f2 w.r.t x1: 12\n", + "The analytical derivative of f2 w.r.t x1: 12\n", + "\n", + "The derivative of f2 w.r.t x2: -4\n", + "The analytical derivative of f2 w.r.t x2: -4\n" + ] + } + ], + "source": [ + "# By sending the argument 0, Autograd will compute the derivative w.r.t the first variable, in this case x1\n", + "f2_grad_x1 = grad(f2,0)\n", + "\n", + "# ... and differentiate w.r.t x2 by sending 1 as an additional arugment to grad\n", + "f2_grad_x2 = grad(f2,1)\n", + "\n", + "x1 = 1.0\n", + "x2 = 3.0 \n", + "\n", + "print(\"Evaluating at x1 = %g, x2 = %g\"%(x1,x2))\n", + "print(\"-\"*30)\n", + "\n", + "# Compare with the analytical derivatives:\n", + "\n", + "# Derivative of f2 w.r.t x1 is: 9*x1**2 + x2:\n", + "f2_grad_x1_analytical = 9*x1**2 + x2\n", + "\n", + "# Derivative of f2 w.r.t x2 is: x1 - 5:\n", + "f2_grad_x2_analytical = x1 - 5\n", + "\n", + "# See the evaluated derivations:\n", + "print(\"The derivative of f2 w.r.t x1: %g\"%( f2_grad_x1(x1,x2) ))\n", + "print(\"The analytical derivative of f2 w.r.t x1: %g\"%( f2_grad_x1(x1,x2) ))\n", + "\n", + "print()\n", + "\n", + "print(\"The derivative of f2 w.r.t x2: %g\"%( f2_grad_x2(x1,x2) ))\n", + "print(\"The analytical derivative of f2 w.r.t x2: %g\"%( f2_grad_x2(x1,x2) ))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the grad function will not produce the true gradient of the function. The true gradient of a function with two or more variables will produce a vector, where each element is the function differentiated w.r.t a variable. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using the elements of its argument directly" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def f3(x): # Assumes x is an array of length 5 or higher\n", + " return 2*x[0] + 3*x[1] + 5*x[2] + 7*x[3] + 11*x[4]**2" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed gradient of f3 is: [ 2. 3. 5. 7. 88.]\n", + "The analytical gradient of f3 is: [ 2. 3. 5. 7. 88.]\n" + ] + } + ], + "source": [ + "f3_grad = grad(f3)\n", + "\n", + "x = np.linspace(0,4,5)\n", + "\n", + "# Print the computed gradient:\n", + "print(\"The computed gradient of f3 is: \", f3_grad(x))\n", + "\n", + "# The analytical gradient is: (2, 3, 5, 7, 22*x[4])\n", + "f3_grad_analytical = np.array([2, 3, 5, 7, 22*x[4]])\n", + "\n", + "# Print the analytical gradient:\n", + "print(\"The analytical gradient of f3 is: \", f3_grad_analytical)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that in this case, when sending an array as input argument, the output from Autograd is another array. This is the true gradient of the function, as opposed to the function in the previous example. By using arrays to represent the variables, the output from Autograd might be easier to work with, as the output is closer to what one could expect form a gradient-evaluting function. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using mathematical functions from Numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f4(x):\n", + " return np.sqrt(1+x**2) + np.exp(x) + np.sin(2*np.pi*x)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed derivative of f4 at x = 2.7 is: 13.8759\n", + "The analytical gradient of f4 is: 13.87586944687107\n" + ] + } + ], + "source": [ + "f4_grad = grad(f4)\n", + "\n", + "x = 2.7\n", + "\n", + "# Print the computed derivative:\n", + "print(\"The computed derivative of f4 at x = %g is: %g\"%(x,f4_grad(x)))\n", + "\n", + "# The analytical derivative is: x/sqrt(1 + x**2) + exp(x) + cos(2*pi*x)*2*pi\n", + "f4_grad_analytical = x/np.sqrt(1 + x**2) + np.exp(x) + np.cos(2*np.pi*x)*2*np.pi\n", + "\n", + "# Print the analytical gradient:\n", + "print(\"The analytical gradient of f4 at x = %g is: %g\"%(x,f4_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using if-else tests" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f5(x):\n", + " if x >= 0:\n", + " return x**2\n", + " else:\n", + " return -3*x + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed derivative of f5 is: 5.4\n", + "The analytical derivative of f5 is: 5.4\n" + ] + } + ], + "source": [ + "f5_grad = grad(f5)\n", + "\n", + "x = 2.7\n", + "\n", + "# Print the computed derivative:\n", + "print(\"The computed derivative of f5 at x = %g is: %g\"%(x,f5_grad(x)))\n", + "\n", + "# The analytical derivative is: \n", + "# if x >= 0, then 2*x\n", + "# else -3\n", + "\n", + "if x >= 0:\n", + " f5_grad_analytical = 2*x\n", + "else:\n", + " f5_grad_analytical = -3\n", + "\n", + "\n", + "# Print the analytical derivative:\n", + "print(\"The analytical derivative of f5 at x = %g is: %g\"%(x,f5_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using for- and while loops" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f6_for(x):\n", + " val = 0\n", + " for i in range(10):\n", + " val = val + x**i\n", + " return val\n", + "\n", + "def f6_while(x):\n", + " val = 0\n", + " i = 0\n", + " while i < 10:\n", + " val = val + x**i\n", + " i = i + 1\n", + " return val" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed derivative of f6_for at x = 0.5 is: 3.95703\n", + "The computed derivative of f6_while at x = 0.5 is: 3.95703\n", + "The analytical derivative of f6 at x = 0.5 is: 3.95703\n" + ] + } + ], + "source": [ + "f6_for_grad = grad(f6_for)\n", + "f6_while_grad = grad(f6_while)\n", + "\n", + "x = 0.5\n", + "\n", + "# Print the computed derivaties of f6_for and f6_while\n", + "print(\"The computed derivative of f6_for at x = %g is: %g\"%(x,f6_for_grad(x)))\n", + "print(\"The computed derivative of f6_while at x = %g is: %g\"%(x,f6_while_grad(x)))\n", + "\n", + "# Both of the functions are implementation of the sum: sum(x**i) for i = 0, ..., 9\n", + "# The analytical derivative is: sum(i*x**(i-1)) \n", + "f6_grad_analytical = 0\n", + "for i in range(10):\n", + " f6_grad_analytical += i*x**(i-1)\n", + "\n", + "print(\"The analytical derivative of f6 at x = %g is: %g\"%(x,f6_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using recursion" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f7(n): # Assume that n is an integer\n", + " if n == 1 or n == 0:\n", + " return 1\n", + " else:\n", + " return n*f7(n-1)" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed derivative of f7 at n = 2 is: 1\n", + "The analytical derivative of f7 at n = 2 is: 1\n" + ] + } + ], + "source": [ + "f7_grad = grad(f7)\n", + "\n", + "n = 2.0\n", + "\n", + "print(\"The computed derivative of f7 at n = %d is: %g\"%(n,f7_grad(n)))\n", + "\n", + "# The function f7 is an implementation of the factorial of n.\n", + "# By using the product rule, one can find that the derivative is:\n", + "\n", + "f7_grad_analytical = 0\n", + "for i in range(int(n)-1):\n", + " tmp = 1\n", + " for k in range(int(n)-1):\n", + " if k != i:\n", + " tmp *= (n - k)\n", + " f7_grad_analytical += tmp\n", + "\n", + "print(\"The analytical derivative of f7 at n = %d is: %g\"%(n,f7_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that if n is equal to zero or one, Autograd will give an error message. This message appears when the output is independent on input. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unsupported functions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Autograd supports many features. However, there are some functions that is not supported (yet) by Autograd." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Assigning a value to the variable being differentiated with respect to" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f8(x): # Assume x is an array\n", + " x[2] = 3\n", + " return x*2" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'ArrayBox' object does not support item assignment", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m8.4\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"The derivative of f8 is:\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mf8_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/wrap_util.py\u001b[0m in \u001b[0;36mnary_f\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margnum\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0munary_operator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0munary_f\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0mnary_op_args\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mnary_op_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_f\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_operator\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/differential_operators.py\u001b[0m in \u001b[0;36mgrad\u001b[0;34m(fun, x)\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0marguments\u001b[0m \u001b[0;32mas\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m`\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbut\u001b[0m \u001b[0mreturns\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mgradient\u001b[0m \u001b[0minstead\u001b[0m\u001b[0;34m.\u001b[0m \u001b[0mThe\u001b[0m \u001b[0mfunction\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m`\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m should be scalar-valued. The gradient has the same type as the argument.\"\"\"\n\u001b[0;32m---> 24\u001b[0;31m \u001b[0mvjp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mans\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_make_vjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 25\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mans\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msize\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26\u001b[0m raise TypeError(\"Grad only applies to real scalar-output functions. \"\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/core.py\u001b[0m in \u001b[0;36mmake_vjp\u001b[0;34m(fun, x)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmake_vjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mstart_node\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mVJPNode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew_root\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mend_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_node\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtrace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstart_node\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mend_node\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mvjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/tracer.py\u001b[0m in \u001b[0;36mtrace\u001b[0;34m(start_node, fun, x)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mtrace_stack\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew_trace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mstart_box\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew_box\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstart_node\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mend_box\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstart_box\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misbox\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mend_box\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_trace\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mstart_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_trace\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_node\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/wrap_util.py\u001b[0m in \u001b[0;36munary_f\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0msubargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msubvals\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0msubargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mf8\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mf8\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# Assume x is an array\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTypeError\u001b[0m: 'ArrayBox' object does not support item assignment" + ] + } + ], + "source": [ + "f8_grad = grad(f8)\n", + "\n", + "x = 8.4\n", + "\n", + "print(\"The derivative of f8 is:\",f8_grad(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here, Autograd tells us that an 'ArrayBox' does not support item assignment. The item assignment is done when the program tries to assign x[2] to the value 3. However, Autograd has implemented the computation of the derivative such that this assignment is not possible. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The syntax a.dot(b) when finding the dot product" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f9(a): # Assume a is an array with 2 elements\n", + " b = np.array([1.0,2.0])\n", + " return a.dot(b)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'ArrayBox' object has no attribute 'dot'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1.0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m0.0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"The derivative of f9 is:\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mf9_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/wrap_util.py\u001b[0m in \u001b[0;36mnary_f\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margnum\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0munary_operator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0munary_f\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0mnary_op_args\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mnary_op_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_f\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_operator\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/differential_operators.py\u001b[0m in \u001b[0;36mgrad\u001b[0;34m(fun, x)\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0marguments\u001b[0m \u001b[0;32mas\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m`\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbut\u001b[0m \u001b[0mreturns\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mgradient\u001b[0m \u001b[0minstead\u001b[0m\u001b[0;34m.\u001b[0m \u001b[0mThe\u001b[0m \u001b[0mfunction\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m`\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m should be scalar-valued. The gradient has the same type as the argument.\"\"\"\n\u001b[0;32m---> 24\u001b[0;31m \u001b[0mvjp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mans\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_make_vjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 25\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mans\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msize\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26\u001b[0m raise TypeError(\"Grad only applies to real scalar-output functions. \"\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/core.py\u001b[0m in \u001b[0;36mmake_vjp\u001b[0;34m(fun, x)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmake_vjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mstart_node\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mVJPNode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew_root\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mend_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_node\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtrace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstart_node\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mend_node\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mvjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/tracer.py\u001b[0m in \u001b[0;36mtrace\u001b[0;34m(start_node, fun, x)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mtrace_stack\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew_trace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mstart_box\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew_box\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstart_node\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mend_box\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstart_box\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misbox\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mend_box\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_trace\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mstart_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_trace\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_node\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/wrap_util.py\u001b[0m in \u001b[0;36munary_f\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0msubargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msubvals\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0msubargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mf9\u001b[0;34m(a)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mf9\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# Assume a is an array with 2 elements\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1.0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2.0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'ArrayBox' object has no attribute 'dot'" + ] + } + ], + "source": [ + "f9_grad = grad(f9)\n", + "\n", + "x = np.array([1.0,0.0])\n", + "\n", + "print(\"The derivative of f9 is:\",f9_grad(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we are told that the 'dot' function does not belong to Autograd's version of a Numpy array. \n", + "To overcome this, an alternative syntax which also computed the dot product can be used:" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f9_alternative(x): # Assume a is an array with 2 elements\n", + " b = np.array([1.0,2.0])\n", + " return np.dot(x,b) # The same as x_1*b_1 + x_2*b_2" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The gradient of f9 is: [1. 2.]\n" + ] + } + ], + "source": [ + "f9_alternative_grad = grad(f9_alternative)\n", + "\n", + "x = np.array([3.0,0.0])\n", + "\n", + "print(\"The gradient of f9 is:\",f9_alternative_grad(x))\n", + "\n", + "# The analytical gradient of the dot product of vectors x and b with two elements (x_1,x_2) and (b_1, b_2) respectively\n", + "# w.r.t x is (b_1, b_2)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Recommended to avoid" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [documentation](https://github.com/HIPS/autograd/blob/master/docs/tutorial.md) recommends to avoid inplace operations such as" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "a += b\n", + "a -= b\n", + "a*= b\n", + "a /=b" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/src/Splines/autodiff/example_plot.ipynb b/doc/src/Splines/autodiff/example_plot.ipynb index c74b328cf..8c65512a2 100644 --- a/doc/src/Splines/autodiff/example_plot.ipynb +++ b/doc/src/Splines/autodiff/example_plot.ipynb @@ -9,7 +9,7 @@ }, { "cell_type": "code", - "execution_count": 22, + "execution_count": 1, "metadata": {}, "outputs": [ { @@ -54,12 +54,12 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": 3, "metadata": {}, "outputs": [ { "data": { - "image/png": "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\nAAAAAElFTkSuQmCC\n", + "image/png": "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\n", "text/plain": [ "
    " ] @@ -111,6 +111,13 @@ "\n", "print(\"The max absolute difference is: %g\"%(np.max(np.abs(computed - analytic))))" ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] } ], "metadata": { diff --git a/doc/src/Splines/autodiff/examples_allowed_functions-Copy1.ipynb b/doc/src/Splines/autodiff/examples_allowed_functions-Copy1.ipynb new file mode 100644 index 000000000..c128b8714 --- /dev/null +++ b/doc/src/Splines/autodiff/examples_allowed_functions-Copy1.ipynb @@ -0,0 +1,680 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# Examples of the supported features in Autograd" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Before using Autograd for more complicated calculations, it might be useful to experiment with what kind of functions Autograd is capable of finding the gradient of. The following Python functions are just meant to illustrate what Autograd can do, but please feel free to experiment with other, possibly more complicated, functions as well! " + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "import autograd.numpy as np\n", + "from autograd import grad" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Supported functions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here are some examples of supported function implementations that Autograd can differentiate. Keep in mind that this list over examples is not comprehensive, but rather explores which basic constructions one might often use. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using simple arithmetics" + ] + }, + { + "cell_type": "code", + "execution_count": 15, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f1(x):\n", + " return x**3 + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 62, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The gradient of f1 evaluated at a = 1 using autograd is: 3\n", + "The gradient of f1 evaluated at a = 1 by finding the analytic expression is: 3\n" + ] + } + ], + "source": [ + "f1_grad = grad(f1)\n", + "\n", + "# Remember to send in float as argument to the computed gradient from Autograd!\n", + "a = 1.0\n", + "\n", + "# See the evaluated gradient at a using autograd:\n", + "print(\"The gradient of f1 evaluated at a = %g using autograd is: %g\"%(a,f1_grad(a)))\n", + "\n", + "# Compare with the analytical derivative, that is f1'(x) = 3*x**2 \n", + "grad_analytical = 3*a**2\n", + "print(\"The gradient of f1 evaluated at a = %g by finding the analytic expression is: %g\"%(a,grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions with two (or more) arguments" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "To differentiate with respect to two (or more) arguments of a Python function, Autograd need to know at which variable the function if being differentiated with respect to. " + ] + }, + { + "cell_type": "code", + "execution_count": 13, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f2(x1,x2):\n", + " return 3*x1**3 + x2*(x1 - 5) + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 14, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Evaluating at x1 = 1, x2 = 3\n", + "------------------------------\n", + "The derivative of f2 w.r.t x1: 12\n", + "The analytical derivative of f2 w.r.t x1: 12\n", + "\n", + "The derivative of f2 w.r.t x2: -4\n", + "The analytical derivative of f2 w.r.t x2: -4\n" + ] + } + ], + "source": [ + "# By sending the argument 0, Autograd will compute the derivative w.r.t the first variable, in this case x1\n", + "f2_grad_x1 = grad(f2,0)\n", + "\n", + "# ... and differentiate w.r.t x2 by sending 1 as an additional arugment to grad\n", + "f2_grad_x2 = grad(f2,1)\n", + "\n", + "x1 = 1.0\n", + "x2 = 3.0 \n", + "\n", + "print(\"Evaluating at x1 = %g, x2 = %g\"%(x1,x2))\n", + "print(\"-\"*30)\n", + "\n", + "# Compare with the analytical derivatives:\n", + "\n", + "# Derivative of f2 w.r.t x1 is: 9*x1**2 + x2:\n", + "f2_grad_x1_analytical = 9*x1**2 + x2\n", + "\n", + "# Derivative of f2 w.r.t x2 is: x1 - 5:\n", + "f2_grad_x2_analytical = x1 - 5\n", + "\n", + "# See the evaluated derivations:\n", + "print(\"The derivative of f2 w.r.t x1: %g\"%( f2_grad_x1(x1,x2) ))\n", + "print(\"The analytical derivative of f2 w.r.t x1: %g\"%( f2_grad_x1(x1,x2) ))\n", + "\n", + "print()\n", + "\n", + "print(\"The derivative of f2 w.r.t x2: %g\"%( f2_grad_x2(x1,x2) ))\n", + "print(\"The analytical derivative of f2 w.r.t x2: %g\"%( f2_grad_x2(x1,x2) ))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that the grad function will not produce the true gradient of the function. The true gradient of a function with two or more variables will produce a vector, where each element is the function differentiated w.r.t a variable. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using the elements of its argument directly" + ] + }, + { + "cell_type": "code", + "execution_count": 12, + "metadata": {}, + "outputs": [], + "source": [ + "def f3(x): # Assumes x is an array of length 5 or higher\n", + " return 2*x[0] + 3*x[1] + 5*x[2] + 7*x[3] + 11*x[4]**2" + ] + }, + { + "cell_type": "code", + "execution_count": 66, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed gradient of f3 is: [ 2. 3. 5. 7. 88.]\n", + "The analytical gradient of f3 is: [ 2. 3. 5. 7. 88.]\n" + ] + } + ], + "source": [ + "f3_grad = grad(f3)\n", + "\n", + "x = np.linspace(0,4,5)\n", + "\n", + "# Print the computed gradient:\n", + "print(\"The computed gradient of f3 is: \", f3_grad(x))\n", + "\n", + "# The analytical gradient is: (2, 3, 5, 7, 22*x[4])\n", + "f3_grad_analytical = np.array([2, 3, 5, 7, 22*x[4]])\n", + "\n", + "# Print the analytical gradient:\n", + "print(\"The analytical gradient of f3 is: \", f3_grad_analytical)" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that in this case, when sending an array as input argument, the output from Autograd is another array. This is the true gradient of the function, as opposed to the function in the previous example. By using arrays to represent the variables, the output from Autograd might be easier to work with, as the output is closer to what one could expect form a gradient-evaluting function. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using mathematical functions from Numpy" + ] + }, + { + "cell_type": "code", + "execution_count": 10, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f4(x):\n", + " return np.sqrt(1+x**2) + np.exp(x) + np.sin(2*np.pi*x)" + ] + }, + { + "cell_type": "code", + "execution_count": 81, + "metadata": { + "scrolled": false + }, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed derivative of f4 at x = 2.7 is: 13.8759\n", + "The analytical gradient of f4 is: 13.87586944687107\n" + ] + } + ], + "source": [ + "f4_grad = grad(f4)\n", + "\n", + "x = 2.7\n", + "\n", + "# Print the computed derivative:\n", + "print(\"The computed derivative of f4 at x = %g is: %g\"%(x,f4_grad(x)))\n", + "\n", + "# The analytical derivative is: x/sqrt(1 + x**2) + exp(x) + cos(2*pi*x)*2*pi\n", + "f4_grad_analytical = x/np.sqrt(1 + x**2) + np.exp(x) + np.cos(2*np.pi*x)*2*np.pi\n", + "\n", + "# Print the analytical gradient:\n", + "print(\"The analytical gradient of f4 at x = %g is: %g\"%(x,f4_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using if-else tests" + ] + }, + { + "cell_type": "code", + "execution_count": 75, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f5(x):\n", + " if x >= 0:\n", + " return x**2\n", + " else:\n", + " return -3*x + 1" + ] + }, + { + "cell_type": "code", + "execution_count": 76, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed derivative of f5 is: 5.4\n", + "The analytical derivative of f5 is: 5.4\n" + ] + } + ], + "source": [ + "f5_grad = grad(f5)\n", + "\n", + "x = 2.7\n", + "\n", + "# Print the computed derivative:\n", + "print(\"The computed derivative of f5 at x = %g is: %g\"%(x,f5_grad(x)))\n", + "\n", + "# The analytical derivative is: \n", + "# if x >= 0, then 2*x\n", + "# else -3\n", + "\n", + "if x >= 0:\n", + " f5_grad_analytical = 2*x\n", + "else:\n", + " f5_grad_analytical = -3\n", + "\n", + "\n", + "# Print the analytical derivative:\n", + "print(\"The analytical derivative of f5 at x = %g is: %g\"%(x,f5_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using for- and while loops" + ] + }, + { + "cell_type": "code", + "execution_count": 88, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f6_for(x):\n", + " val = 0\n", + " for i in range(10):\n", + " val = val + x**i\n", + " return val\n", + "\n", + "def f6_while(x):\n", + " val = 0\n", + " i = 0\n", + " while i < 10:\n", + " val = val + x**i\n", + " i = i + 1\n", + " return val" + ] + }, + { + "cell_type": "code", + "execution_count": 87, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed derivative of f6_for at x = 0.5 is: 3.95703\n", + "The computed derivative of f6_while at x = 0.5 is: 3.95703\n", + "The analytical derivative of f6 at x = 0.5 is: 3.95703\n" + ] + } + ], + "source": [ + "f6_for_grad = grad(f6_for)\n", + "f6_while_grad = grad(f6_while)\n", + "\n", + "x = 0.5\n", + "\n", + "# Print the computed derivaties of f6_for and f6_while\n", + "print(\"The computed derivative of f6_for at x = %g is: %g\"%(x,f6_for_grad(x)))\n", + "print(\"The computed derivative of f6_while at x = %g is: %g\"%(x,f6_while_grad(x)))\n", + "\n", + "# Both of the functions are implementation of the sum: sum(x**i) for i = 0, ..., 9\n", + "# The analytical derivative is: sum(i*x**(i-1)) \n", + "f6_grad_analytical = 0\n", + "for i in range(10):\n", + " f6_grad_analytical += i*x**(i-1)\n", + "\n", + "print(\"The analytical derivative of f6 at x = %g is: %g\"%(x,f6_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Functions using recursion" + ] + }, + { + "cell_type": "code", + "execution_count": 116, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f7(n): # Assume that n is an integer\n", + " if n == 1 or n == 0:\n", + " return 1\n", + " else:\n", + " return n*f7(n-1)" + ] + }, + { + "cell_type": "code", + "execution_count": 115, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The computed derivative of f7 at n = 2 is: 1\n", + "The analytical derivative of f7 at n = 2 is: 1\n" + ] + } + ], + "source": [ + "f7_grad = grad(f7)\n", + "\n", + "n = 2.0\n", + "\n", + "print(\"The computed derivative of f7 at n = %d is: %g\"%(n,f7_grad(n)))\n", + "\n", + "# The function f7 is an implementation of the factorial of n.\n", + "# By using the product rule, one can find that the derivative is:\n", + "\n", + "f7_grad_analytical = 0\n", + "for i in range(int(n)-1):\n", + " tmp = 1\n", + " for k in range(int(n)-1):\n", + " if k != i:\n", + " tmp *= (n - k)\n", + " f7_grad_analytical += tmp\n", + "\n", + "print(\"The analytical derivative of f7 at n = %d is: %g\"%(n,f7_grad_analytical))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Note that if n is equal to zero or one, Autograd will give an error message. This message appears when the output is independent on input. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## Unsupported functions" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Autograd supports many features. However, there are some functions that is not supported (yet) by Autograd." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Assigning a value to the variable being differentiated with respect to" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f8(x): # Assume x is an array\n", + " x[2] = 3\n", + " return x*2" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "ename": "TypeError", + "evalue": "'ArrayBox' object does not support item assignment", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mTypeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m8.4\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"The derivative of f8 is:\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mf8_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/wrap_util.py\u001b[0m in \u001b[0;36mnary_f\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margnum\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0munary_operator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0munary_f\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0mnary_op_args\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mnary_op_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_f\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_operator\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/differential_operators.py\u001b[0m in \u001b[0;36mgrad\u001b[0;34m(fun, x)\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0marguments\u001b[0m \u001b[0;32mas\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m`\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbut\u001b[0m \u001b[0mreturns\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mgradient\u001b[0m \u001b[0minstead\u001b[0m\u001b[0;34m.\u001b[0m \u001b[0mThe\u001b[0m \u001b[0mfunction\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m`\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m should be scalar-valued. The gradient has the same type as the argument.\"\"\"\n\u001b[0;32m---> 24\u001b[0;31m \u001b[0mvjp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mans\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_make_vjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 25\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mans\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msize\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26\u001b[0m raise TypeError(\"Grad only applies to real scalar-output functions. \"\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/core.py\u001b[0m in \u001b[0;36mmake_vjp\u001b[0;34m(fun, x)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmake_vjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mstart_node\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mVJPNode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew_root\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mend_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_node\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtrace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstart_node\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mend_node\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mvjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/tracer.py\u001b[0m in \u001b[0;36mtrace\u001b[0;34m(start_node, fun, x)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mtrace_stack\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew_trace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mstart_box\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew_box\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstart_node\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mend_box\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstart_box\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misbox\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mend_box\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_trace\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mstart_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_trace\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_node\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/wrap_util.py\u001b[0m in \u001b[0;36munary_f\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0msubargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msubvals\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0msubargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mf8\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mf8\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# Assume x is an array\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 2\u001b[0;31m \u001b[0mx\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0;36m3\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 3\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0;36m2\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;31mTypeError\u001b[0m: 'ArrayBox' object does not support item assignment" + ] + } + ], + "source": [ + "f8_grad = grad(f8)\n", + "\n", + "x = 8.4\n", + "\n", + "print(\"The derivative of f8 is:\",f8_grad(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here, Autograd tells us that an 'ArrayBox' does not support item assignment. The item assignment is done when the program tries to assign x[2] to the value 3. However, Autograd has implemented the computation of the derivative such that this assignment is not possible. " + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### The syntax a.dot(b) when finding the dot product" + ] + }, + { + "cell_type": "code", + "execution_count": 25, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f9(a): # Assume a is an array with 2 elements\n", + " b = np.array([1.0,2.0])\n", + " return a.dot(b)" + ] + }, + { + "cell_type": "code", + "execution_count": 26, + "metadata": { + "scrolled": true + }, + "outputs": [ + { + "ename": "AttributeError", + "evalue": "'ArrayBox' object has no attribute 'dot'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m Traceback (most recent call last)", + "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[1;32m 3\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1.0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m0.0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 5\u001b[0;31m \u001b[0mprint\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m\"The derivative of f9 is:\"\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0mf9_grad\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/wrap_util.py\u001b[0m in \u001b[0;36mnary_f\u001b[0;34m(*args, **kwargs)\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 19\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtuple\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0mi\u001b[0m\u001b[0;34m]\u001b[0m \u001b[0;32mfor\u001b[0m \u001b[0mi\u001b[0m \u001b[0;32min\u001b[0m \u001b[0margnum\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 20\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0munary_operator\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0munary_f\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m*\u001b[0m\u001b[0mnary_op_args\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mnary_op_kwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 21\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_f\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mnary_operator\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/differential_operators.py\u001b[0m in \u001b[0;36mgrad\u001b[0;34m(fun, x)\u001b[0m\n\u001b[1;32m 22\u001b[0m \u001b[0marguments\u001b[0m \u001b[0;32mas\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m`\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mbut\u001b[0m \u001b[0mreturns\u001b[0m \u001b[0mthe\u001b[0m \u001b[0mgradient\u001b[0m \u001b[0minstead\u001b[0m\u001b[0;34m.\u001b[0m \u001b[0mThe\u001b[0m \u001b[0mfunction\u001b[0m\u001b[0;31m \u001b[0m\u001b[0;31m`\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;31m`\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 23\u001b[0m should be scalar-valued. The gradient has the same type as the argument.\"\"\"\n\u001b[0;32m---> 24\u001b[0;31m \u001b[0mvjp\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mans\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0m_make_vjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 25\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0;32mnot\u001b[0m \u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mans\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0msize\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0;36m1\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 26\u001b[0m raise TypeError(\"Grad only applies to real scalar-output functions. \"\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/core.py\u001b[0m in \u001b[0;36mmake_vjp\u001b[0;34m(fun, x)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mmake_vjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mstart_node\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mVJPNode\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew_root\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mend_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_node\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mtrace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstart_node\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0mend_node\u001b[0m \u001b[0;32mis\u001b[0m \u001b[0;32mNone\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mvjp\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mg\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mvspace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mzeros\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/tracer.py\u001b[0m in \u001b[0;36mtrace\u001b[0;34m(start_node, fun, x)\u001b[0m\n\u001b[1;32m 8\u001b[0m \u001b[0;32mwith\u001b[0m \u001b[0mtrace_stack\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnew_trace\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[0mstart_box\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnew_box\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mx\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mt\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mstart_node\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 10\u001b[0;31m \u001b[0mend_box\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mstart_box\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 11\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misbox\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mend_box\u001b[0m\u001b[0;34m)\u001b[0m \u001b[0;32mand\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_trace\u001b[0m \u001b[0;34m==\u001b[0m \u001b[0mstart_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_trace\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 12\u001b[0m \u001b[0;32mreturn\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_value\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mend_box\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0m_node\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m/home/krisetine/anaconda3/lib/python3.6/site-packages/autograd/wrap_util.py\u001b[0m in \u001b[0;36munary_f\u001b[0;34m(x)\u001b[0m\n\u001b[1;32m 13\u001b[0m \u001b[0;32melse\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 14\u001b[0m \u001b[0msubargs\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0msubvals\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mzip\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mx\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m---> 15\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0mfun\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m*\u001b[0m\u001b[0msubargs\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0;34m**\u001b[0m\u001b[0mkwargs\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 16\u001b[0m \u001b[0;32mif\u001b[0m \u001b[0misinstance\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m,\u001b[0m \u001b[0mint\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 17\u001b[0m \u001b[0mx\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0margs\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0margnum\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", + "\u001b[0;32m\u001b[0m in \u001b[0;36mf9\u001b[0;34m(a)\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[0;32mdef\u001b[0m \u001b[0mf9\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0ma\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m:\u001b[0m \u001b[0;31m# Assume a is an array with 2 elements\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[0mb\u001b[0m \u001b[0;34m=\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0marray\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0;34m[\u001b[0m\u001b[0;36m1.0\u001b[0m\u001b[0;34m,\u001b[0m\u001b[0;36m2.0\u001b[0m\u001b[0;34m]\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0;32m----> 3\u001b[0;31m \u001b[0;32mreturn\u001b[0m \u001b[0ma\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mdot\u001b[0m\u001b[0;34m(\u001b[0m\u001b[0mb\u001b[0m\u001b[0;34m)\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m", + "\u001b[0;31mAttributeError\u001b[0m: 'ArrayBox' object has no attribute 'dot'" + ] + } + ], + "source": [ + "f9_grad = grad(f9)\n", + "\n", + "x = np.array([1.0,0.0])\n", + "\n", + "print(\"The derivative of f9 is:\",f9_grad(x))" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "Here we are told that the 'dot' function does not belong to Autograd's version of a Numpy array. \n", + "To overcome this, an alternative syntax which also computed the dot product can be used:" + ] + }, + { + "cell_type": "code", + "execution_count": 31, + "metadata": { + "collapsed": true + }, + "outputs": [], + "source": [ + "def f9_alternative(x): # Assume a is an array with 2 elements\n", + " b = np.array([1.0,2.0])\n", + " return np.dot(x,b) # The same as x_1*b_1 + x_2*b_2" + ] + }, + { + "cell_type": "code", + "execution_count": 32, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "The gradient of f9 is: [1. 2.]\n" + ] + } + ], + "source": [ + "f9_alternative_grad = grad(f9_alternative)\n", + "\n", + "x = np.array([3.0,0.0])\n", + "\n", + "print(\"The gradient of f9 is:\",f9_alternative_grad(x))\n", + "\n", + "# The analytical gradient of the dot product of vectors x and b with two elements (x_1,x_2) and (b_1, b_2) respectively\n", + "# w.r.t x is (b_1, b_2)." + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "### Recommended to avoid" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "The [documentation](https://github.com/HIPS/autograd/blob/master/docs/tutorial.md) recommends to avoid inplace operations such as" + ] + }, + { + "cell_type": "raw", + "metadata": {}, + "source": [ + "a += b\n", + "a -= b\n", + "a*= b\n", + "a /=b" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "Python 3", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.7.0" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/doc/src/Splines/autodiff/examples_allowed_functions.ipynb b/doc/src/Splines/autodiff/examples_allowed_functions.ipynb index ebd1d4dc3..e7c165de7 100644 --- a/doc/src/Splines/autodiff/examples_allowed_functions.ipynb +++ b/doc/src/Splines/autodiff/examples_allowed_functions.ipynb @@ -18,19 +18,7 @@ "cell_type": "code", "execution_count": 1, "metadata": {}, - "outputs": [ - { - "ename": "ModuleNotFoundError", - "evalue": "No module named 'autograd'", - "output_type": "error", - "traceback": [ - "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", - "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", - "\u001b[0;32m\u001b[0m in \u001b[0;36m\u001b[0;34m()\u001b[0m\n\u001b[0;32m----> 1\u001b[0;31m \u001b[0;32mimport\u001b[0m \u001b[0mautograd\u001b[0m\u001b[0;34m.\u001b[0m\u001b[0mnumpy\u001b[0m \u001b[0;32mas\u001b[0m \u001b[0mnp\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n\u001b[0m\u001b[1;32m 2\u001b[0m \u001b[0;32mfrom\u001b[0m \u001b[0mautograd\u001b[0m \u001b[0;32mimport\u001b[0m \u001b[0mgrad\u001b[0m\u001b[0;34m\u001b[0m\u001b[0m\n", - "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'autograd'" - ] - } - ], + "outputs": [], "source": [ "import autograd.numpy as np\n", "from autograd import grad" @@ -59,10 +47,8 @@ }, { "cell_type": "code", - "execution_count": 15, - "metadata": { - "collapsed": true - }, + "execution_count": 3, + "metadata": {}, "outputs": [], "source": [ "def f1(x):\n", @@ -71,7 +57,7 @@ }, { "cell_type": "code", - "execution_count": 62, + "execution_count": 4, "metadata": {}, "outputs": [ { @@ -554,10 +540,8 @@ }, { "cell_type": "code", - "execution_count": 25, - "metadata": { - "collapsed": true - }, + "execution_count": 5, + "metadata": {}, "outputs": [], "source": [ "def f9(a): # Assume a is an array with 2 elements\n",