This commit is contained in:
Morten Hjorth-Jensen
2022-10-05 07:54:20 +02:00
parent 1412a627cb
commit b00518e915
7 changed files with 1675 additions and 976 deletions
+10
View File
@@ -67,3 +67,13 @@ found info about 5 exercises
*** warning: latex envir \begin{bmatrix} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments.
output in chapter1.ipynb
Translating doconce text in chapter1.do.txt to ipynb
*** replacing \bm{...} by \boldsymbol{...} (\bm is not supported by MathJax)
found info about 5 exercises
*** warning: latex envir \begin{bmatrix} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments.
*** warning: latex envir \begin{bmatrix} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments.
*** warning: latex envir \begin{bmatrix} does not work well in Markdown. Stick to \[ ... \], equation, equation*, align, or align* environments in math environments.
output in chapter1.ipynb
+5 -5
View File
@@ -88,7 +88,7 @@ role when we develop a specific machine learning algorithm.
Machine learning is an extremely rich field, in spite of its young
age. The increases we have seen during the last three decades in
computational capabilities have been followed by developments of
methods and techniques for analyzing and handling large date sets,
methods and techniques for analyzing and handling large data sets,
relying heavily on statistics, computer science and mathematics. The
field is rather new and developing rapidly. Popular software packages
written in Python for machine learning like
@@ -113,7 +113,7 @@ two main categories. In *supervised learning* we know the answer to a
problem, and let the computer deduce the logic behind it. On the other
hand, *unsupervised learning* is a method for finding patterns and
relationship in data sets without any prior knowledge of the system.
Some authours also operate with a third category, namely
Some authors also operate with a third category, namely
*reinforcement learning*. This is a paradigm of learning inspired by
behavioral psychology, where learning is achieved by trial-and-error,
solely from rewards and punishment.
@@ -176,14 +176,14 @@ what is the likelihood of finding $B$.
In science and engineering we often end up in situations where we want to infer (or learn) a
quantitative model $M$ for a given set of sample points $\bm{X} \in [x_1, x_2,\dots x_N]$.
As we will see repeatedely in these lectures, we could try to fit these data points to a model given by a
As we will see repeatedly in these lectures, we could try to fit these data points to a model given by a
straight line, or if we wish to be more sophisticated to a more complex
function.
The reason for inferring such a model is that it
serves many useful purposes. On the one hand, the model can reveal information
encoded in the data or underlying mechanisms from which the data were generated. For instance, we could discover important
corelations that relate interesting physics interpretations.
correlations that relate interesting physics interpretations.
In addition, it can simplify the representation of the given data set and help
us in making predictions about future data samples.
@@ -328,7 +328,7 @@ y = 10x+0.01 \times N(0,1),
where $x$ is defined as before. Does the fit look better? Indeed, by
reducing the role of the noise given by the normal distribution we see immediately that
our linear prediction seemingly reproduces better the training
set. However, this testing 'by the eye' is obviouly not satisfactory in the
set. However, this testing 'by the eye' is obviously not satisfactory in the
long run. Here we have only defined the training data and our model, and
have not discussed a more rigorous approach to the _cost_ function.
+20 -21
View File
@@ -104,7 +104,7 @@ later shrinkage methods like Ridge and Lasso regressions.
This is given by the _Singular Value Decomposition_ (SVD) algorithm,
perhaps the most powerful linear algebra algorithm. The SVD provides
a numerically stable matrix decomposition that is used in a large
swath oc applications and the decomposition is always stable
swath of applications and the decomposition is always stable
numerically.
In machine learning it plays a central role in dealing with for
@@ -123,7 +123,7 @@ when the matrix $\bm{X}$ (our so-called design matrix) is high-dimensional,
are problems with near singular or singular matrices. The column vectors of $\bm{X}$
may be linearly dependent, normally referred to as super-collinearity.
This means that the matrix may be rank deficient and it is basically impossible to
to model the data using linear regression. As an example, consider the matrix
model the data using linear regression. As an example, consider the matrix
!bt
\begin{align*}
\mathbf{X} & = \left[
@@ -143,7 +143,7 @@ The columns of $\bm{X}$ are linearly dependent. We see this easily since the
the first column is the row-wise sum of the other two columns. The rank (more correct,
the column rank) of a matrix is the dimension of the space spanned by the
column vectors. Hence, the rank of $\mathbf{X}$ is equal to the number
of linearly independent columns. In this particular case the matrix has rank 2.
of linearly independent columns. In this particular case the matrix has rank 1.
Super-collinearity of an $(n \times p)$-dimensional design matrix $\mathbf{X}$ implies
that the inverse of the matrix $\bm{X}^T\bm{X}$ (the matrix we need to invert to solve the linear regression equations) is non-invertible. If we have a square matrix that does not have an inverse, we say this matrix singular. The example here demonstrates this
@@ -170,7 +170,7 @@ If our design matrix $\bm{X}$ which enters the linear regression problem
!et
has linearly dependent column vectors, we will not be able to compute the inverse
of $\bm{X}^T\bm{X}$ and we cannot find the parameters (estimators) $\beta_i$.
The estimators are only well-defined if $(\bm{X}^{T}\bm{X})^{-1}$ exits.
The estimators are only well-defined if $(\bm{X}^{T}\bm{X})$ can be inverted.
This is more likely to happen when the matrix $\bm{X}$ is high-dimensional. In this case it is likely to encounter a situation where
the regression parameters $\beta_i$ cannot be estimated.
@@ -188,7 +188,7 @@ where $\bm{I}$ is the identity matrix. When we discuss _Ridge_ regression this
===== Basic math of the SVD =====
From standard linear algebra we know that a square matrix $\bm{X}$ can be diagonalized if and only it is
From standard linear algebra we know that a square matrix $\bm{X}$ can be diagonalized if and only if it is
a so-called "normal matrix":"https://en.wikipedia.org/wiki/Normal_matrix", that is if $\bm{X}\in {\mathbb{R}}^{n\times n}$
we have $\bm{X}\bm{X}^T=\bm{X}^T\bm{X}$ or if $\bm{X}\in {\mathbb{C}}^{n\times n}$ we have $\bm{X}\bm{X}^{\dagger}=\bm{X}^{\dagger}\bm{X}$.
The matrix has then a set of eigenpairs
@@ -381,7 +381,6 @@ def SVDinv(A):
return np.matmul(V,np.matmul(invD,UT))
#X = np.array([ [1.0, -1.0, 2.0], [1.0, 0.0, 1.0], [1.0, 2.0, -1.0], [1.0, 1.0, 0.0] ])
# Non-singular square matrix
X = np.array( [ [1,2,3],[2,4,5],[3,5,6]])
print(X)
@@ -402,7 +401,7 @@ rectangular matrices where the number of rows and columns are not equal.
It is also called the the Moore-Penrose Inverse after two independent discoverers of the method or the Generalized Inverse.
It is used for the calculation of the inverse for singular or near singular matrices and for rectangular matrices.
Using the SVD we can obtain the pseudoinverse of a matrix $\bm{A}$ (labeled here as $\bm{A}_{\mathrm{PI}}$
Using the SVD we can obtain the pseudoinverse (PI) of a matrix $\bm{A}$ (labeled here as $\bm{A}_{\mathrm{PI}}$
!bt
\[
\bm{A}_{\mathrm{PI}}= \bm{V}\bm{D}_{\mathrm{PI}}\bm{U}^T,
@@ -469,7 +468,7 @@ We can SVD decompose our matrix as
!et
where $\bm{U}$ is an orthogonal matrix of dimension $n\times n$, meaning that $\bm{U}\bm{U}^T=\bm{U}^T\bm{U}=\bm{I}_n$. Here $\bm{I}_n$ is the unit matrix of dimension $n \times n$.
Similarly, $\bm{V}$ is an orthogonal matrix of dimension $p\times p$, meaning that $\bm{V}\bm{V}^T=\bm{V}^T\bm{V}=\bm{I}_p$. Here $\bm{I}_n$ is the unit matrix of dimension $p \times p$.
Similarly, $\bm{V}$ is an orthogonal matrix of dimension $p\times p$, meaning that $\bm{V}\bm{V}^T=\bm{V}^T\bm{V}=\bm{I}_p$. Here $\bm{I}_p$ is the unit matrix of dimension $p \times p$.
Finally $\bm{\Sigma}$ contains the singular values $\sigma_i$. This matrix has dimension $n\times p$ and the singular values $\sigma_i$ are all positive. The non-zero values are ordered in descending order, that is
@@ -656,7 +655,7 @@ function, that is we have
\frac{\partial^2 C(\bm{\beta})}{\partial \bm{\beta}^T\partial \bm{\beta}} =\frac{2}{n}\bm{X}^T\bm{X}.
\]
!et
This quantity defines was what is called the Hessian matrix (the second derivative of a function we want to optimize).
This quantity defines what is called the Hessian matrix (the second derivative of the cost function we want to optimize).
The Hessian matrix plays an important role and is defined in this course as
@@ -777,7 +776,7 @@ with a given vector
!et
With these definitions, we can now rewrite our $2\times 2$
correlation/covariance matrix in terms of a moe general design/feature
correlation/covariance matrix in terms of a more general design/feature
matrix $\bm{X}\in {\mathbb{R}}^{n\times p}$. This leads to a $p\times p$
covariance matrix for the vectors $\bm{x}_i$ with $i=0,1,\dots,p-1$
@@ -883,7 +882,7 @@ The above procedure with _numpy_ can be made more compact if we use _pandas_.
We whow here how we can set up the correlation matrix using _pandas_, as done in this simple code
We know here how we can set up the correlation matrix using _pandas_, as done in this simple code
!bc pycod
import numpy as np
import pandas as pd
@@ -1344,7 +1343,7 @@ This equation does not lead to a nice analytical equation as in Ridge regression
Let us assume that our design matrix is given by unit (identity) matrix, that is a square diagonal matrix with ones only along the
diagonal. In this case we have an equal number of rows and columns $n=p$.
Our model approximation is just $\tilde{\bm{y}}=\bm{\beta}$ and the mean squared error and thereby the cost function for ordinary least sqquares (OLS) is then (we drop the term $1/n$)
Our model approximation is just $\tilde{\bm{y}}=\bm{\beta}$ and the mean squared error and thereby the cost function for ordinary least squares (OLS) is then (we drop the term $1/n$)
!bt
\[
C(\bm{\beta})=\sum_{i=0}^{p-1}(y_i-\beta_i)^2,
@@ -1396,7 +1395,7 @@ which leads to
Plotting these results ("figure in handwritten notes for week 36":"https://github.com/CompPhysics/MachineLearning/blob/master/doc/HandWrittenNotes/2021/NotesSeptember9.pdf") shows clearly that Lasso regression suppresses (sets to zero) values of $\beta_i$ for specific values of $\lambda$. Ridge regression reduces on the other hand the values of $\beta_i$ as function of $\lambda$.
As another examples,
As another example,
let us assume we have a data set with outputs/targets given by the vector
!bt
@@ -1600,13 +1599,13 @@ plt.show()
!ec
We see here that we reach a plateau for the Ridge results. Writing out the coefficients $\bm{\beta}$, we that they are getting smaller and smaller and our error stabilizes since the predicted values of $\tilde{\bm{y}}$ approach zero.
We see here that we reach a plateau for the Ridge results. Writing out the coefficients $\bm{\beta}$, we observe that they are getting smaller and smaller and our error stabilizes since the predicted values of $\tilde{\bm{y}}$ approach zero.
This happens also for Lasso regression, as seen from the next code
output. The difference is that Lasso shrinks the values of $\beta$ to
zero at a much earlier stage and the results flatten out. We see that
Lasso gives also an excellent fit for small values of $\lambda$ and
shows rthe best performance of the three regression methods.
shows the best performance of the three regression methods.
!bc pycod
import os
@@ -1967,7 +1966,7 @@ p(y_i, \bm{X}\vert\bm{\beta})=\frac{1}{\sqrt{2\pi\sigma^2}}\exp{\left[-\frac{(y_
!et
which reads as finding the likelihood of an event $y_i$ with the input variables $\bm{X}$ given the parameters (to be determined) $\bm{\beta}$.
Since these events are assumed to be independent and identicall distributed we can build the probability distribution function (PDF) for all possible event $\bm{y}$ as the product of the single events, that is we have
Since these events are assumed to be independent and identically distributed we can build the probability distribution function (PDF) for all possible event $\bm{y}$ as the product of the single events, that is we have
!bt
\[
@@ -2072,7 +2071,7 @@ p(X \cup Y)= p(X)+p(Y)-p(X \cap Y).
The product rule (aka joint probability) is given by
!bt
\[
p(X \cup Y)= p(X,Y)= p(X\vert Y)p(Y)=p(Y\vert X)p(X),
p(X \cap Y)= p(X,Y)= p(X\vert Y)p(Y)=p(Y\vert X)p(X),
\]
!et
where we read $p(X\vert Y)$ as the likelihood of obtaining $X$ given $Y$.
@@ -2352,7 +2351,7 @@ parameters $\beta_j$ as function of polynomial order and of the added
noise. Here we recommend to use $\sigma^2=1$ as variance for the
added noise (which follows a normal distribution with mean value zero).
Comment your results. If you have a large noise term, do the parameters $\beta_j$ vary more as function
model complexity? And what about their variance?
of model complexity? And what about their variance?
@@ -2393,7 +2392,7 @@ p(\bm{\beta}\vert\bm{D})\propto p(\bm{D}\vert\bm{\beta})p(\bm{\beta}).
\]
!et
We have a model for $p(\bm{D}\vert\bm{\beta})$ but need one for the _prior_ $p(\bm{\beta}$!
We have a model for $p(\bm{D}\vert\bm{\beta})$ but need one for the _prior_ $p(\bm{\beta})$!
@@ -2464,14 +2463,14 @@ constants terms that do not depend on $\beta$, we have
!bt
\[
C(\bm{\beta}=\frac{\vert\vert (\bm{y}-\bm{X}\bm{\beta})\vert\vert_2^2}{2\sigma^2}+\frac{1}{\tau}\vert\vert\bm{\beta}\vert\vert_1,
C(\bm{\beta})=\frac{\vert\vert (\bm{y}-\bm{X}\bm{\beta})\vert\vert_2^2}{2\sigma^2}+\frac{1}{\tau}\vert\vert\bm{\beta}\vert\vert_1,
\]
!et
and replacing $1/\tau$ with $\lambda$ we have
!bt
\[
C(\bm{\beta}=\frac{\vert\vert (\bm{y}-\bm{X}\bm{\beta})\vert\vert_2^2}{2\sigma^2}+\lambda\vert\vert\bm{\beta}\vert\vert_1,
C(\bm{\beta})=\frac{\vert\vert (\bm{y}-\bm{X}\bm{\beta})\vert\vert_2^2}{2\sigma^2}+\lambda\vert\vert\bm{\beta}\vert\vert_1,
\]
!et
which is our Lasso cost function!
+331 -32
View File
@@ -280,9 +280,19 @@ The convex subsets of $\mathbb{R}$ are the intervals of
$\mathbb{R}$. Examples of convex sets of $\mathbb{R}^2$ are the
regular polygons (triangles, rectangles, pentagons, etc...).
_Convex function_: Let $X \subset \mathbb{R}^n$ be a convex
set. Assume that the function $f: X \rightarrow \mathbb{R}$ is
continuous, then $f$ is said to be convex if
$f(tx_1 + (1-t)x_2) \leq tf(x_1) + (1-t)f(x_2)$
for all
$x_1, x_2 \in X$ and for all $t \in [0,1]$.
_Convex function_: Let $X \subset \mathbb{R}^n$ be a convex set. Assume that the function $f: X \rightarrow \mathbb{R}$ is continuous, then $f$ is said to be convex if $$f(tx_1 + (1-t)x_2) \leq tf(x_1) + (1-t)f(x_2) $$ for all $x_1, x_2 \in X$ and for all $t \in [0,1]$. If $\leq$ is replaced with a strict inequaltiy in the definition, we demand $x_1 \neq x_2$ and $t\in(0,1)$ then $f$ is said to be strictly convex. For a single variable function, convexity means that if you draw a straight line connecting $f(x_1)$ and $f(x_2)$, the value of the function on the interval $[x_1,x_2]$ is always below the line as illustrated below.
If $\leq$ is replaced with a strict inequality in the
definition, we demand $x_1 \neq x_2$ and $t\in(0,1)$ then $f$ is said
to be strictly convex. For a single variable function, convexity means
that if you draw a straight line connecting $f(x_1)$ and $f(x_2)$, the
value of the function on the interval $[x_1,x_2]$ is always below the
line as discussed below.
In the following we state first and second-order conditions which
@@ -296,7 +306,7 @@ all $x$ in the domain of $f$). Then $f$ is convex if and only if $D_f$
is a convex set and $$f(y) \geq f(x) + \nabla f(x)^T (y-x) $$ holds
for all $x,y \in D_f$. This condition means that for a convex function
the first order Taylor expansion (right hand side above) at any point
a global under estimator of the function. To convince yourself you can
is a global under estimator of the function. To convince yourself you can
make a drawing of $f(x) = x^2+1$ and draw the tangent line to $f(x)$ and
note that it is always below the graph.
!eblock
@@ -1756,7 +1766,14 @@ a /=b
===== Using Autograd with OLS =====
!split
===== Replace or not =====
In the above code, we have use replacement in setting up the
mini-batches. The discussion
"here":"https://sebastianraschka.com/faq/docs/sgd-methods.html" may be
useful.
===== Using Autograd =====
We conclude the part on optmization by showing how we can make codes
for linear regression and logistic regression using _autograd_. The
@@ -1816,8 +1833,110 @@ plt.show()
!ec
===== Same code but now with momentum gradient descent =====
!bc pycod
# Using Autograd to calculate gradients for OLS
from random import random, seed
import numpy as np
import autograd.numpy as np
import matplotlib.pyplot as plt
from autograd import grad
=== Including Stochastic Gradient Descent with Autograd ===
def CostOLS(beta):
return (1.0/n)*np.sum((y-X @ beta)**2)
n = 100
x = 2*np.random.rand(n,1)
y = 4+3*x#+np.random.randn(n,1)
X = np.c_[np.ones((n,1)), x]
XT_X = X.T @ X
theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)
print("Own inversion")
print(theta_linreg)
# Hessian matrix
H = (2.0/n)* XT_X
EigValues, EigVectors = np.linalg.eig(H)
print(f"Eigenvalues of Hessian Matrix:{EigValues}")
theta = np.random.randn(2,1)
eta = 1.0/np.max(EigValues)
Niterations = 30
# define the gradient
training_gradient = grad(CostOLS)
for iter in range(Niterations):
gradients = training_gradient(theta)
theta -= eta*gradients
print(iter,gradients[0],gradients[1])
print("theta from own gd")
print(theta)
# Now improve with momentum gradient descent
change = 0.0
delta_momentum = 0.3
for iter in range(Niterations):
# calculate gradient
gradients = training_gradient(theta)
# calculate update
new_change = eta*gradients+delta_momentum*change
# take a step
theta -= new_change
# save the change
change = new_change
print(iter,gradients[0],gradients[1])
print("theta from own gd wth momentum")
print(theta)
!ec
We note indeed a considerable increase in efficiency here, we less iterations needed.
However, if we can invert the Hessian matrix, this is the preferred approach, as shown in the example here.
!bc pycod
# Using Newton's method
from random import random, seed
import numpy as np
import autograd.numpy as np
import matplotlib.pyplot as plt
from autograd import grad
def CostOLS(beta):
return (1.0/n)*np.sum((y-X @ beta)**2)
n = 100
x = 2*np.random.rand(n,1)
y = 4+3*x+np.random.randn(n,1)
X = np.c_[np.ones((n,1)), x]
XT_X = X.T @ X
beta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)
print("Own inversion")
print(beta_linreg)
# Hessian matrix
H = (2.0/n)* XT_X
# Note that here the Hessian does not depend on the parameters beta
invH = np.linalg.pinv(H)
EigValues, EigVectors = np.linalg.eig(H)
print(f"Eigenvalues of Hessian Matrix:{EigValues}")
beta = np.random.randn(2,1)
Niterations = 5
# define the gradient
training_gradient = grad(CostOLS)
for iter in range(Niterations):
gradients = training_gradient(beta)
beta -= invH @ gradients
print(iter,gradients[0],gradients[1])
print("beta from own Newton code")
print(beta)
!ec
===== Including Stochastic Gradient Descent with Autograd =====
In this code we include the stochastic gradient descent approach discussed above. Note here that we specify which argument we are taking the derivative with respect to when using _autograd_.
!bc pycod
@@ -1898,43 +2017,223 @@ print(theta)
!ec
=== And Logistic Regression ===
Here we include momentum in the standard gradient descent approach.
!bc pycod
# Using Autograd to calculate gradients using SGD
# OLS example
from random import random, seed
import numpy as np
import autograd.numpy as np
import matplotlib.pyplot as plt
from autograd import grad
def sigmoid(x):
return 0.5 * (np.tanh(x / 2.) + 1)
# Note change from previous example
def CostOLS(y,X,theta):
return np.sum((y-X @ theta)**2)
def logistic_predictions(weights, inputs):
# Outputs probability of a label being true according to logistic model.
return sigmoid(np.dot(inputs, weights))
n = 100
x = 2*np.random.rand(n,1)
y = 4+3*x+np.random.randn(n,1)
def training_loss(weights):
# Training loss is the negative log-likelihood of the training labels.
preds = logistic_predictions(weights, inputs)
label_probabilities = preds * targets + (1 - preds) * (1 - targets)
return -np.sum(np.log(label_probabilities))
X = np.c_[np.ones((n,1)), x]
XT_X = X.T @ X
theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)
print("Own inversion")
print(theta_linreg)
# Hessian matrix
H = (2.0/n)* XT_X
EigValues, EigVectors = np.linalg.eig(H)
print(f"Eigenvalues of Hessian Matrix:{EigValues}")
# Build a toy dataset.
inputs = np.array([[0.52, 1.12, 0.77],
[0.88, -1.08, 0.15],
[0.52, 0.06, -1.30],
[0.74, -2.49, 1.39]])
targets = np.array([True, True, False, True])
theta = np.random.randn(2,1)
eta = 1.0/np.max(EigValues)
Niterations = 100
# Define a function that returns gradients of training loss using Autograd.
training_gradient_fun = grad(training_loss)
# Note that we request the derivative wrt third argument (theta, 2 here)
training_gradient = grad(CostOLS,2)
# Optimize weights using gradient descent.
weights = np.array([0.0, 0.0, 0.0])
print("Initial loss:", training_loss(weights))
for i in range(100):
weights -= training_gradient_fun(weights) * 0.01
for iter in range(Niterations):
gradients = (1.0/n)*training_gradient(y, X, theta)
theta -= eta*gradients
print("theta from own gd")
print(theta)
print("Trained loss:", training_loss(weights))
n_epochs = 50
M = 5 #size of each minibatch
m = int(n/M) #number of minibatches
t0, t1 = 5, 50
def learning_schedule(t):
return t0/(t+t1)
theta = np.random.randn(2,1)
change = 0.0
delta_momentum = 0.3
for epoch in range(n_epochs):
for i in range(m):
random_index = M*np.random.randint(m)
xi = X[random_index:random_index+M]
yi = y[random_index:random_index+M]
gradients = (1.0/M)*training_gradient(yi, xi, theta)
eta = learning_schedule(epoch*m+i)
# calculate update
new_change = eta*gradients+delta_momentum*change
# take a step
theta -= new_change
# save the change
change = new_change
print("theta from own sdg with momentum")
print(theta)
!ec
=== Similar (second order function now) problem but now with AdaGrad ===
!bc pycod
# Using Autograd to calculate gradients using AdaGrad and Stochastic Gradient descent
# OLS example
from random import random, seed
import numpy as np
import autograd.numpy as np
import matplotlib.pyplot as plt
from autograd import grad
# Note change from previous example
def CostOLS(y,X,theta):
return np.sum((y-X @ theta)**2)
n = 10000
x = np.random.rand(n,1)
y = 2.0+3*x +4*x*x# +np.random.randn(n,1)
X = np.c_[np.ones((n,1)), x, x*x]
XT_X = X.T @ X
theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)
print("Own inversion")
print(theta_linreg)
# Note that we request the derivative wrt third argument (theta, 2 here)
training_gradient = grad(CostOLS,2)
# Define parameters for Stochastic Gradient Descent
n_epochs = 50
M = 5 #size of each minibatch
m = int(n/M) #number of minibatches
# Guess for unknown parameters theta
theta = np.random.randn(3,1)
# Value for learning rate
eta = 0.01
# Including AdaGrad parameter to avoid possible division by zero
delta = 1e-8
for epoch in range(n_epochs):
# The outer product is calculated from scratch for each epoch
Giter = np.zeros(shape=(3,3))
for i in range(m):
random_index = M*np.random.randint(m)
xi = X[random_index:random_index+M]
yi = y[random_index:random_index+M]
gradients = (1.0/M)*training_gradient(yi, xi, theta)
# Calculate the outer product of the gradients
Giter +=gradients @ gradients.T
# Simpler algorithm with only diagonal elements
Ginverse = np.c_[eta/(delta+np.sqrt(np.diagonal(Giter)))]
# compute update
update = np.multiply(Ginverse,gradients)
theta -= update
print("theta from own AdaGrad")
print(theta)
!ec
Running this code we note an almost perfect agreement with the results from matrix inversion.
Similarly, here is our implementation of RMSprop.
!bc pycod
# Using Autograd to calculate gradients using RMSprop and Stochastic Gradient descent
# OLS example
from random import random, seed
import numpy as np
import autograd.numpy as np
import matplotlib.pyplot as plt
from autograd import grad
# Note change from previous example
def CostOLS(y,X,theta):
return np.sum((y-X @ theta)**2)
n = 10000
x = np.random.rand(n,1)
y = 2.0+3*x +4*x*x# +np.random.randn(n,1)
X = np.c_[np.ones((n,1)), x, x*x]
XT_X = X.T @ X
theta_linreg = np.linalg.pinv(XT_X) @ (X.T @ y)
print("Own inversion")
print(theta_linreg)
# Note that we request the derivative wrt third argument (theta, 2 here)
training_gradient = grad(CostOLS,2)
# Define parameters for Stochastic Gradient Descent
n_epochs = 50
M = 5 #size of each minibatch
m = int(n/M) #number of minibatches
# Guess for unknown parameters theta
theta = np.random.randn(3,1)
# Value for learning rate
eta = 0.01
# Value for parameter rho
rho = 0.99
# Including AdaGrad parameter to avoid possible division by zero
delta = 1e-8
for epoch in range(n_epochs):
Giter = np.zeros(shape=(3,3))
for i in range(m):
random_index = M*np.random.randint(m)
xi = X[random_index:random_index+M]
yi = y[random_index:random_index+M]
gradients = (1.0/M)*training_gradient(yi, xi, theta)
# Previous value for the outer product of gradients
Previous = Giter
# Accumulated gradient
Giter +=gradients @ gradients.T
# Scaling with rho the new and the previous results
Gnew = (rho*Previous+(1-rho)*Giter)
# Taking the diagonal only and inverting
Ginverse = np.c_[eta/(delta+np.sqrt(np.diagonal(Gnew)))]
# Hadamard product
update = np.multiply(Ginverse,gradients)
theta -= update
print("theta from own RMSprop")
print(theta)
!ec
===== Introducing "JAX":"https://jax.readthedocs.io/en/latest/" =====
Presently, instead of using _autograd_, we recommend using "JAX":"https://jax.readthedocs.io/en/latest/"
_JAX_ is Autograd and "XLA (Accelerated Linear Algebra))":"https://www.tensorflow.org/xla",
brought together for high-performance numerical computing and machine learning research.
It provides composable transformations of Python+NumPy programs: differentiate, vectorize, parallelize, Just-In-Time compile to GPU/TPU, and more.
Here's a simple example on how you can use _JAX_ to compute the derivate of the logistic function.
!bc pycod
import jax.numpy as jnp
from jax import grad, jit, vmap
def sum_logistic(x):
return jnp.sum(1.0 / (1.0 + jnp.exp(-x)))
x_small = jnp.arange(3.)
derivative_fn = grad(sum_logistic)
print(derivative_fn(x_small))
!ec
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff