interp2 returns NaN when given points are within mesh boundaries
    5 views (last 30 days)
  
       Show older comments
    
I'm writing a scrip to execute gradient descent on a function. I'm generating 150 random starting points, within the bounds of the mesh, to execute the algorithm with. However, when I run this, at some point I get a NaN - I'm pretty sure this comes from interp2. Since all the starting points I generate are within the x,y boundaries, I am very confused as to why. What do you think?
Here's the script:
fun = @(x) cos(x(1)/2)*cos(x(2)) + x(2)/10 - x(1)/5;
sol = fmincon(fun,[0,0],[],[],[],[],[-9,-8],[9,8])
fun(sol)
% Define x and y range
x = -9:0.2:9;
y = -8:0.2:8;
% Compute z values
[X, Y] = meshgrid(x, y);
%Z = comp_z(X, Y);
Z = cos(X/2).*cos(Y) + (Y/10) - (X/5);
% Plot z using imagesc
imagesc(x,y,Z);
%Set the colormap to "hot"
colormap hot;
% Add axis labels and a title
xlabel('x');
ylabel('y');
zlabel('z(x,y)');
title('z(x,y) = cos(x/2)cos(y) + (y/10) - (x/5)');
hold on;
for i = 1:150
    disp(i);
    % Set starting points and parameters for gradient descent
    x0_1 = -8 + (rand*16);
    y0_1 = -7 + (rand*14);
    gamma = 0.2;
    epsilon = 0.002;
    % Perform gradient descent starting at (x0_1, y0_1)
    descent_matrix = gradient_descent(x, y, Z, x0_1, y0_1, gamma, epsilon);
    % Plot end points of gradient decents 
    line(descent_matrix(end,1), descent_matrix(end,2),'Marker','o','MarkerEdgeColor','cyan')
end
And here's the function:
function [descent_matrix] = gradient_descent(x, y, z, x0, y0, alpha, epsilon)
  % Compute gradient of z
  [dzdx, dzdy] = gradient(z); 
  % Compute z at starting point using cubic interpolation
  z0 = interp2(x, y, z, x0, y0, '*cubic');
  % Compute gradient at starting point using cubic interpolation
  gradz0 = [interp2(x, y, dzdx, x0, y0, 'cubic'), interp2(x, y, dzdy, x0, y0, 'cubic')]; 
  % Store starting point in positions matrix
  descent_matrix = [x0, y0, z0]; 
  % Initialize steps counter
  steps = 0; 
  % Perform gradient descent until step size is sufficiently small
  while true
      % Update x position
      x0 = x0 - alpha .* gradz0(1);
      % Update y position
      y0 = y0 - alpha .* gradz0(2);
      zi = interp2(x, y, z, x0, y0, 'cubic');
      % Compute gradient at starting point using cubic interpolation
      gradz0 = [interp2(x, y, dzdx, x0, y0, 'cubic'), interp2(x, y, dzdy, x0, y0, 'cubic')]; 
      % Store starting point in positions matrix
      descent_matrix = [descent_matrix; x0, y0, zi]; 
      % Increment steps counter
      steps = steps + 1; 
      % Check if step size is sufficiently small      
      if sqrt((x0 - descent_matrix(end-1,1)).^2 + (y0 - descent_matrix(end-1,2)).^2) < epsilon     
          % Exit loop
          break; 
      end
  end
end
1 Comment
  Torsten
      
      
 on 31 Dec 2022
				
      Edited: Torsten
      
      
 on 31 Dec 2022
  
			Looking at this update
x0 = x0 - alpha .* gradz0(1);
% Update y position
y0 = y0 - alpha .* gradz0(2);
I wonder how you guarantee that x0 and y0 remain in the initial bounds 
x = -9:0.2:9;
y = -8:0.2:8;
And I ask myself why you apply gradient descent on a matrix of values for z and not on the function z(x,y) itself.
Answers (1)
  Naeimeh N
      
 on 31 Dec 2022
        
      Edited: Naeimeh N
      
 on 31 Dec 2022
  
      1- If all the the starting points you are generating are within the range of the x and y arrays, then make sure that you have sufficient data points in the x, y, and z arrays to accurately interpolate the values. 
2- Another possible issue could be that the gradient descent algorithm is getting stuck at a local minimum. You may want to try adjusting the step size (alpha) or the convergence criteria (epsilon) to see if this helps.
0 Comments
See Also
Categories
				Find more on Creating and Concatenating Matrices in Help Center and File Exchange
			
	Products
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!

