Contents
%Lab 3: Functions, SVD, error correction, Vectorization, Saving and Loading
1 Functions
%Functions made: Width and deg2rad %Exercise 1: Make a rad2deg function %Exercise 2: Package the inner product logic we wrote last time into a %function %Exercise 3: Package the matrix multiplication logic from lab 2 into a %function
2 SVD! The most useful thing (for us) in Linear Algebra
%a) Verify the 3 things I so boldly asserted last week. %Remember: We did not derive or prove this. So let's at least check them for ii = 1:1%e5 %Let's try 100,000 times. To see if the SVD always works M = randn(2,2) %Create some random matrix M. Any matrix will do. This will represent the operations x = randn(2,2) %Create some random matrix x that represents data. [U,S,V] = svd(M) %Do the SVD on matrix M. C = M*x %To find out what the operations matrix does to the data, apply it %Check whether SVD of M and M do correspond to the same thing? D = U * S * V' * x %The other radical claim was that the SVD corresponds to a sum of outer %products. Let's convince ourselves that this is actually true. What if I %forgot a sign somewhere? SOP = (S(1,1).*(U(:,1)*V(:,1)')*x) + ... (S(2,2).*(U(:,2)*V(:,2)')*x) %We convinced ourselves by visual inspection that the SVD and M indeed %produce the same output. Generally speaking, that is not good enough - we %want to do this programmatically. C == D; %The problem with this is that MATLAB has enough numerical precision %to get you in trouble. It's not infinite, so it's not perfect, but there %are slight rounding errors somewhere in the 16th after-digit place %So we need to set the numerical precision we want %Setting numerical precision: C = round(C.*1000)./1000; %Setting numerical precision to 3 after comma digits %This works by multiplying by thousand, rounding, then dividing by 1000 %again. This might make a good function. Because you will want to %set the precision arbitrarily, user-defined. And you will use this a lot. %And it is clunky. D = round(D.*1000)/1000; C == D; %This is nice, but still requires visual inspection. %How do we reduce this output to a single number that tells %me whether it matches or not? %Idea: Let's sum them up and compare to the number of elements in the %matrix E(ii) = sum(sum(C == D)) == numel(C); %This presumes that C and D are %the same dimensionality, because we only check C. end %Exercise for the reader: %Do this with matrices of different dimensionalities %Convince yourself programmatically that SOP also corresponds to the others %I did this just for one case %Write a numerical precision function
M = -1.5176 0.50836 -2.1421 0.39312 x = 0.3078 -1.3729 1.3686 0.67888 U = -0.59101 -0.80667 -0.80667 0.59101 S = 2.6966 0 0 0.18259 V = 0.97342 -0.22902 -0.22902 -0.97342 C = 0.22863 2.4286 -0.12132 3.2078 D = 0.22863 2.4286 -0.12132 3.2078 SOP = 0.22863 2.4286 -0.12132 3.2078
3 Let's get a visual intuition for the SVD
figure %Open a figure %Every rectangle (and we will illustrate everything here with a rectangle %can be defined by 4 numbers. The 4 numbers we will draw randomly %here are x-position and y-position of corner, width and height M = randn(1,4) %CornerX, CornerY, Width, Height %Now, we need to translate that into an x- and y-trace and plot those xTrace = [M(1,1), M(1,1)+M(1,3), M(1,1)+M(1,3), M(1,1), M(1,1)] yTrace = [M(1,2), M(1,2), M(1,2) + M(1,4), M(1,2) + M(1,4), M(1,2)] plot(xTrace,yTrace,'color','k','linewidth',3) axis equal shg %After generating the original rectangle, we now rotate it %Rotation is done by us through multiplication with orthogonal matrices %Later, we'll use one coming out of the SVD %Here, we'll use a designed one, so we can pick how much to rotate theta = degToRad(-30); %30 degrees in radians U = [cos(theta) sin(theta); -sin(theta) cos(theta)]; %Rotation matrix %Put the traces into a matrix so we can apply the rotation at once R(1,:) = xTrace; R(2,:) = yTrace; RR = U*R; %Matrix multiplication hold on %I want to see it in terms of the old coordinate system pause plot(RR(1,:),RR(2,:),'color','r','linewidth',3) S = [2 0; 0 3] %This will compress the first dimension by half and double the 2nd one SRR = S*RR; %Applying a stretch to the rotated rectangle. pause plot(SRR(1,:),SRR(2,:),'color','b','linewidth',3) %Exercise: Create a function where the user can input rotation angle, %stretch factors (one for each dimension) and an arbitrary matrix and it %outputs plots of the original matrix (rectangle) and the transformed one %Add the 2nd rotation. We only did one.
M = -0.28529 0.85964 -0.72878 0.82052 xTrace = -0.28529 -1.0141 -1.0141 -0.28529 -0.28529 yTrace = 0.85964 0.85964 1.6802 1.6802 0.85964 S = 2 0 0 3

4 Saving and loading
whos %Gives a list of variables in the workspace save('MyFirstVariables') %This saves all variables. If you want to save only some, you need to list them by name clear all %Delete everything in the workspace to show that the loading worked whos load('MyFirstVariables') %Load these variables again %If these files are *not* in your working directory (or path), you need to %give a path. Generally, we recommend to be in the path you need to be. %You can do this programmatically with cd - change directory
Name Size Bytes Class Attributes A 1000000x1 8000000 double B 999996x1 7999968 double C 2x2 32 double D 2x2 32 double E 1x1 1 logical M 1x4 32 double R 2x5 80 double RR 2x5 80 double S 2x2 32 double SOP 2x2 32 double SRR 2x5 80 double U 2x2 32 double V 2x2 32 double ans 2x2 4 logical cumsum 1x1 8 double ii 1x1 8 double n 1x50 400 double temp 500499x1 4003992 double temp1 1x50 400 double temp2 1x50 400 double theta 1x1 8 double timeWithCommand 1x1 8 double timeWithFind 1x1 8 double timeWithFunction 1x1 8 double timeWithFunctions 1x1 8 double timeWithLoop 1x1 8 double timeWithVector 1x1 8 double x 2x2 32 double xTrace 1x5 40 double yTrace 1x5 40 double
5 Error checking and error correcting code
%This is a little bit of an advanced topic, but we'll do just enough of it %for you to do the homework A = randn(2,3) B = randn(2,3) %C = A*B %Where they touch, they need to match. Here, they don't, so MATLAB throws an error %If MATLAB throws an error, execution of code is terminated. This can be %problematic. It makes sense to write code in a flexible fashion. Basically %anticipate that the user will do something ill-conceived and plan %accordingly. %MATLAB does this with try - catch statements try %This is blue. This is recognized by MATLAB as a program flow command. It modifies the program flow C = A*B %Do the best you can to do it. Of course we know it will fail catch %If you encounter an error in the course of programmatic affairs. By trying that. %Do this *instead* or *try this* instead %First thing: Tell the user that there was a problem disp('Error! You''re matrix dimensions did not match. That''s ok - we fixed that for you') C = A*B' %Transpose end
A = -0.19824 -0.66304 -0.1039 -1.1714 1.6994 0.073608 B = 1.958 0.12326 0.81588 -0.68751 -0.34372 0.19284 Error! You're matrix dimensions did not match. That's ok - we fixed that for you C = -0.55463 0.34415 -2.0241 0.23543
6 Vectorization
%MATLAB is optimized to handle matrices - as it is an interpreted %language, loops will be slow. So, they should be avoided wherever %possible. It is almost always possible. So why ever use loops? They do %have their place - they always work and they are easy to understand. %a) Creating a vector with a million elements %First with a loop clear A tic %Starts the clock for ii = 1:1e6 A(ii,1) = ii; %Fill A from 1 to a million, via loop. Every time we go through it, we add a number end timeWithLoop = toc %Stops the stopwatch, and I want to save that number %With a function clear A tic A = linspace(1,1e6,1e6); timeWithFunction = toc %With a vector clear A %Clear because I don't want to confer an unfair advantage to the vector tic %Every time you call tick, a stopwatch is started A = 1:1e6; timeWithVector = toc %Every time you call toc, it is stopped %Vector was ~200 times faster than the loop. This is typical %Function was ~30 times faster. %b) Checking whether elements are larger or smaller than some value A = rand(1e6,1); %Matrix A with a million random numbers from 0 to 1 clear B %clear B to be fair tic for ii = 1:length(A) %Go through all elements of A if A(ii,1) > 0.5 %Check if it is larger or smaller than reference value B(ii,1) = 1; %If larger, assign 1 to appropriate spot in B else B(ii,1) = 0; %Otherwise zero end end timeWithLoop = toc clear B tic B = A>0.5; %All at once timeWithCommand = toc clear B tic temp = find(A>0.5); %Use the find function to get the indices of the locations in A where the condition is true B(temp(:,1),1) = 1; %Use these indices in B, setting them 1. timeWithFind = toc %Find is an amazing function. It doesn't give you values, it gives you the %indices of the values where something you care about is true. %Command was ~60 times faster than the loop %Find was ~15 times faster than the loop
timeWithLoop = 0.84983 timeWithFunction = 0.011541 timeWithVector = 0.0017938 timeWithLoop = 1.4143 timeWithCommand = 0.00097717 timeWithFind = 0.016161
% c) Add only numbers in the vector that are large enough %Now we combine these functions A = rand(1e6,1); %Our random matrix with a million elements cumsum = 0; tic for ii = 1:length(A) %Go through all elements of A if A(ii,1) > 0.5 cumsum = cumsum + A(ii,1); end end cumsum timeWithLoop = toc %Version with find tic temp = find(A>0.5); %Just find the indices of those that are larger - ONE command, not a million cumsum = sum(A(temp)) %Using these indices timeWithFunctions = toc %No difference in sum, but the functional way is ~75 times faster. %Apart from speed, you can make sets nicely with vectors %For instance %Create a matrix of odd numbers from 1 to 100, their square roots and %squares in 50 columns and 3 rows without a loop format shortg %this avoids output in scientific notation n = 1:2:100; %Every other one is an odd number temp1 = sqrt(n); %Their square root temp2 = n.^2; %Their square, element-wise M = [n;temp1;temp2] %Stack the vectors to get a matrix
cumsum = 3.7502e+05 timeWithLoop = 0.99794 cumsum = 3.7502e+05 timeWithFunctions = 0.015579 M = Columns 1 through 6 1 3 5 7 9 11 1 1.7321 2.2361 2.6458 3 3.3166 1 9 25 49 81 121 Columns 7 through 12 13 15 17 19 21 23 3.6056 3.873 4.1231 4.3589 4.5826 4.7958 169 225 289 361 441 529 Columns 13 through 18 25 27 29 31 33 35 5 5.1962 5.3852 5.5678 5.7446 5.9161 625 729 841 961 1089 1225 Columns 19 through 24 37 39 41 43 45 47 6.0828 6.245 6.4031 6.5574 6.7082 6.8557 1369 1521 1681 1849 2025 2209 Columns 25 through 30 49 51 53 55 57 59 7 7.1414 7.2801 7.4162 7.5498 7.6811 2401 2601 2809 3025 3249 3481 Columns 31 through 36 61 63 65 67 69 71 7.8102 7.9373 8.0623 8.1854 8.3066 8.4261 3721 3969 4225 4489 4761 5041 Columns 37 through 42 73 75 77 79 81 83 8.544 8.6603 8.775 8.8882 9 9.1104 5329 5625 5929 6241 6561 6889 Columns 43 through 48 85 87 89 91 93 95 9.2195 9.3274 9.434 9.5394 9.6437 9.7468 7225 7569 7921 8281 8649 9025 Columns 49 through 50 97 99 9.8489 9.9499 9409 9801