again!
Initially, thanks a lot for the response to the primary two elements of this sequence.
It feels good that a lot of you could have discovered them useful.
As all the time, when you have any ideas, questions, or solutions whereas studying, I’d love to listen to your perspective.
Now, let’s decide up the place we left off in half 2.
Why Recompute the Identical Gradients?
We calculated the gradient for utilizing the chain rule.
[
frac{partial L}{partial w_1}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial a_1}
cdot
frac{partial a_1}{partial z_1}
cdot
frac{partial z_1}{partial w_1}
]
We acquired the identical equation that we had beforehand derived utilizing classical differentiation in Half 1.
[
frac{partial L}{partial w_1}
=
-2(y-hat{y})
cdot
w_3
cdot
mathrm{ReLU}'(w_1x+b_1)
cdot
x
]
We then got here to know simply how vital the chain rule is.
Now, what concerning the gradients for the opposite parameters?
[
b_1,; w_2,; b_2,; w_3,; w_4,; b_3
]
We’ve already seen your complete course of for . So, we typically consider repeating the identical steps which is utilizing the chain rule for the remaining parameters.
If we take a look in any respect the chain rule equations for all parameters, we are able to observe that most of the partial derivatives seem greater than as soon as.
[
frac{partial L}{partial w_1}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial a_1}
cdot
frac{partial a_1}{partial z_1}
cdot
frac{partial z_1}{partial w_1}
]
[
frac{partial L}{partial b_1}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial a_1}
cdot
frac{partial a_1}{partial z_1}
cdot
frac{partial z_1}{partial b_1}
]
[
frac{partial L}{partial w_2}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial a_2}
cdot
frac{partial a_2}{partial z_2}
cdot
frac{partial z_2}{partial w_2}
]
[
frac{partial L}{partial b_2}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial a_2}
cdot
frac{partial a_2}{partial z_2}
cdot
frac{partial z_2}{partial b_2}
]
[
frac{partial L}{partial w_3}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial w_3}
]
[
frac{partial L}{partial w_4}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial w_4}
]
[
frac{partial L}{partial b_3}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial b_3}
]
Let’s think about
[b_1]
The chain rule equation for this parameter is
[
frac{partial L}{partial b_1}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial a_1}
cdot
frac{partial a_1}{partial z_1}
cdot
frac{partial z_1}{partial b_1}
]
Now, let’s examine this with chain rule equation of .
[
frac{partial L}{partial w_1}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial a_1}
cdot
frac{partial a_1}{partial z_1}
cdot
frac{partial z_1}{partial w_1}
]
We will observe that a lot of the chain is definitely an identical.
Each equations comprise
[
frac{partial L}{partial hat{y}}
]
In addition they comprise
[
frac{partial hat{y}}{partial a_1}
]
and
[
frac{partial a_1}{partial z_1}
]
The one distinction is the ultimate partial spinoff.
For , the ultimate time period is
[
frac{partial z_1}{partial w_1}
]
whereas for b1, the ultimate time period is
[
frac{partial z_1}{partial b_1}
]
Now, if we calculate the gradient for b1, then first three partial derivatives are computed twice, although their values are precisely the identical.
The identical sample seems once we compute the gradients for
[
w_2,; b_2,; w_3,; w_4,; b_3
]
In every case, most of the intermediate partial derivatives seem greater than as soon as.
At this level, we typically have a query.
Why are we recomputing the identical intermediate partial derivatives which we’ve already computed as soon as?
If we proceed this manner, then we find yourself doing many pointless calculations.
For our small neural community, this may occasionally not seem like an enormous problem, however in actual world we’ve got neural networks with thousands and thousands of parameters.
If we proceed in the identical method for large neural networks, then it ends in growing the time and computational assets required to coach the mannequin, making the coaching course of far more costly.
What can we do right here?
The one concept that involves our thoughts is, as a substitute of recomputing the identical values, why don’t we reuse these values at any time when we’d like them.
That is precisely the thought behind backpropagation.
It doesn’t use a unique method for computing gradients however depends totally on the chain rule.
Now we all know the thought behind backpropagation.
Then we would suppose, once we compute the gradient for ,
[
frac{partial L}{partial w_1}
=
frac{partial L}{partial hat{y}}
cdot
frac{partial hat{y}}{partial a_1}
cdot
frac{partial a_1}{partial z_1}
cdot
frac{partial z_1}{partial w_1}.
]
we retailer the intermediate partial derivatives
[
frac{partial L}{partial hat{y}},
qquad
frac{partial L}{partial a_1},
qquad
frac{partial L}{partial z_1}
]
Subsequent, whereas computing the gradient of
[frac{partial L}{partial b_1}]
we are able to merely reuse the beforehand computed values of
[
frac{partial L}{partial hat{y}},
qquad
frac{partial L}{partial a_1},
qquad
frac{partial L}{partial z_1}
]
Equally, we proceed computing the gradients of the remaining parameters, storing intermediate partial derivatives at any time when attainable and reusing them at any time when they’re wanted.
What do you concentrate on this method?
From an Concept to an Algorithm
If that is the method, then why is it referred to as backpropagation?
Right here, we’re working with a small neural community to know the thought behind backpropagation.
For our small neural community, this method can be utilized or we are able to say it’s manageable.
However what if we’ve got a neural community with 1000’s and even thousands and thousands of parameters?
It turns into more and more tough to determine which intermediate values needs to be saved, when they need to be reused, and in what order the gradients needs to be computed.
However why are we even interested by this?
In any case, in apply, who computes these gradients manually?
Don’t we merely write code?
Sure, we do.
If we implement the method we simply mentioned for this neural community, it really works.
Now let’s say we construct a unique neural community with a unique structure.
Ought to we redesign our gradient computation process once more?
As neural networks grow to be extra advanced, regularly altering our implementation turns into tough.
What can we observe from this?
We don’t need to redesign the logic for gradient computation process each time the structure adjustments.
As a substitute, we’d like a normal algorithm that computes gradients effectively for any differentiable neural community, no matter its structure.
That is precisely what backpropagation supplies us.
Backpropagation isn’t just about storing intermediate values and reusing them at any time when wanted. It’s far more than that.
It supplies us an algorithm which implies a scientific method of computing gradients effectively for neural networks of various sizes and architectures.
Let’s See Backpropagation Step by Step
Earlier than studying tips on how to implement backpropagation in code, let’s first perceive the whole arithmetic behind it and see the way it works step-by-step.

Earlier than continuing, let’s attempt to keep in mind what occurred through the ahead cross.
A Fast Recap
We already know that in ahead cross, info travels from the enter layer to output layer.
At each layer, the neural community does a small computation.
Let’s see these computations one after the other.
We started with the enter function [x]
The primary hidden neuron computed
[
z_1=w_1x+b_1
]
The second hidden neuron computed
[
z_2=w_2x+b_2
]
At this level, we’ve got computed the linear mixtures for each hidden neurons.
Then the outputs from the hidden neurons are then handed by the ReLU activation operate.
For the primary hidden neuron, we’ve got
[
a_1=mathrm{ReLU}(z_1)
]
Equally, for the second hidden neuron
[
a_2=mathrm{ReLU}(z_2)
]
These activation values are actually the inputs to the output layer.
Utilizing the outputs from each hidden neurons, the output neuron computed the ultimate prediction.
[
hat{y}=w_3a_1+w_4a_2+b_3
]
At this level, we acquired our predicted worth.
Lastly, we in contrast the anticipated worth with the precise worth utilizing the Imply Squared Error (MSE) loss operate.
[
L=frac{1}{n}sum_{i=1}^{n}(y_i-hat{y}_i)^2
]
This gave us the loss, from which we understood how far our prediction is from the precise worth.
Now, right here’s one thing new which we should always deal with.
As soon as the ahead cross is finished, we’ve got the values of
[
z_1,quad
a_1,quad
z_2,quad
a_2,quad
hat{y},
quadtext{and}quad
L
]
for each coaching instance within the dataset.
We’ll reuse all of those values through the backward cross.
Now, the ahead cross is full, and we’ve got the prediction and the corresponding loss.
The subsequent step is to find out how every weight and bias contributed to this loss.
As soon as we all know how the loss adjustments with respect to each parameter, we are able to replace them in a path that reduces the loss.
That is precisely the place the backward cross begins.
Observe
Backward Cross: the execution section throughout coaching.
Backpropagation: the algorithm used to compute gradients.
It’s time for backpropagation.
We’ve already seen that within the earlier elements of this sequence, at any time when we wished to compute the gradient of a parameter, resembling , we began from that parameter and utilized the chain rule till we ultimately reached the loss operate.
Backpropagation approaches the identical drawback in another way.
As a substitute of ranging from a parameter, it begins from the loss operate and systematically strikes backward by the community.
As we’ve got seen that the loss instantly will depend on the prediction, the primary amount computed through the backward cross is
[
frac{partial L}{partial hat{y}}
]
Earlier than computing the gradients of any weight or bias, we should first understand how the loss adjustments with respect to the prediction.

You would possibly suppose that we’ve already computed it in earlier elements, whereas discovering the gradient of .
The distinction is that we’re now fixing it utilizing the backpropagation algorithm, which all the time begins right here on the loss.
We all know our loss operate
[
L=frac{1}{n}sum_{i=1}^{n}(y_i-hat{y}_i)^2
]
and in earlier elements we already calculated this
[
frac{partial L}{partialhat{y}_i}
=
-frac{2}{n}(y_i-hat{y}_i)
]
We’ve calculated the primary gradient through the backward cross.
Now, in backpropagation algorithm, as soon as a gradient has been calculated, we don’t calculate it once more.
As a substitute, we hold it and reuse it wherever it’s required whereas shifting backward by the community.
That is adopted all through the community.
Now that we’ve got computed the primary gradient, we all know how the loss adjustments with respect to the anticipated worth.
Our subsequent aim is to find out how the loss adjustments with respect to every weight and bias in order that we are able to replace these parameters to cut back the loss.
Transferring Again to Output Layer
Now let’s transfer one step backward by our community. The subsequent layer we arrive at is the output layer.
Right here, we have to discover how the loss adjustments with respect to , and .
We’ve the output equation
[
hat{y}=w_3a_1+w_4a_2+b_3
]
Let’s begin with .
Utilizing the chain rule,
[
frac{partial L}{partial w_3}
=
frac{partial L}{partialhat{y}}
cdot
frac{partialhat{y}}{partial w_3}
]
As we already calculated this intimately in earlier elements, let’s simply think about the ultimate resolution, as our predominant purpose is to know the method.
[
frac{partialhat{y}}{partial w_3}
=
a_1
]
From the earlier step, we already saved
[
frac{partial L}{partialhat{y}}
=
-frac{2}{n}(y-hat{y})
]
Substituting each the outcomes, we get
[
frac{partial L}{partial w_3}
=
-frac{2}{n}(y-hat{y})a_1
]
Equally, for and
[
frac{partial L}{partial w_4}
=
-frac{2}{n}(y-hat{y})a_2
]
and
[
frac{partial L}{partial b_3}
=
-frac{2}{n}(y-hat{y})
]
We’ve now computed the gradients for the parameters within the output layer.
Transferring Again to Hidden Layer
Now we transfer one step backward to the hidden layer.
It’s time to compute the gradients of the parameters within the hidden layer.
[
w_1,qquad b_1,qquad w_2,qquad text{and}qquad b_2
]
We’ve two hidden neurons in our hidden layers
Let’s first deal with the primary hidden neuron.
In the course of the backward cross, the gradient propagates by the next sequence:
[
L
rightarrow
hat{y}
rightarrow
a_1
rightarrow
z_1
rightarrow
w_1,; b_1
]
We will observe that earlier than reaching the parameters [w_1] and [b_1] the gradient should first cross by the activation operate.
We already know from the ahead cross that
[
a_1=mathrm{ReLU}(z_1)
]
Due to this fact, the subsequent step is to find out how the loss adjustments with respect to the hidden layer activation,
[
a_1
]
As soon as we’ve got calculate this gradient, the subsequent step is to maneuver backward by the ReLU activation and see how the loss adjustments with respect to
[
z_1
]
After that, we are able to compute the gradients of [w_1] and [b_1]
Equally, for the second hidden neuron, the gradient follows
[
L
rightarrow
hat{y}
rightarrow
a_2
rightarrow
z_2
rightarrow
w_2,; b_2
]
As each hidden neurons comply with precisely the identical sequence of steps, we’ll derive the gradients for the primary hidden neuron.
The identical process can then be utilized to the second hidden neuron.
Let’s begin by calculating the gradient of the hidden layer activation
[
a_1
]
Utilizing the chain rule,
[
frac{partial L}{partial a_1}
=
frac{partial L}{partialhat{y}}
cdot
frac{partialhat{y}}{partial a_1}
]
From the earlier steps, we already know
[
frac{partial L}{partialhat{y}}
=
-frac{2}{n}(y-hat{y})
]
and from the output layer equation,
[
frac{partialhat{y}}{partial a_1}
=
w_3
]
Substituting these into the chain rule, we get
[
frac{partial L}{partial a_1}
=
-frac{2}{n}(y-hat{y})w_3
]
It tells us how delicate the loss is to adjustments within the hidden layer activation,
[
a_1
]
Now that we all know how the loss adjustments with respect to [a_1] we are able to proceed shifting one step backward by the ReLU activation.
Thus far, we’ve got decided how the loss adjustments with respect to the hidden layer activation
[
a_1
]
However our aim is to calculate the gradients of [w_1] and [b_1]
For that, we first want to maneuver one step backward by the ReLU activation.
From the ahead cross, we all know that
[
a_1=mathrm{ReLU}(z_1)
]
So, our subsequent aim is to find out how the loss adjustments with respect to
[
z_1
]
Utilizing the chain rule,
[
frac{partial L}{partial z_1}
=
frac{partial L}{partial a_1}
cdot
frac{partial a_1}{partial z_1}
]
We have already got
[
frac{partial L}{partial a_1}
]
Now we solely must compute
[
frac{partial a_1}{partial z_1}
]
We all know what ReLU does.
If the enter to ReLU is destructive, its spinoff is
[
frac{partial a_1}{partial z_1}=0
]
If the enter to ReLU is constructive, its spinoff is
[
frac{partial a_1}{partial z_1}=1
]
Substituting this into the chain rule, we get
[
frac{partial L}{partial z_1}
=
-frac{2}{n}(y-hat{y})w_3frac{partial a_1}{partial z_1}
]
Right here, we merely write this spinoff as
[
mathrm{ReLU}'(z_1)
]
Substituting this into the chain rule, we acquire
[
frac{partial L}{partial z_1}
=
-frac{2}{n}(y-hat{y})w_3mathrm{ReLU}'(z_1)
]
What does this equation inform us?
It tells us how delicate the loss is to adjustments in
[
z_1
]
Now that we all know how the loss adjustments with respect to [z_1] we are able to lastly compute the gradients of [w_1] and [b_1]
From the ahead cross we’ve got
[
z_1=w_1x+b_1
]
Let’s begin with [w_1]
Utilizing the chain rule,
[
frac{partial L}{partial w_1}
=
frac{partial L}{partial z_1}
cdot
frac{partial z_1}{partial w_1}
]
we already computed
[
frac{partial L}{partial z_1}
]
So, we solely must compute
[
frac{partial z_1}{partial w_1}
]
as
[
z_1=w_1x+b_1
]
we get
[
frac{partial z_1}{partial w_1}=x
]
Substituting these into the chain rule, we get
[
frac{partial L}{partial w_1}
=
-frac{2}{n}(y-hat{y})w_3mathrm{ReLU}'(z_1)x
]
We’ve seen this already partly 2, which tells us how the loss adjustments with respect to
[
w_1
]
Subsequent, we have to compute the gradient of [b_1]
Utilizing the chain rule,
[
frac{partial L}{partial b_1}
=
frac{partial L}{partial z_1}
cdot
frac{partial z_1}{partial b_1}
]
As soon as once more, we reuse the beforehand computed gradient
[
frac{partial L}{partial z_1}
]
Since
[
z_1=w_1x+b_1
]
we’ve got
[
frac{partial z_1}{partial b_1}=1
]
Due to this fact,
[
frac{partial L}{partial b_1}
=
-frac{2}{n}(y-hat{y})w_3mathrm{ReLU}'(z_1)
]
Now, following the identical process for the second hidden neuron, we get
[
frac{partial L}{partial w_2}
=
-frac{2}{n}(y-hat{y})w_4mathrm{ReLU}'(z_2)x
]
and
[
frac{partial L}{partial b_2}
=
-frac{2}{n}(y-hat{y})w_4mathrm{ReLU}'(z_2)
]
Lastly, we’ve got computed the gradients of each parameter in our neural community utilizing the backpropagation algorithm.
Placing It All Collectively
If we have a look at the earlier elements of the sequence, we are able to observe that the arithmetic didn’t change.
The chain rule remains to be the muse of backpropagation.
However the best way we utilized the chain rule has modified.
As a substitute of deriving the gradient of each parameter from scratch, backpropagation begins from the loss, strikes backward by the community, and reuses beforehand computed gradients at any time when they’re wanted.
This avoids repeating the identical intermediate calculations and makes the method far more systematic.
This similar technique might be utilized to a lot bigger neural networks.
Regardless of the variety of layers or parameters be, backpropagation follows the identical course of to compute the gradients of all parameters.
The identical technique of ahead cross and backward cross is repeated for each statement within the dataset.
For each coaching instance, we get totally different intermediate values and gradients.
After computing the gradients, we replace the weights and biases based mostly on the optimization methodology getting used, resembling Batch Gradient Descent, Stochastic Gradient Descent (SGD) or Mini-batch Gradient Descent.
I hope you discovered this sequence useful, gained one thing to construct on, and loved studying alongside the best way.
For those who’re new to this sequence and wish to learn the earlier articles, you’ll find them right here.
I’d love to listen to your ideas. In case you have any questions or suggestions, be at liberty to go away a touch upon LinkedIn.
If there’s a subject you’d like me to cowl in a future article, I’d be completely happy to listen to.
Complicated concepts grow to be easy once we perceive them one step at a time.
Thanks for studying!















