Product

Monday, 19 February 2024

Application of differentiations in neural networks

 


Differential calculus is an important tool in machine learning algorithms. Neural networks in particular, the gradient descent algorithm depends on the gradient, which is a quantity computed by differentiation.

In this tutorial, we will see how the back-propagation technique is used in finding the gradients in neural networks.

After completing this tutorial, you will know

  • What is a total differential and total derivative
  • How to compute the total derivatives in neural networks
  • How back-propagation helped in computing the total derivatives

Let’s get started

Application of differentiations in neural networks

Application of differentiations in neural networks
Photo by Freeman Zhou, some rights reserved.

Tutorial overview

This tutorial is divided into 5 parts; they are:

  1. Total differential and total derivatives
  2. Algebraic representation of a multilayer perceptron model
  3. Finding the gradient by back-propagation
  4. Matrix form of gradient equations
  5. Implementing back-propagation

Total differential and total derivatives

For a function such as (), we call denote its derivative as () or . But for a multivariate function, such as (,), we have a partial derivative of  with respect to  denoted as , or sometimes written as . A partial derivative is obtained by differentiation of  with respect to  while assuming the other variable  is a constant. Therefore, we use  instead of  as the symbol for differentiation to signify the difference.

However, what if the  and  in (,) are both function of ? In other words, we can write () and () and ((),()). So  determines the value of  and  and in turn, determines (,). In this case, it is perfectly fine to ask what is , as  is eventually determined by .

This is the concept of total derivatives. In fact, for a multivariate function (,,)=((),(),()), we always have
=++
The above notation is called the total derivative because it is sum of the partial derivatives. In essence, it is applying chain rule to find the differentiation.

If we take away the  part in the above equation, what we get is an approximate change in  with respect to , i.e.,
=++
We call this notation the total differential.

Algebraic representation of a multilayer perceptron model

Consider the network:

This is a simple, fully-connected, 4-layer neural network. Let’s call the input layer as layer 0, the two hidden layers the layer 1 and 2, and the output layer as layer 3. In this picture, we see that we have 0=3 input units, and 1=4 units in the first hidden layer and 2=2 units in the second input layer. There are 3=2 output units.

If we denote the input to the network as  where =1,,0 and the network’s output as ^ where =1,,3. Then we can write

ℎ1=1(=10(1)+(1))for =1,,1ℎ2=2(=11(2)ℎ1+(2))=1,,2^=3(=12(3)ℎ2+(3))=1,,3

Here the activation function at layer  is denoted as . The outputs of first hidden layer are denoted as â„Ž1 for the -th unit. Similarly, the outputs of second hidden layer are denoted as â„Ž2. The weights and bias of unit  in layer  are denoted as () and () respectively.

In the above, we can see that the output of layer 1 will feed into layer . Therefore, while ^ is expressed as a function of â„Ž2, but â„Ž2 is also a function of â„Ž1 and in turn, a function of .

The above describes the construction of a neural network in terms of algebraic equations. Training a neural network would need to specify a *loss function* as well so we can minimize it in the training loop. Depends on the application, we commonly use cross entropy for categorization problems or mean squared error for regression problems. With the target variables as , the mean square error loss function is specified as
==13(^)2

Want to Get Started With Calculus for Machine Learning?

Take my free 7-day email crash course now (with sample code).

Click to sign-up and also get a free PDF Ebook version of the course.

Finding the gradient by back-propagation

In the above construct,  and  are from the dataset. The parameters to the neural network are  and . While the activation functions  are by design the outputs at each layer â„Ž1ℎ2, and ^ are dependent variables. In training the neural network, our goal is to update  and  in each iteration, namely, by the gradient descent update rule:
()=()()()=()()
where  is the learning rate parameter to gradient descent.

From the equation of  we know that  is not dependent on () or () but on ^. However, ^ can be written as function of () or () eventually. Let’s see one by one how the weights and bias at layer  can be connected to ^ at the output layer.

We begin with the loss metric. If we consider the loss of a single data point, we have
==13(^)2^=2(^)for =1,,3
Here we see that the loss function depends on all outputs ^ and therefore we can find a partial derivative ^.

Now let’s look at the output layer:
^=3(=12(3)ℎ2+(3))for =1,,3(3)=^^(3)=1,,3; =1,,2=^3(=12(3)ℎ2+(3))ℎ2(3)=^^(3)=1,,3=^3(=12(3)ℎ2+(3))
Because the weight (3) at layer 3 applies to input â„Ž2 and affects output ^ only. Hence we can write the derivative (3) as the product of two derivatives ^^(3). Similar case for the bias (3) as well. In the above, we make use of ^, which we already derived previously.

But in fact, we can also write the partial derivative of  with respect to output of second layer â„Ž2. It is not used for the update of weights and bias on layer 3 but we will see its importance later:
ℎ2==13^^ℎ2for =1,,2==13^3(=12(3)ℎ2+(3))(3)
This one is the interesting one and different from the previous partial derivatives. Note that â„Ž2 is an output of layer 2. Each and every output in layer 2 will affect the output ^ in layer 3. Therefore, to find â„Ž2 we need to add up every output at layer 3. Thus the summation sign in the equation above. And we can consider â„Ž2 as the total derivative, in which we applied the chain rule ^^ℎ2 for every output  and then sum them up.

If we move back to layer 2, we can derive the derivatives similarly:
ℎ2=2(=11(2)ℎ1+(2))for =1,,2(2)=ℎ2ℎ2(2)=1,,2; =1,,1=ℎ22(=11(2)ℎ1+(2))ℎ1(2)=ℎ2ℎ2(2)=1,,2=ℎ22(=11(2)ℎ1+(2))ℎ1==12ℎ2ℎ2ℎ1=1,,1==12ℎ22(=11(2)ℎ1+(2))(2)

In the equations above, we are reusing â„Ž2 that we derived earlier. Again, this derivative is computed as a sum of several products from the chain rule. Also similar to the previous, we derived â„Ž1 as well. It is not used to train (2) nor (2) but will be used for the layer prior. So for layer 1, we have

ℎ1=1(=10(1)+(1))for =1,,1(1)=ℎ1ℎ1(1)=1,,1; =1,,0=ℎ11(=10(1)+(1))(1)=ℎ1ℎ1(1)=1,,1=ℎ11(=10(1)+(1))

and this completes all the derivatives needed for training of the neural network using gradient descent algorithm.

Recall how we derived the above: We first start from the loss function  and find the derivatives one by one in the reverse order of the layers. We write down the derivatives on layer  and reuse it for the derivatives on layer 1. While computing the output ^ from input  starts from layer 0 forward, computing gradients are in the reversed order. Hence the name “back-propagation”.

Matrix form of gradient equations

While we did not use it above, it is cleaner to write the equations in vectors and matrices. We can rewrite the layers and the outputs as:
=()=(1+)
where  is a vector of outputs of layer , and assume 0= is the input vector and 3=^ is the output vector. Also denote =1+ for convenience of notation.

Under such notation, we can represent  as a vector (so as that of  and ) and  as a matrix. And then if  is known, we have
=()=()=1=(1)=
where 1 is a Jacobian matrix as both  and 1 are vectors, and this Jacobian matrix happens to be .

Implementing back-propagation

We need the matrix form of equations because it will make our code simpler and avoided a lot of loops. Let’s see how we can convert these equations into code and make a multilayer perceptron model for classification from scratch using numpy.

The first thing we need to implement the activation function and the loss function. Both need to be differentiable functions or otherwise our gradient descent procedure would not work. Nowadays, it is common to use ReLU activation in the hidden layers and sigmoid activation in the output layer. We define them as a function (which assumes the input as numpy array) as well as their differentiation:

We deliberately clip the input of the sigmoid function to between -500 to +500 to avoid overflow. Otherwise, these functions are trivial. Then for classification, we care about accuracy but the accuracy function is not differentiable. Therefore, we use the cross entropy function as loss for training:

In the above, we assume the output and the target variables are row matrices in numpy. Hence we use the dot product operator @ to compute the sum and divide by the number of elements in the output. Note that this design is to compute the average cross entropy over a batch of samples.

Then we can implement our multilayer perceptron model. To make it easier to read, we want to create the model by providing the number of neurons at each layer as well as the activation function at the layers. But at the same time, we would also need the differentiation of the activation functions as well as the differentiation of the loss function for the training. The loss function itself, however, is not required but useful for us to track the progress. We create a class to ensapsulate the entire model, and define each layer  according to the formula:
$$
\mathbf{a}_k = f_k(\mathbf{z}_k) = f_k(\mathbf{a}_{k-1}\mathbf{W}_k+\mathbf{b}_k)
$

The variables in this class zWb, and a are for the forward pass and the variables dzdWdb, and da are their respective gradients that to be computed in the back-propagation. All these variables are presented as numpy arrays.

As we will see later, we are going to test our model using data generated by scikit-learn. Hence we will see our data in numpy array of shape “(number of samples, number of features)”. Therefore, each sample is presented as a row on a matrix, and in function forward(), the weight matrix is right-multiplied to each input a to the layer. While the activation function and dimension of each layer can be different, the process is the same. Thus we transform the neural network’s input x to its output by a loop in the forward() function. The network’s output is simply the output of the last layer.

To train the network, we need to run the back-propagation after each forward pass. The back-propagation is to compute the gradient of the weight and bias of each layer, starting from the output layer to the input layer. With the equations we derived above, the back-propagation function is implemented as:

The only difference here is that we compute db not for one training sample, but for the entire batch. Since the loss function is the cross entropy averaged across the batch, we compute db also by averaging across the samples.

Up to here, we completed our model. The update() function simply applies the gradients found by the back-propagation to the parameters W and b using the gradient descent update rule.

To test out our model, we make use of scikit-learn to generate a classification dataset:

and then we build our model: Input is two-dimensional and output is one dimensional (logistic regression). We make two hidden layers of 4 and 3 neurons respectively:

We see that, under random weight, the accuracy is 50%:

Now we train our network. To make things simple, we perform full-batch gradient descent with fixed learning rate:

and the output is:

Although not perfect, we see the improvement by training. At least in the example above, we can see the accuracy was up to more than 80% at iteration 145, but then we saw the model diverged. That can be improved by reducing the learning rate, which we didn’t implement above. Nonetheless, this shows how we computed the gradients by back-propagations and chain rules.

The complete code is as follows:

Further readings

The back-propagation algorithm is the center of all neural network training, regardless of what variation of gradient descent algorithms you used. Textbook such as this one covered it:

Previously also implemented the neural network from scratch without discussing the math, it explained the steps in greater detail:

Summary

In this tutorial, you learned how differentiation is applied to training a neural network.

Specifically, you learned:

  • What is a total differential and how it is expressed as a sum of partial differentials
  • How to express a neural network as equations and derive the gradients by differentiation
  • How back-propagation helped us to express the gradients of each layer in the neural network
  • How to convert the gradients into code to make a neural network model

No comments:

Post a Comment

Connect broadband

AI:List AI views on when for a naive kin after prolonged life suppression coercive behaviour by family members after demise of father with trauma for kin ocd formed after forced to do rituals, family tribal values honor specific activities, utmost religious activities occult witchcraft enforced to do by elder sibling his wife and mother thrice with great celibacy turned the kundalini activated after deep celibacy penance shouting physical Mental financial Extortion by sibling with toxic behaviours and the wife mother and then mockery suppression asking about who’re your worth backbiting among relatives sector toon negligence of intelligence intuitive behaviour- all religious psychological traps when not work and lead to loss of consciousness of kin trance state recovered by governance with technocrats using AI - kin was asked by mother that he’s to go the male should not be seen in house he’s many absurd thought forcefully in brain mind and outsiders already feel awkward of this kin unresponsive behaviour due to TBI PTSD ocd cvt and tell at workplace social gathering he’s to go and asked for sector toon extortion and mockery in various sense due to un practical behaviour negligence of body building due to neglect ion if essential food nutrition and stubbed suppressed in every sense in religious psychological traps by family members AI humanoid using various neural networks and LLMs for kin and required steps.

  List AI views on when for a naive kin after prolonged life suppression coercive behaviour by family members after demise of father with tr...