0 1 00:00:00,960 --> 00:00:03,960 Let me scroll back up to where we had our cost. 1 2 00:00:04,020 --> 00:00:06,070 We're going to add two loops here. 2 3 00:00:06,210 --> 00:00:09,730 The first one will be "for i in range()", 3 4 00:00:09,870 --> 00:00:11,250 and then how far do we want to go? 4 5 00:00:11,730 --> 00:00:15,220 We want to go across all the theta values. 5 6 00:00:15,240 --> 00:00:23,250 So it's gonna be "nr_thetas" between the parentheses and then colon and we're going to 6 7 00:00:23,250 --> 00:00:32,550 do the same thing for our second loop we're going to say "for j in range(nr_thetas 7 8 00:00:33,120 --> 00:00:34,580 ):". 8 9 00:00:34,590 --> 00:00:37,080 Now what do we want to do inside the loop? 9 10 00:00:37,080 --> 00:00:39,360 Let's do something very unimaginative 10 11 00:00:39,360 --> 00:00:50,310 first. Let's print out all the values that we have inside our plot_t0 variable and we're 11 12 00:00:50,310 --> 00:00:52,050 going to print them out one by one. 12 13 00:00:52,050 --> 00:00:59,310 So we're gonna have "plot_t0[]" and now we have a choice - we can go row by 13 14 00:00:59,640 --> 00:01:01,500 column or column by row. 14 15 00:01:01,510 --> 00:01:13,890 So if we go by column then we'd have i in the first set of square brackets and then j in the second 15 16 00:01:14,220 --> 00:01:15,810 set of square brackets. 16 17 00:01:15,810 --> 00:01:18,320 Let's see what happens. 17 18 00:01:18,320 --> 00:01:19,550 There we go. 18 19 00:01:19,550 --> 00:01:21,860 This is us printing out 25 19 20 00:01:21,860 --> 00:01:30,370 values, the 25 values that are stored inside our theta matrix, our theta five by five 20 21 00:01:30,380 --> 00:01:35,460 array. The other way, say j and i, 21 22 00:01:35,480 --> 00:01:38,330 our output would look like this. 22 23 00:01:38,330 --> 00:01:44,990 In this case we're staying in the same column, namely the first one, and we're looking at all the first 23 24 00:01:45,020 --> 00:01:46,190 elements. 24 25 00:01:46,340 --> 00:01:51,820 If we have i and then j, then we're doing one row at a time. 25 26 00:01:51,830 --> 00:01:53,800 So this is the first element in the row. 26 27 00:01:53,810 --> 00:01:55,420 This the second element in the row. 27 28 00:01:55,430 --> 00:01:56,540 This is the third one. 28 29 00:01:56,570 --> 00:01:58,730 This is the fourth one. This is the fifth one. 29 30 00:01:58,730 --> 00:02:08,210 And then this is the first element in the second row. On the other hand, if we have j and then i, then 30 31 00:02:08,210 --> 00:02:14,270 we would be looking at the first element in the first row, the first element in the second row, the first 31 32 00:02:14,270 --> 00:02:17,120 element in the third row and so on. 32 33 00:02:17,120 --> 00:02:24,410 So the order in which we supply the indices here to our two dimensional array it matters in the sense 33 34 00:02:24,410 --> 00:02:30,870 that it determines in which order our loop will go through the array. 34 35 00:02:31,130 --> 00:02:36,190 But regardless in which order you go through you still hit up all the values. 35 36 00:02:36,230 --> 00:02:42,650 So I'm going to comment this out and now I'm going to write the code to calculate our estimated y values. 36 37 00:02:42,770 --> 00:02:49,840 So y_hat is equal to the first value in our theta_0 array. 37 38 00:02:49,900 --> 00:03:00,140 It's going to be "plot_t0[i] 38 39 00:03:00,140 --> 00:03:11,050 [j]". So this is gonna be our first t_0 value. I'm going to add "plot_t1 39 40 00:03:11,080 --> 00:03:13,830 [i] 40 41 00:03:13,940 --> 00:03:19,390 [j]*x_5". 41 42 00:03:19,730 --> 00:03:29,500 So this is gonna calculate our predicted y values for the first set of theta parameters. And then what 42 43 00:03:29,500 --> 00:03:36,660 we're gonna say is we're going to say that the plot_cost matrix is going to update and it's going 43 44 00:03:36,660 --> 00:03:39,130 to update in the same position. 44 45 00:03:39,200 --> 00:03:43,940 It's gonna be updating in [i][j]. 45 46 00:03:43,950 --> 00:03:52,100 And it's gonna be equal to the output from our lovely mean squared error function, 46 47 00:03:52,160 --> 00:04:05,030 so "mse(y_5, y_hat)", so we're gonna calculate our y_hat 47 48 00:04:05,030 --> 00:04:15,440 value for these theta parameters and then based on that we're going to calculate our mean squared 48 49 00:04:15,470 --> 00:04:25,020 error and we're gonna update our two dimensional cost array. And we're gonna do that for all of the theta 49 50 00:04:25,020 --> 00:04:28,470 values so we can plot them later on. 50 51 00:04:28,470 --> 00:04:32,700 So there's a lot of calculations going on here but there's only four lines of code. 51 52 00:04:32,730 --> 00:04:37,130 This is very, very terse but very powerful at the same time. 52 53 00:04:37,140 --> 00:04:44,040 Let's take a look at what the plot_cost variable actually looks like after the loop has 53 54 00:04:44,040 --> 00:04:45,410 run. 54 55 00:04:45,420 --> 00:04:46,420 Let's take a look. 55 56 00:04:46,600 --> 00:04:54,830 I'm going to hit Shift+Enter and here we see that it is a five by five matrix. 56 57 00:04:54,900 --> 00:04:58,330 I can prove this even though it's hard to see because of the lines wrapping. 57 58 00:04:58,380 --> 00:05:05,880 If I say "plot_cost.shape", you can see here it's five by five and we can see that any for 58 59 00:05:05,880 --> 00:05:14,180 each element we've got a mean squared error for a particular combination of thetas. Let's print this 59 60 00:05:14,180 --> 00:05:18,680 stuff out so that we can verify what's going on when we make changes later on. 60 61 00:05:18,860 --> 00:05:28,340 So I'm going to say "print", and then the string 'Shape of plot_t0', comma, "plot_t0 61 62 00:05:28,340 --> 00:05:36,390 .shape", then I'm going to copy this print statement, paste it two more times and in the second one 62 63 00:05:36,400 --> 00:05:47,460 way to change it to t1, and then the third one I'm going to change it to "plot_cost" so this 63 64 00:05:47,460 --> 00:05:55,170 is printing out the dimensions of all the three arrays that we're using and at the moment they're all 64 65 00:05:55,290 --> 00:06:00,310 five by five. Good stuff. 65 66 00:06:00,370 --> 00:06:03,470 Now it's time to throw the stuff up onto a chart. 66 67 00:06:03,670 --> 00:06:04,510 A 3D chart, 67 68 00:06:04,510 --> 00:06:05,480 no less. 68 69 00:06:05,480 --> 00:06:13,510 Let's take a look. I'm going to add a comment in this new cell "Plotting MSE". 69 70 00:06:13,510 --> 00:06:23,020 And I'm going to do our old trick with the figure, I'm going to say "fig=plt.figure( 70 71 00:06:25,140 --> 00:06:34,750 figsize=[16,12]" and then you've got some axes that I've got 71 72 00:06:34,750 --> 00:06:35,240 to create. 72 73 00:06:35,320 --> 00:06:43,870 So it's going to be "fig.gca", get current axes, and it's gonna be for a 3D projection, so "projection=" 73 74 00:06:44,470 --> 00:06:52,540 and then the string "3d", lowercase d. And our chart's gonna have three axes, it's gonna have 74 75 00:06:53,140 --> 00:06:56,800 a Y label on X label and a Z label. 75 76 00:06:56,830 --> 00:07:08,890 So I'm going to see "ax.set_xlabel('Theta 0')". So 76 77 00:07:08,890 --> 00:07:18,640 theta 0 is gonna be on our x axis and it's gonna be at font size say 20. 77 78 00:07:18,640 --> 00:07:23,890 Copy that whole line, paste it two more times and then I will make some changes. 78 79 00:07:23,890 --> 00:07:25,870 Second one is gonna set the Y label. 79 80 00:07:25,930 --> 00:07:32,050 The third one is gonna set the Z label and then the string is gonna be updated to theta 1 and then 80 81 00:07:32,050 --> 00:07:33,700 for the z axis, 81 82 00:07:33,700 --> 00:07:36,280 this is gonna be it's gonna be our cost, right? 82 83 00:07:36,280 --> 00:07:39,460 "Cost - MSE". 83 84 00:07:40,750 --> 00:07:49,310 So we've created our plot, set the size of our figure, then we've grabbed our axes object from our figure, 84 85 00:07:49,970 --> 00:07:56,600 we've set some of the attributes of the axes using the set_xlabel, set_ylabel 85 86 00:07:56,600 --> 00:08:07,370 and "set_zlabel" functions and now we do the best part - "ax.plot_surface()", 86 87 00:08:07,770 --> 00:08:16,700 and inside the parentheses, we have to supply three two dimensional arrays; the first one was gonna be 87 88 00:08:16,700 --> 00:08:17,900 our theta 0, 88 89 00:08:17,990 --> 00:08:20,060 so this is on our x axis. 89 90 00:08:20,060 --> 00:08:29,000 The second one it's gonna be plot_t1, and this is gonna be for our y axis. And the third 90 91 00:08:29,000 --> 00:08:37,310 one is gonna be the cost that we calculated in our nested loop so plot_cpst. 91 92 00:08:37,310 --> 00:08:44,140 And finally we're gonna say "plot.show()" with some parentheses at the end. 92 93 00:08:44,150 --> 00:08:48,910 Now we should be able to get a visualization of all that work we just did. 93 94 00:08:49,040 --> 00:08:54,710 And before I hit Shift+Enter, let me just quickly check the code that I've written, 94 95 00:08:54,710 --> 00:09:01,540 see if I've made any typos I'm spotting one of them here in setting the figure we've got to use our 95 96 00:09:01,550 --> 00:09:06,200 matplotlib object which is "plt.figure" not "plot.figure". 96 97 00:09:06,830 --> 00:09:14,810 So plt was our matplotlib object and plt.figure grabs our figure object. 97 98 00:09:14,810 --> 00:09:15,730 I think we're good now. 98 99 00:09:15,740 --> 00:09:23,840 So let me hit Shift+Enter and see what this looks like. Voila! It looks like.. 99 100 00:09:23,890 --> 00:09:32,390 so I realize this might be a little bit underwhelming and it looks like a video game from the 1990s. 100 101 00:09:32,390 --> 00:09:39,320 This is I think the kind of graphics they had but we can change this very, very easily. If I scroll 101 102 00:09:39,320 --> 00:09:49,850 back up and increase the number of data points we're using from 5 to say 200 and I update 102 103 00:09:50,030 --> 00:09:56,960 this cell then we're gonna generate a lot more theta zeros and a lot more theta ones with our 103 104 00:09:56,960 --> 00:09:59,080 linspace function as such. 104 105 00:09:59,210 --> 00:10:07,710 I'm going to hit Shift+Enter on this cell. I can see that we're now dealing with a 200 by 200 array. 105 106 00:10:07,910 --> 00:10:11,680 So a lot more data points that we're plotting now. 106 107 00:10:11,690 --> 00:10:18,890 And when I replot our surface by hitting Shift+Enter to update this cell then it will look something 107 108 00:10:19,010 --> 00:10:20,780 like this. 108 109 00:10:20,780 --> 00:10:22,400 Brilliant. 109 110 00:10:22,400 --> 00:10:25,250 How are you liking the navy blue? 110 111 00:10:25,250 --> 00:10:31,580 I think we've got to add a splash of color to this to make it a bit more interesting. 111 112 00:10:31,580 --> 00:10:38,180 I'm going to go back up to my plot_surface function and I'm going to make use of this color map that 112 113 00:10:38,180 --> 00:10:39,900 we imported earlier. 113 114 00:10:39,940 --> 00:10:42,960 It's gonna be an extra argument I'm gonna supply here, 114 115 00:10:42,980 --> 00:10:48,890 "cmap" and it's going to be set equal to our cm module, 115 116 00:10:48,890 --> 00:10:55,240 put a dot after it and then I'm going to use "hot" and hit Shift+Enter. 116 117 00:10:55,650 --> 00:10:58,190 Now this is starting to look pretty good. 117 118 00:10:58,220 --> 00:11:02,450 I personally think this surface doesn't just look hot, 118 119 00:11:02,450 --> 00:11:05,860 you could say it almost looks super hot. 119 120 00:11:06,760 --> 00:11:13,160 But before I lose you to this video game, let's compare our function and our calculations to our regression 120 121 00:11:13,220 --> 00:11:20,220 estimates because we can actually pull out the lowest mean squared error from our plot variable, 121 122 00:11:20,240 --> 00:11:20,740 right? 122 123 00:11:20,780 --> 00:11:34,970 So if I come down here and I write print and then write "Min value of plot_cost", comma 123 124 00:11:35,030 --> 00:11:35,440 "plot_ 124 125 00:11:35,440 --> 00:11:37,810 cost.min", 125 126 00:11:37,820 --> 00:11:45,470 and then some parentheses, I can actually pull out the lowest mean squared error from our surface plot 126 127 00:11:45,590 --> 00:11:54,290 that we just used for graphing and that is 0.94838. 127 128 00:11:54,410 --> 00:12:03,140 But hold on, I hear you say, what are the theta 0 and theta 1 values associated with that cost that 128 129 00:12:03,140 --> 00:12:04,650 we just pulled out? 129 130 00:12:04,730 --> 00:12:08,180 I mean, after all, we care about our parameter values, 130 131 00:12:08,210 --> 00:12:08,850 right? 131 132 00:12:08,870 --> 00:12:17,950 So how can we grab the row and the column indices which correspond to this minimum cost? 132 133 00:12:18,500 --> 00:12:21,070 And for that numpy has you covered. 133 134 00:12:21,380 --> 00:12:24,830 It's got a function called "unravel_index". 134 135 00:12:24,830 --> 00:12:36,140 So I'm going to say "ij_min=np.unravel_index()" and it needs two 135 136 00:12:36,140 --> 00:12:37,110 inputs - 136 137 00:12:37,160 --> 00:12:44,920 it needs the indices and that's going to be equal to "plot_ 137 138 00:12:44,960 --> 00:12:45,920 cost." 138 139 00:12:46,130 --> 00:12:47,770 and then "argmin", 139 140 00:12:47,840 --> 00:12:56,320 so this will output the indices from our 2D array where the mean squared 140 141 00:12:56,330 --> 00:12:58,580 error is at its lowest. 141 142 00:12:59,000 --> 00:13:00,500 And then we have a comma afterwards. 142 143 00:13:00,530 --> 00:13:06,910 And we supply that second input to the unravel_index function and that's the dimensions, 143 144 00:13:06,940 --> 00:13:17,020 "dims" of the 2D array that we are supplying, so we can say "dims = plot_cost. 144 145 00:13:17,230 --> 00:13:21,670 shape" and this will give us the row and the column index. 145 146 00:13:21,700 --> 00:13:23,050 Let's print this out. 146 147 00:13:23,140 --> 00:13:28,540 "print('Min occurs at (i, 147 148 00:13:28,630 --> 00:13:29,320 j) 148 149 00:13:29,470 --> 00:13:40,570 :', ij_min". So the minimum occurs at the 111th throw and 149 150 00:13:40,570 --> 00:13:42,430 91st column. 150 151 00:13:42,430 --> 00:13:48,760 So this is where after running that nested for loop the mean squared error was the lowest. The theta 0 151 152 00:13:48,760 --> 00:13:55,450 value associated with row number 111 and column 91 is as follows: 152 153 00:13:55,450 --> 00:14:09,340 "print('Min MSE for Theta 0 at plot_t0[111][91]', 153 154 00:14:09,370 --> 00:14:20,300 plot_t0[111][91])". Hitting Shift+ 154 155 00:14:20,330 --> 00:14:27,980 Enter we can see that this is fiendishly close to what the scikit learn package calculated. Now of course 155 156 00:14:28,550 --> 00:14:35,750 using a nested for loop is not better, it's very much a brute force method but I kind of wanted 156 157 00:14:35,750 --> 00:14:44,090 to show you how you can use these 2d arrays and how you can work with them and how you can access particular 157 158 00:14:44,120 --> 00:14:50,840 values using the row and the column indices. So let's do that one more time, but this time we'll grab the 158 159 00:14:50,840 --> 00:15:01,550 theta 1 value just for good measure so it'll be "print('Min MSE for Theta 1 at plot_ 159 160 00:15:01,700 --> 00:15:11,570 t1[111][91]', plot_t1 160 161 00:15:11,660 --> 00:15:15,080 [111][91])". 161 162 00:15:15,250 --> 00:15:18,670 So this should be close to 1.2. 162 163 00:15:18,710 --> 00:15:23,540 Let's take a look. And it is, it's 1.23. 163 164 00:15:23,850 --> 00:15:24,960 Brilliant. 164 165 00:15:24,960 --> 00:15:32,850 Now all that's left to do is run our gradient descent algorithm on this cost function and then we've 165 166 00:15:32,850 --> 00:15:34,500 come full circle. 166 167 00:15:34,710 --> 00:15:36,550 I'll see you in the next lesson. 167 168 00:15:37,050 --> 00:15:43,050 Super hot is actually one of the most interesting games I've played recently by the way. So I just had 168 169 00:15:43,050 --> 00:15:50,370 to mention it. It's this first person shooter but with a twist, time only moves forward when you move 169 170 00:15:50,730 --> 00:15:56,690 and there's no music it's just the sound effect of glass shattering. That's right. That's it. 170 171 00:15:56,690 --> 00:15:57,250 So yeah. 171 172 00:15:57,300 --> 00:16:02,450 If you're curious, check it out on Steam if you want a break from programming. 172 173 00:16:02,460 --> 00:16:06,030 I do hope you give Super Hot a try and let me know what you think. 173 174 00:16:06,240 --> 00:16:12,060 Just the don't do what I did and play it really late at night because if you're anything like me you'll 174 175 00:16:12,060 --> 00:16:14,350 get too excited and you'll have trouble sleeping. 175 176 00:16:14,350 --> 00:16:16,800 So yeah take care.