All right. 1
So in this lesson we're gonna do a couple of things. 2
We're gonna be plotting our gradient descent path on our 3D surface so we can see our algorithm slowly 3
working its way down to the bottom of the bowl. 4
But this is also a really good opportunity to learn a little bit more about numpy's n-dimensional 5
arrays because these things are incredibly powerful and we're gonna be taking a look at how we can append 6
values to arrays, how we can concatenate arrays, how we can slice arrays and how we can select particular 7
columns of an array. Let's commemorate the upcoming topics with a new section heading. 8
So I'm going to change this cell to Markdown and then I'm going to put two pound symbols here and then I'll 9
write "Graphing 3D Gradient Descent & Advanced Numpy Arrays". And I'll hit Shift+Enter. 10
I'm also going to add a few more cells to the bottom so that way I'm working more in the center of the 11
screen. Now to do our plotting what we're going to do is we're gonna scroll a little bit up and we're 12
going to copy this cell here, I'm going to copy the cell and I'm going to paste this cell here. 13
And the reason I'm doing this is so that I can add some code to it. 14
I want to modify the cells so we have a record of what we've been doing but this is also the cell which 15
is gonna contain the code that tracks the progress of our gradient descent. 16
So I'm going to add some code to this. Now, as before the values that we're gonna be tracking are how 17
are our parameters change as the loop runs and the place where I'm going to store all these values that we're 18
gonna be tracking is going to be a variable that I'm going to call values_array and 19
the very first value this values array is going to have is going to consist of our initial guess, our 20
params. 21
So leaving the code like this, 22
let's take a really quick look at the shape of our values array. 23
So I'm going to print the "values_array.shape" and see what I get. 24
The result is gonna be the very first line that's printed below the cell so I can see that this is a 25
tuple and my array just consists of two elements and that's no surprise, those elements are gonna be 26
1.8 and 1.0. 27
And that's all this shape attribute is showing us. Now the thing is, I can transform this array if I want 28
to. Instead of having a one dimensional array with two elements, I can have a two dimensional array with 29
one element each instead. 30
But why would I want two dimensions? 31
Well what I want to do is I want to keep all the x values in one dimension and then I want to keep all 32
the y values in the second dimension. 33
So what I'm going to do is I want to transform my array into a new shape so handily there is something 34
called a reshape method which takes two inputs - 35
one is the number of rows and the other is the number of columns. 36
So rows are first so it's gonna be 1,2 - 37
those are gonna be the arguments to the reshape method. 38
Now if I rerun the cell have a look at the output below the cell to see how many rows and how many columns 39
my array has now. 40
So you should see this updated to 1,2 - one row, two columns. I now have a two dimensional array. 41
My x value is gonna be in my first dimension and my y value is going to be in my second dimension. 42
Okay yeah, 43
so you might say "Yeah Phillip great preamble, but where are you going with this?". 44
And what I would say to that is I'm setting the scene for the code I'm going to add to my for loop right 45
here. 46
But before I do that and move on to the code inside the gradient descent, let me add a new cell below 47
this one and just go through a few methods and a few techniques for working with multi-dimensional arrays. 48
So I'm going to add a little comment here and I'm going to call this "Advanced Numpy Array Practice". 49
And the first thing I'm going to do of course is create a dummy array. 50
This array is going to have a name, 51
it's going to be called kirk, and it's going to be equal to np.array, so we're creating an array, parentheses, 52
and then I want this array to have one row and two columns. 53
So I'm going to have one square bracket and then a second square bracket and inside I'm going to put 54
a string. 55
I'm going to say "Captain" and then comma and then I'm going to have another string and that's gonna read "Guitar". 56
So two strings surrounded by two square brackets. 57
So just to verify that we indeed have a two dimensional array, 58
let's print out "kirk.shape" below the cell and hit Shift+Enter. There we see that indeed we have 59
one row and two columns by using this notation here. 60
All right. 61
So upwards and onwards. This time we're gonna create a two by two array. 62
So this is gonna be two rows, two columns. 63
And I'm going to call this array "hs_band" and we've said it's equal to "np.array()", 64
and then I'm going to add two square brackets again and inside the second square bracket I'm going to 65
add a string and call it "Black Thought". 66
And then after the string and I'm going to add a comma and then another string "MC" and then after that first 67
closing square bracket I'm going to add another comma and then I'm going to open another square bracket, 68
and add the string "Questlove", comma and then the string "Drums" and then you'll have two square brackets at 69
the end and the parentheses. 70
So this is our second array and let's print out the shape. So "print(hs_band.shape)" and 71
here we can see that indeed this array is two by two - two rows two columns. 72
Now when working with multi-dimensional arrays like this let me ask you a question. 73
How do you think we would go about selecting a particular item in the array? So previously we just used 74
the square bracket notation and then we supplied an index. 75
Let's see what happens when we do that on a two dimensional array. 76
So I'll print and I'll just put down in the string the code I'm going to add after the string. 77
So I'm going to say "hs_band[0]", 78
and then after the string I'm going to add a comma and then put the actual Python code here "hs_band[0]". 79
I'm going to hit Shift+Enter here. So we can see here that if I use the very, very same approach with a two dimensional 80
array for selecting a particular item as with a one dimensional array I don't get back one item, 81
instead I'm getting back an entire row. I'm getting back all the elements in that first row. But the thing 82
is that kind of makes sense, right? 83
We have two dimensions so we shouldn't be supplying one index, 84
we should be supplying two indices. 85
How do we do that? 86
Let me just copy this line of Python code here. 87
And add a print statement. 88
Paste the print statement below. 89
And then instead of having just "hs_band[0]", 90
I'm going to add another pair of square brackets here and between those I'm going to put the value 1. 91
I'm going to add that to my string as well so that we're consistent and I'm going to hit Shift+Enter and what 92
you should see is that in this case we're selecting one particular element, we're selecting the first 93
row and then the first column in that row. 94
So we're honing in on the string "MC". If you have trouble seeing this in your print statements then 95
you can put a few spaces here and a semicolon, might make it a little easier and then you'll have a nice 96
separation between the the string and the value that you're getting back with your Python code. 97
All right. 98
So this was a really one difference between working with a one dimensional array and a two dimensional 99
array. 100
Now, as a challenge, 101
can you modify this print statement to select the word "Questlove" and have that printed out right here 102
where it says "MC" currently? 103
I'll give you a few seconds to pause the video and give this a shot. So I hope you had a chance to solve 104
this. 105
Questlove is in the second row. 106
So we start counting at zero. 107
Second row is at index 1 and it is the first item in the second row, 108
so first column. 109
So this would be column zero. 110
Let me Shift+Enter to prove to you that this is indeed the case. 111
And there we go. 112
We see Questlove printed out below. 113
Now let's create another array but through a different way. 114
I'm going to call this array 115
"the_roots". I'm going to set it equal to "np.append", 116
so I'm not going to write "np.array", I'm going to write "np.append". 117
I'm gonna open the parentheses and inside these parentheses I'm going to supply three arguments, three inputs - 118
the first argument is gonna be the array I want to append items to, this is gonna be "arr = hs_ 119
band", I'm going to put comma and supply my second argument and these are gonna be the values so I'm going to write 120
"values = kirk" and then I'm going to supply the third argument and this is going to be the axis. Axis is gonna 121
be equal to zero. And below all this I'm going add a print statements, so I'm going to say "print(the_roots)". 122
Now before I hit Shift+Enter, I'm going to make sure my variable names are the same. 123
So, 124
so this is gonna be "the_roots = np.append(arr=hs_band, values= 125
kirk, axis=0)" and then I am indeed printing this variable here, printing the_roots. 126
Now let me Shift+Enter so you can see what this looks like. Now what we've got is that below the cell, there 127
are six elements being printed out. 128
We've got the four elements from hs_band and we've appended two extra elements, namely "Captain" and "Guitar" 129
to these four elements. 130
So our array called the_roots is actually three by two, 131
it's a three by two array. 132
Now let's take a look at this append method. The append method takes three arguments - 133
the first one is, well, the element where the items are going to be appended to 134
and the second argument here is our array which was appended to hs_band and then we've got 135
this third argument here - 136
axis; axis=0 and the first time I saw this I thought "Man, this is a really confusing word" but 137
it's actually pretty simple. Axis basically means should we add our values as a row 138
or should we add them as a column. 139
So what we've done is we said "axis=0", 140
and that means that our values inside kirk are added as a row on to our two by two array. So our two by 141
two array became a three by two array. 142
If axis instead was equal to one, then we would be trying to add our new values as a column. 143
But you have to be careful with these axes. If you try to change this to one and press Shift+Enter it 144
actually won't work, because Kirk is actually a one by two array and not a two by one array. 145
So you have to be careful because your axes have to match you can't add up or append items to arrays 146
where the dimensions don't match. 147
Kirk has one row, two columns and you can't add a one row two columns as columns to a two by two. 148
If you actually wanted to do that you'd have to reshape the Kirk array to be two by one. 149
This is the only way it would work. 150
In this case you would indeed get a two by three matrix, a two by three array. 151
So I hope this makes sense - if you're appending stuff to an existing array then the shapes of the array 152
have to be compatible. 153
So in this case what I actually want to do is I want to add rows on to my existing array so I'm going to say 154
axis=0 155
and the way I've made these arrays the rows already match. 156
So I'm going to hit Shift+Enter again. 157
So you refresh this and you can see, indeed, 158
okay I've got an artist and I've got a role in the band and here's another artist and here's another 159
role in the band, 160
and so on. Now I'm not gonna make you add all the band members of the roots individually that would be 161
very, very time consuming but um let's just pretend this band has three members for now. 162
And suppose that we want to select all the band members just by their nicknames. 163
So we want to just take an entire column from this array. 164
How would we do that? 165
And the answer is that this is actually really, really, really easy to do with some special Python notation 166
for slicing arrays. 167
Let me show you. 168
If I print out, uh, add a string here "Printing nicknames...", comma and here's how we slice our 169
array. 170
Here's how we only print out the first column. 171
We're gonna say "the_roots[]", and I'm going to supply two values - 172
the first one is gonna be a column and I'm going to have a comma and then we're to have a zero. 173
So what we're saying here is - take all the rows, so a colon is the shorthand notation here for selecting 174
all the rows, 175
all the values in the rows and that second argument here, that zero refers to the first column. 176
Let me hit Shift+Enter to show you what I mean. 177
I'm going to scroll down and there you should see "Printing nicknames... ['Blackthorn', 'Questlove', 'Captain']". 178
All right. 179
So let's practice this one more time. 180
I'm going to add another band member though, so I'm going to say the_roots and I'm going 181
to update our roots array with "np.append" and for the array I'm going to choose the_roots 182
and for the values I'm gonna say 183
"values = [[]]", 184
So I'm going to add the values here directly and then between those square brackets I'm going to provide 185
two strings - 186
the first one is gonna say "Malik 187
B", and then comma, single quotes MC, closing square brackets comma, axis again is equal to zero. 188
Having added another band member here let's print out the roles. I'm going to say "Printing 189
band roles..." 190
and then after the string, put a comma, 191
and now I'm going to throw the ball over into your court. 192
I'm going to challenge you to print out all the band roles in the roots. 193
So I'm going to give you a few seconds to pause the video and write the Python code that will print 194
out all the band members roles below the cell. 195
And here's the solution. 196
Again we're gonna use our array slicing notation so I'm going to say "the_roots[ 197
:,1]", I'm going to hit Shift+Enter. 198
I can see now that we've got two MCs, one set of drums and one guitar. All right, 199
so with these array techniques covered we're ready to move on to graphing our gradient descent. And 200
if you haven't heard of the roots then check out our song of theirs called "The Next Movement". 201
That's one of my personal favorites. A long time ago, 202
I actually went to see these guys live. 203
They came down to London and I think one of the things that impressed me most was that during the performance 204
the band members traded the instruments, 205
so like the drummer took the guitar and the guitarist took the vocals and the vocalist took the bass 206
and so on. 207
And having done that they proceeded to play their next song just showing everyone in the audience that 208
they weren't one trick ponies but actual musicians who could do more than than one thing. 209
I mean I haven't gone to that many concerts but I've never seen that before. 210
So yeah check out these guys. 211
They're pretty cool.