Trying to plot an estimate of a surface with plot3

6 views (last 30 days)
I have a dummy dataset and a function f fitted to it with ordinary least squares. The function f = @(x,a) a(1)*x + a(2) takes a = [a(1) a(2)] as input in addition to x coordinates of the datapoints. The idea is to plot a 3D "dot surface" with plot3 to demonstrate that fminsearch used on the sum of squares function fa = @(a) sum( (y-f(x,a)).^2 ) actually finds the optimum value of a, which is also plotted.
I can't make the plot appear properly. The dots (values of sum of squares) appear on a line x=y on top of each other, instead of one value for each xy pair. Here x and y are a(1) and a(2), and z is the sum of squares fa given the input a = [a(1) a(2)]. The question is, how to make the dots appear as a surface? It is possible with plot3, the second image is an example of the desired result. Here is my code:
f = @(x,a) a(1)*x+a(2);
x = [0.558755760368664;0.835253456221198;2.66705069124424;3.01267281105991;4.15322580645161];
y = [0.298833819241982;2.36880466472303;1.74198250728863;3.54956268221574;4.19096209912536];
% initial guess
a0 = [-1.5 1];
% least squares
fa = @(a) sum((y-f(x,a)).^2);
[a,val] = fminsearch(fa,a0);
% computing the z values for the plot
A1 = -2:0.1:5; A2 = -2:0.1:5;
NS = zeros(length(A1),length(A2));
for i = 1:length(A1)
for j = 1:length(A2)
NS(i,j) = fa([A1(i) A2(j)]);
end
end
% draw the "surface" of dots of values of the least squares function
plot3(A1,A2,NS,'bo');
xlabel('a_1'); ylabel('a_2'); zlabel('PNS'); axis tight; grid on
% mark the optimal point a
hold on; plot3(a(1),a(2),f(x,a),'k*');
The data is genreated with ginput. This is an exercise from an old course, I'm learning it independently as a preparation for my actual studies. Here an example of the kind of results I've had. The dots form pillars, instead of a surface. The third image demonstrates it even better.
Here is the example solution.
This is my attempt from above:

Accepted Answer

Star Strider
Star Strider on 15 Aug 2022
Edited: Star Strider on 15 Aug 2022
Use the surf or mesh functions to plot a surface matrix.
Try this —
f = @(x,a) a(1)*x+a(2);
x = [0.558755760368664;0.835253456221198;2.66705069124424;3.01267281105991;4.15322580645161];
y = [0.298833819241982;2.36880466472303;1.74198250728863;3.54956268221574;4.19096209912536];
% initial guess
a0 = [-1.5 1];
% least squares
fa = @(a) sum((y-f(x,a)).^2);
[a,val] = fminsearch(fa,a0);
% computing the z values for the plot
A1 = -2:0.1:5; A2 = -2:0.1:5;
NS = zeros(length(A1),length(A2));
for i = 1:length(A1)
for j = 1:length(A2)
NS(i,j) = fa([A1(i) A2(j)]);
end
end
% draw the "surface" of dots of values of the least squares function
figure
surf(A1,A2,NS, 'FaceAlpha', 0.5, 'EdgeColor','none');
xlabel('a_1'); ylabel('a_2'); zlabel('PNS'); axis tight; grid on
% mark the optimal point a
hold on; plot3(a(1),a(2),f(x,a),'k*');
[A1m,A2m] = meshgrid(A1,A2); % Easiest Way To Create Necessary Vectors
DotSize = 5;
figure
scatter3(A1m(:), A2m(:), NS(:), DotSize, NS(:), 'o', 'filled', 'MarkerFaceAlpha',0.5)
hold on
plot3(a(1),a(2),f(x,a),'k*');
hold off
grid on
colormap(turbo)
xlabel('a_1')
ylabel('a_2')
zlabel('NS')
title('Dot Surface')
view(20,30) % Camera Position
EDIT — (15 Aug 2022 at 14:34)
Added ‘Dot Surface’ plot.
.
  2 Comments
Star Strider
Star Strider on 15 Aug 2022
As always, my pleasure!
The arguments to the surface plot functions can have vectors describing the first two axes for the first two variables (so they only have to be vectors equal to the sizes of the matrix in those diemnsions and not matrices themselves), however plot3 and stem3 have to have arrays (vectors or matrices) with the same sizes for the first three arguments, and possibly the first five if the marker sizes and colours are defined for each marker.
(PNS is OLS in Finnish, that's the z-value in the plot)
Thank you for the explanation. I learned something that I was not expecting to learn!
.

Sign in to comment.

More Answers (1)

Walter Roberson
Walter Roberson on 15 Aug 2022
Your A1 and A2 are vectors the same length, but your NS is 2D. Effectively for each A1(J), A2(J) you draw a column NS(:,J), which is not what you wanted: you wanted combinations A1(J), A2(K), NS(J,K)
f = @(x,a) a(1)*x+a(2);
x = [0.558755760368664;0.835253456221198;2.66705069124424;3.01267281105991;4.15322580645161];
y = [0.298833819241982;2.36880466472303;1.74198250728863;3.54956268221574;4.19096209912536];
% initial guess
a0 = [-1.5 1];
% least squares
fa = @(a) sum((y-f(x,a)).^2);
[a,val] = fminsearch(fa,a0);
% computing the z values for the plot
A1 = -2:0.1:5; A2 = -2:0.1:5;
[A1G, A2G] = meshgrid(A1, A2);
NS = arrayfun(@(a1,a2) fa([a1,a2]), A1G, A2G);
surf(A1G, A2G, NS, 'edgecolor', 'none');
xlabel('a_1'); ylabel('a_2'); zlabel('PNS'); axis tight; grid on
% mark the optimal point a
hold on; plot3(a(1),a(2),f(x,a),'r*');

Products


Release

R2022a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!