All right so now it's time to visualize our mean squared error cost function. 1
Now I don't know about you but I can't look at these equations and picture what they actually look like 2
in my head. 3
I'm the kind of person who really needs a graph or a chart or something visual to really understand 4
what's going on. 5
So let me insert a subheading here with Markdown, two pound symbols and I'll just write "3D plot for the 6
MSE cost function" and let's have a subheading here that reads "Make data for thetas". 7
The first step in creating our plot is to create a whole range of theta values that we can use to calculate 8
the mean squared error for. 9
So remember I said that the cost function depends on the parameter values and not the data itself, 10
not the x_5 or the y_5 arrays but it depends on the theta. 11
That's what the cost function is trying to map. 12
The first thing that I am going to do is I'm going to set the number of data points for our chart. 13
I'm going to call this nr_thetas. 14
It's gonna be a variable. 15
And to start off with I'm going to set it equal to 5. 16
And then I'm going to create our data points. 17
So I'll create a variable called th_0, 18
I'm going to set that equal to the return value from numpy's linspace function. 19
That's gonna be "np.linspace()". 20
And then we're gonna supply three inputs - 21
start value, 22
we're gonna say -1; stop value we're going to say is equal to 3, and a number of intervals, so the number 23
of points that we're gonna create, I'm going gonna set that equal to "nr_thetas". 24
So that way when we look at th_0, we see that it has 5 values it's an array of 1, 2, 3, 4, 5 25
items. 26
Then I'm going to copy this line of code here, paste it in and have the same thing for theta_1, theta_1 is also 27
going to go from -1 to 3 and it's going to have 5 values. 28
So what we've done here is we've created a one dimensional array, but we're gonna have a 3D plot, 29
so we're going to need a two dimensional array. 30
We're not plotting a line, we're plotting a surface and for these we need an array of two dimensions. 31
The way we're gonna create a two dimensional array is by using numpy's mesh grid function. 32
So we've done this before. 33
And just to differentiate between the one dimensional and two dimensional variables I'll create another 34
set. 35
So I'm going to say "plot_t0, plot_t1 = np.meshgrid()", so meshgrid is the 36
function that will give us a two dimensional array and we're are using this comma notation "plot_t0, 37
plot_t1" as a way of unpacking a sequence because meshgrid will return to us a tuple. Meshgrid in 38
turn needs two inputs, so it's gonna be theta 0 and theta 1. From these inputs it's going to create 39
our 2D arrays. 40
So if we look at "th_0.shape" we'll see it's a flat array, one dimensional with 5 41
elements and if we compare that to "plot_t0.shape" then we see that it is a 5 by 42
5 array. It's two dimensional It has 25 elements total so if I delete the ".shape" and 43
I press Shift+Enter I can see it here it looks like this - 5 by 5, 25 elements total. 44
Now it's time to calculate the mean squared error for all the theta 0 and all the theta 1 values 45
in our range. 46
So let me ask you this - do you think that the cost that we calculate will have one dimension or will 47
it have two dimensions? And the answer is it's also gonna be two dimensional - the surface plot needs to 48
know the mean squared error value for all the combinations of theta zeros and theta ones - we're gonna 49
be plotting a surface not a line after all. 50
So here's what we're gonna do - we're gonna start out with a two dimensional array of just zeros and then 51
we're gonna calculate the mean squared error for each value in our array separately. 52
This will give us a chance to learn about another Python programming technique, which is very, very common 53
and that's using nested loops. 54
Let's add this as a subheading actually, so I am going to change this to Markdown, three pound signs and then I'm going to say 55
"Calc MSE using nested for loops". Going to add a few more cells down here. 56
Keep working in the middle of the screen. 57
And the first thing I'm going to do now is I'm going to create a two dimensional array just of zeroes, so 58
numpy actually has a function called zeros which is perfect for this. 59
All we need to do is supply the dimensions of the array that we want as an output. 60
So the variable that's going to hold on to all our mean squared error calculations is going gonna be 61
called "plot_cost" 62
and that's gonna be equal to the return value from this zeros 63
function that I mentioned. 64
So "np.zeros()" 65
and then inside the parentheses we supply the dimensions. 66
So if I supply 2 by 3, 67
So "2,3" and then say "plot_cost", 68
I can see what a 2 by 3 array of zeros will look like. 69
There'll be 3 columns and 2 rows, 2 rows 3 columns. 70
If it's 5 by 5, 71
on the other hand it'll be 5 rows and 5 columns. 72
Now I'm not going to have a hardcoded 5 in here. 73
Instead I'm going to use the "nr_thetas" variable and and feed it as an argument to 74
our zeros function. 75
So what I'm going to do is I'm going to supply a tuple, which you can see by the two parentheses and it's 76
gonna be square, it's gonna be symmetrical, so it's going to have the same number of rows and the same 77
number of columns. 78
So it'll be "nr_thetas, nr_thetas". 79
This is gonna be the input to our zeros function, 80
so if I ever have to change my variable up here and update this cell then my plot_cost 81
will update as well. 82
Now it's time to talk about nested loops. 83
Let me add that as a comment here, say "Nested loop practice". 84
Let me show you what I mean. 85
So to create a nested loop, we're going to use two for loops. 86
So the first for loop it's gonna look like this, is gonna read "for i in range()" and then say the number 87
3 between the parentheses, then colon, and then inside this for loop there'll be another for loop. 88
So I'm going to write "for j in range(3):" and inside the second for loop, 89
I'm going to put a print statement. 90
So, let me print the string "Hello" and hit Shift+Enter and what we see is that hello is printed a total 91
of 9 times so, three, three and three; 3 times 3 is 9. 92
So this is how many times we print "Hello". 93
Let's go a step further than just printing "Hello" nine times. 94
Let me show you another way of doing the string interpolation with Python. 95
This is a different way that we can work with the strings from what we've seen before. 96
This particular method is called an "fstring". 97
It's an fstring because there's an "f" right in front of the string. 98
So it's gonna be "f" and then you have the single or double quotes and then within the string itself I'm 99
going to say "value of i is" and then I'm going to use a set of curly braces and inside these curly 100
braces, I can access a variable in my Python code. 101
So for example I can access this variable 102
i here, the iterator in my outer loop. So I'm going to 103
say "i" 104
in between the curly braces, and then I'm going to continue "and j is", 105
and then another set of curly braces, 106
and then inside these curly braces I'm going to actually put the value "j". 107
So I'm accessing this variable, the second iterator the one for the inner for loop. And 108
now I'm going to hit Shift+Enter', see what we get. 109
So what we see here is that the values that are printed out from inside these curly braces change every 110
time the loop is executed by having this special notation, the f in front and then the curly braces were 111
able to tell Python that something inside this string should not be considered a string. 112
Instead we're able to reference values that are stored in variables elsewhere. 113
Now the other thing that's really, really cool about this particular pattern is that we can see what happened 114
exactly when our loop executed 9 times. 115
So before we had "Hello" printed 9 times. 116
But this time we can see what's actually going on and how these i and j values are changing. When the loop 117
first starts out, 118
i is equal to 0, 119
and j is equal to 0. 120
And then what happens is that the inner loop executes three times, j becomes equal to 1 and then to 2. 121
And after that it's done executing. 122
And then the outer loop increments by 1. 123
So i goes from 0 to 1, and then it's j's turn again; j goes from 0 to 2, executes 3 times 124
and the whole thing repeats one final time. 125
So one of the things you can probably already tell is how this might be applied to many, many different 126
kinds of problems. 127
In particular it goes very, very well with iterating through a 2D array or a 2D matrix. If you want to 128
hit up every single value then you can go row by row and column by column. 129
And this is exactly what we're going to do. 130
The important thing with this sort of stuff as with all Python code is to make sure the indentation 131
is correct and that way Python knows that this loop is indeed nested inside this first one.