In this section, we shall be focusing on common TensorFlow methods like the Expanddims method, like
the squeeze, reshape, concatenate, stack, gather and gather, and the methods.
So we will start with the expanding method.
So here we have Expanddims.
Let's first of all suppose that we have some input.
So let's say we have a we have a um which is TensorFlow 1D uh or this 1D tensor.
Let's say we have 12345676 and seven okay.
So let's suppose that we have this tensor A and we have a method which takes in only 2D um values.
So what will what we could do here is we could add an extra dimension.
That's, uh, the role of our Expanddims method.
So here we have expanddims returns a tensor with a length one axis inserted at index axis.
So you see it takes an input and a specific axis.
So essentially here um, because we do not want to change, um, the values we have in our inputs,
like in this case a we are just going to add an extra axis of length one.
So if we want to have uh, let's just do TensorFlow expand dims.
Um, we have a and then let's say we add this the zeroth axis.
So we have that.
Well for now let's print out let's print out the shape the shape of a.
So print out a shape.
And then we have um this TensorFlow expand dims a axis specified to be zero.
There we go.
And then we run that you would find that we have this output which is 1234567 similar or the same as
what we have here.
But with the difference now that we have this extra dimension, see this?
Of size one.
And so now, um, we've, we'll be able to pass this into that method, which needs a 2D input.
Another example or another modification could be that we may want to add this axis, um, into that
position one.
So if we have an input like this and we want to add this at position one, we let's let's have this
zero.
Let's just copy this and and place out here.
So now we have position one axis one.
You see now that we have this still a 2D um tensor.
But now that extra axis was added at this position one.
So now we have a six by one tensor instead of a one by six tensor.
Again it's still the same values one, two three, 456 up to seven.
Um, obviously if we have something 2D, that's we have a 2D tensor or even a 3D tensor, you could
convert this into a 4D tensor.
So let's let's just paste this out here we have a and then we let's run that tensor flow expand um expand
dimensions.
Well let's print out the shape of a um print out the shape of a.
We have TensorFlow, expand the dimensions and then we specify a.
And then we give the axis.
So let's suppose that we do not put any axis.
Let's just run that and see what we get.
See missing required position or positional argument.
So let's have axis equals zero.
We run that.
And you see now we have a one by two by three by four tensor.
So this is a 4D tensor we have now from this 3D tensor.
So uh that's it.
If we say say we want to have one you see.
Notice how it's one by two by three.
If we say one one half one, it's now two by one by three by four.
Um, it's still the same tensor, still same values.
You see two, six, five, two and so on and so forth.
So it's still the same values.
But now, um, it's two by one by three by four.
So we've added this extra, um, this option right here, here in the documentation we have some uses
of this operation.
So you see when we want to add an outer batch dimension to a single element.
So let's suppose that you've trained a model and then you have some inputs.
So let's say the input was this year um or let's let's take this input.
So let's suppose that we have this input which is two by three by four.
Now uh, the models are generally trained in batches.
And so it wouldn't take this two by three by four.
It would want to take, um, an input of shape batch by two by three by four.
But even though we have this input which is two by three by four, we could convert it to that form
batch by two by three by four, by simply adding that dimension.
Uh, and that's done by this, um, Expanddims.
Another case where we could make use of the Expanddims method is to align axis for broadcasting.
So we could, um, add that extra dimension and then carry out broadcasting.
Then we have to add an inner vector length axis to a tensor of scalars.
It should be noted that if we have or if we set the axis to negative one, then that's simply the last
axis.
So um, here, uh, if we say negative one, you will find that this will fall on the at the last position.
So here we have two by three by four by one.
This operation is related to TensorFlow.
Squeeze um reshape and sparse expand dimensions methods.
Well let's look at this um TensorFlow squeeze here.
Instead we have that.
It removes dimensions of size one from the shape of a tensor.
So it's kind of like the opposite of what we did with the expand dimensions.
So here um let's suppose that we have this um output.
So let's say we have C which is this.
Let's print out the shape of C.
Now if we do TensorFlow squeeze and then we have C.
And then we'll specify that the axis we want to take off is the last axis.
Then you um get a new output.
So here we have let's get back here we have the C which has a shape.
But after squeezing out that um dimension we now have two by three by four, which is what we had originally.
So that's how we could, um, play around with these two methods, depending on your specific use case.
Moving on to the reshape method, we have this, um, tool which permits us to reshape our input tensors
without changing the order in which they were, um, initially.
So let's get back here.
Um, suppose we have a, uh, a constant, and here we say one, two, three, four, um, five, five,
six, seven, eight and nine.
So let's say we want to reshape this.
Um, we could do TensorFlow reshape and then we'll.
A and then we give it a new shape.
So for now we have this um 1D tensor which has nine elements.
And so we could convert this into a 2D tensor where we would have three by three.
So let's um run this and see what we get.
Let's run that.
Let's print this out.
There we go.
We you see we have 123456789.
Notice how the ordering um is, is maintained.
Now you could, you could have three by three by one run that again see order is still maintained.
Now let's get back and say we want to have three by two.
You see we have an error.
And this makes sense because, um, you cannot have as input nine values and then want to reshape in
such a way that, um, you would have expected to have six values because, um, this output matrix
here, which is three by two, has actually six values or takes six values, because obviously it's
three by two.
So that's three rows, two columns, that's six values.
And so given that our input is um above that, this reshaping cannot work.
So you have to be careful to make sure that, um, the shape you pass in actually matches with the,
the input you're, you're sending in here.
And so sometimes when you are not sure, you could say for example, negative one.
So if we put negative one right here.
You'll see that it's going to TensorFlow is going to figure out, um, what is the right value for the,
for the, uh, for this position.
Now, if you put for obviously if there is no number that when you multiply by four it's going to give
um nine.
So it's not going to work.
But let's say we put let's try negative one here.
We try negative one.
We still have an error.
So reshape only one input size maybe negative one not both.
So because we have both here it doesn't work.
So let's say we have that three negative one.
And then let's say one.
Run that again.
And we should have this 331.
So that's it.
That's how we um carry out the reshaping.
Now we could have um, 2D inputs like you have here in the documentation.
Scroll down.
You could pick out some examples.
So let's say we have this T one.
Let's take this t one and then we paste it out here.
There we go.
We have t one.
Spin out the shape of T one.
Um, has an attribute shape.
Well, this is TensorFlow constant.
Um.
That's fine.
Put this way and then we close that.
So we have t one shape now.
And we could reshape this um into a 1D tensor.
So we could, you could do um TensorFlow reshape of t one um with of shape six.
So we'll run that.
And you see that works.
So we now reshape this into a 1D tensor.
Again notice how the order is maintained.
So if we had um four here and then here we had let's say two.
You run that and run this, we should have 1432656.
So the order is, um respected.
We now move to the next method, which is going to be the concat method.
Um, let's get back to see.
Here we have c, um, concat.
There we go.
We have this concat method.
And what this concat method does is it concatenates two tensors along a given dimension.
And so that's why here you have to specify the values.
That's the two the two tensors or the different tensors.
And then you also specify the axis.
Let's copy this example and show how the Concatenate method works.
So here we have T1T2.
There we go.
Um then let's let's run this and then let's do concatenate that's concat.
And then we'll specify t1 and t2.
Then we have the axis which is set to zero.
Now let's first of all start by printing out the shapes of T1 and out of T2.
As you could see the both um two by three tensors.
And so what the Concatenate method does is uh, when you specify the axis, it's going to concatenate
the two tensors along this specified axis.
So two, three um together with two three is going to produce uh four three because you, you specify
that the axis is zero.
So along this zero axis we carry out the concatenation.
And then we're now left with an output which is four by three.
And that's exactly what we see right here.
Now notice how um this 123456 is this first T1.
And then 789 ten 1112 is the next T two.
So what if we modify this axis.
So let's let's take this to be axis one.
If you have axis one then we'll go from 2 to 3 23226.
You see we now concatenating along this um axis one.
So now we have two six.
So let's run this and see what we get.
You see now we have this two by six.
So again we have 123456123456.
There we go.
And for this first part see this first part.
And then we have 789 ten um 1112.
So depending on whether you want to concatenate along the rows or along the columns, you just need
to specify that where at the level of this axis.
Now let's take some other example from the documentation.
Scroll down and let's copy this example here.
We could start by printing out the shape.
So we have t1 and t2 shape.
There we go.
We have 222 and 222.
And so if we concatenate along the last axis as the example was given in the documentation, then we
would have um let's add this code cell and show that.
So let's just copy this.
We have 222 concatenated with 222 along the last axis.
That's because we specify negative one.
Then our output should be two two and then four.
So we'll still have our 3D tensor as output.
But the 2D tensors or the matrices we have in this um 3D blocks or in this 3D tensor.
But this 2D blocks will be concatenated such that we now have um, two by four shapes.
So instead of this two by two we take this concatenate with this, and then from two by four.
Then we take this, concatenate with this, and we form two by four.
So let's go ahead and run that and see what we get.
You see, we have one 2 or 1, two, two, three.
Let's get back here.
Scroll back up.
We have 122, three.
You see that?
That block here.
Is it right here.
1223.
And then we have seven four, eight for this block.
See this block right here.
Well it's actually this with this.
And then for the next one we have 4453 which is this block.
4453.
And then we have two, ten, 15, 11.
Now if this was along the z axis, as if we had zero here, then we should have four, two, two.
You see.
So now we're going to have um, instead of having blocks of two we're going to have blocks of four.
So let's run that and see what we obtain.
There we go.
You see, now, instead of having, um, a block like here where we had, um, just two, like here,
we just have two blocks of, um, two by two matrices.
Now we have four blocks, um, of two by two matrices.
And obviously we have one, two, two, three one, 223, four, 453.
And then we have 74842 ten 1511.
So that's it.
Now another common and similar method is the stack method.
What the stack does is it stacks a list of uh rank R tensors into one of rank R plus one.
So getting back is similar with the concat.
So we're taking the values.
And then we specify the axis.
So let's get back and see what we get when we carry out stacking.
Um for this first example.
So here we have t1 and t2.
Now let's take this off.
Let's do TensorFlow stack.
TensorFlow stack.
We have um t1 t2.
And then we specify the axis.
Let's take axis zero.
We run that and see what we get.
Well let's take this.
Let's run this again because we had um created a new T1 t2.
So uh one thing you will notice is that with a concat let's get, let's take the axis to, let's say
the axis to zero with the concat.
There is no, um, extra dimension created.
So um, if our inputs are four by three or if our inputs are 2D, then our output will be 2D.
Whereas with the concat, if our inputs are 2D, then our output will be 3D.
And if our inputs are 3D, our output will be 4D.
So here we have this um tool 123456.
There we go.
And then we have 789 ten 1112.
You see, they have been stacked in such a way that they now form, um, a 3D tensor where we have this
extra dimension created.
So if you look carefully at the start of the stack method, it's similar to um, carrying out, um,
expanddims.
So making use of the Expanddims, um, let's, let's have the axis set to zero.
So we add an extra dimension to T1, and we also add another extra dimension um, to T2.
So there we have this extra dimension added to both T1 and T2.
Let's reduce this.
Um, and then uh we run that so well this is concat actually.
So let's get back.
Um, let's just have, let's just have this.
Copy that.
And then we let's, let's run it just above here.
So here is concat concat.
And let's take this back to um original stack.
So when we stacked um t1 t2 okay.
So that's for stack run this again to be sure.
So this is for stack two by two by three.
Now what the relationship between concat and start is uh, for the concat you, you can or you can get
the stack from concat by adding this extra dimension.
Remember we said we're going to add an extra dimension.
And here we we just simply add that extra dimension for T1 and add it for T2.
And then carry out the concat normally.
So you will notice that now we have exact same output with a with a stack and with a concat.
So you see clearly the difference between the two.
With a concat no extra dimension added, or the stack will have that extra dimension added.
Now if we change this axis to the last one negative one, we're going to have two by three because our
inputs are two by three.
So our inputs are two by three and now by two.
So the stacking is done on the last axis.
So here we have um one seven or.
Well we have 123456.
You see.
Notice this here this arrangement.
Uh 123456.
And then here we have seven, eight 910, 11, 12.
So, um, the arrangement now is different from what we had before when the axis was set to zero.
Again, you just need to specify a negative one year on that we're getting something different.
But we just needed to have this expand, uh, this extra dimension added at the end.
So let's run that again.
And you see, now that we have exact same output with a stack, our next method is the pad method.
And essentially it pads a tensor with given values.
So here we have TensorFlow pad takes in a tensor um the patterns the mode and the constant values which
will pad with.
So let's take this example and illustrate or show exactly how it works.
Let's get back to our notebook.
We paste this out here.
You see we have this t.
So that's our T.
Then we have the patterns.
We're going to explain exactly how this works.
Then let's print this out.
So let's print this out and see what we get.
You see we have 123456.
And then all this is padded with this zeros.
Now to understand how this is, uh, how we get this kind of output, you should note that this value
for the or this values we have here for the patterns, permit us to know, um, how many values are
for at the top.
We're going to add how many values.
At the bottom we're going to add how many values to the left we're going to add and how many values
to the right we're going to add.
So if you notice here we have 123.
And then we have 456.
At this top is padded with zeros just one.
And at the bottom we spider with zeros just one layer.
So we have just one layer up and one layer down.
But to the left we have two layers.
Notice how we have two layers.
And to the right we have two layers.
Let's say to the right we want to add um two other layers.
So let's just change this to four.
We run that again.
You see now that to the right we have this four layers.
If we want to the top to be four, we run, we change that.
Run that again.
You see now that to the top we have four layers.
To the right we have four layers to the left we still have two layers.
And then to uh the bottom we have one layer.
That's the role of this patterns we have here.
Um, we also have different, uh, this coming different formats.
So we could change this like you see in this examples, uh, we have here.
Well, this is stack.
Let's get back to pattern.
Okay.
So um, if it's constant and then we specify the constant values.
So we could, we could change this here um constant values.
So let's say we, we have constant values and we set that to let's say um 20 or let's say let's just
say uh nine value that's not found in the original tensor.
So here we have nine, you see, all padded by nines getting back apart from padding with constant values,
we could decide to reflect or use reflect or use um, symmetry.
And what this means is that the patterns or the padded values we have surrounding our main tensor,
like here, are going to be gotten from the tensor itself.
And the way these patterns are gotten will be will be dependent on whether it's a reflection or whether
we're making use of symmetry.
The next method we'll look at is the getter method.
So what this gather does is it gathers slices from the tensor axis according to the indices.
So remember when we're um working with um indexing we had for example, we could build we could say
is this um constant.
And here we had say zero one.
Well let's just say 4567.
So if we had this input and then we wanted to have, um, the elements five and six, in that case we
would do a uh, one, two, you know, A13 actually, because it's um, three minus one.
So there we have, um, five and six.
So we go one and then oh, this is zero, this is zero, this is one, this is two.
And that's exactly why we have this five, six.
Now what if we wanted to have four seven and then five.
So what if we do not want um, this to be in a specific order.
Um, that's where the gather method comes in.
So if we want to have, um, this four, seven, five, then we'll say gather, we'll specify a, we
specify that um, four which is zero.
Um, seven is the last.
Um that's zero, one, two, three.
So three and then five is one.
So when you specify this way and it set the axis to zero, you see now that we have 475.
So it's capable of gathering all those elements um based on this order we had set, let's suppose we
have this b we have this B TensorFlow gather and we specify b.
And let's suppose we want to have this this right here.
We want to have this.
And then we want to have this.
But we want to have this first before having this.
So in that case we will have b.
We'll specify that we we want to have the last because this is in row wise.
This is zero.
This is one this is two and this is three.
So one to have three and then zero.
And the axis we specify that's the row the the row.
So it's row wise.
So when we run this now you see we have 33020530205.
And then zero which is 29030.
So it permits us to gather elements from our tensor um, very easily.
Now imagine we wanted to do this same process, but column wise we'll specify the axis to be one.
But here we have um, let's say we want to have this the, this column that's 9630.
And we wanted to have three negative two zero zero.
In that case we will do um one because this is this is zero.
This is one, this is two and this is three.
So we'll have one and three.
And then the axis is set to one.
So we run that again.
You see we have 9630.
And then we have three negative two zero zero.
Now what happens when this indices is 2D.
So let's simply copy this again and paste this out here.
So let's suppose that instead of one three we have one three.
And then let's say um one zero or let's let's say zero two.
Well let's, let's change the order to zero.
So we have one three and two zero.
Close that and that's fine.
Okay.
So instead of one three we have 1320.
So let's see what we have here.
Let's change the axis to zero.
Run that.
And axis zero.
So you would see that, um, it's going to be similar to what we've seen already.
So here we have one three.
So and and because we specify the axis to be zero we are going to pick along the rows.
So here because we've selected axis to be zero we would have one because this is zero.
This is one.
We have this one we have two.
Then we have three.
So you see that we have this here one.
And then we have three which is gotten from um our input.
Now when we have one three, two zero you see that it's similar.
We have the one, we have the three and then two.
You see this is two because this is 012.
This is two one, three five.
So here we have 13501.
And then zero is 29030.
So 29030 exactly as we would expect.
And that's how the gather method works.
Now another method which is similar to the gather method is a gather NDI method.
And the main difference here is that, um, the gather can do this across multiple or rather the gather
ndi um gathers across multiple axes so it can gather elements of a matrix instead of a row or column.
So let's take a simple example to illustrate how the gather NDI works.
Here we have TensorFlow gather.
Um, and well, let's just copy this.
One thing you should note is the fact that it doesn't have, um, an axis.
You don't need to put an axis.
So because as, as has been described here, um, it gathers across multiple axes.
So you don't need to specify a, um a given axis.
So now we have one three, two zero.
You see that.
Well let's, let's run this.
Let's have here gather and run that and see what we get.
You see we have negative two one.
Now the reason why we have negative two one here is simple.
What this gather does is it gets like here we have well let's put this up so it's closer to our be okay.
So here we have let's rearrange this.
We here we have one three.
So unlike the gather which is going to say for example we gathering along all the rows then it means
that we could pick the the first and then we pick the third.
Here we are going to pick the elements directly.
So when you specify 123 it's going to go zero one.
And then 0123.
That's how we have negative two.
And then when you specify two zero it's going to go 012 and then zero which is one.
So that's how we get this output.
Now if you want to get something similar to this one three we had here, what you would need to do is
take this off.
So now it's one it's going to pick all the row.
Um and then it will take or you take your three put your three.
So you're also going to pick the third row.
We run that and you see we get um, exactly what we got with the scatter while specifying your one three.
So you see that while the two methods are used in gathering, um, some elements from the inputs, they
have different ways of functioning.