This question already has an answer here:
MATLAB curve fitting - least squares method - wrong "fit" using high degrees
(1 answer)
Closed 3 years ago.
Hello my question is about curve tiffing of P3(x) I write my code with using polyfit and polyval functions but I need to make it without using these functions.
this is my code that I wrote
n=input('Enter a value: ');
if(n<3)
fprintf('Enter a different value larger than 3')
end
if(n>=3)
x = 1:n;
y = -0.3*x + 2*randn(1,n);
[p,S] = polyfit(x,y,3);
[y_fit,delta] = polyval(p,x,S);
plot(x,y,'bo')
hold on
plot(x,y_fit,'r-')
title('Linear-Fit Output')
legend('Data','Linear Fit')
end
this is code that I write it is working but I am suppose to write it without using polfite and polyval functions
Without Using syms
y = a0*x^0 + a1*x^1 + a2*x^2 + a3*x^3
For n data point --> y = X*a
where
X = [x1^0 , a1*x1^1, a2*x1^2 , a3*x1^3; x2^0 , a1*x2^1, a2*x2^2 , a3*x2^3;...;xn^0 , a1*xn^1 , a2*xn^2 , a3*xn^3 ]
and a = [a0, a1, a2, a3]; y = [y1, y2, ..., yn]
a is computed as follow
y = X*a ---> a = X\y
The code is as follows
n is given
x = 1:n;
y = -0.3*x + 2*randn(1,n);
x0 = ones(n, 1);
x1 = x';
x2 = (x.^2)';
x3 = (x.^3)';
X = [x0 x1 x2 x3];
a = X\(y');
f =#(t)a(1) + a(2).*t + a(3).*(t.^2)+ a(4).*(t.^3);
Use least square method to find best fit cubic polynomial
n=input('Enter a value: ');
if(n<3)
fprintf('Enter a different value larger than 3')
else
x = 1:n;
y = -0.3*x + 2*randn(1,n);
% Cubic regression
syms a0 a1 a2 a3
yq = a0 + a1.*x + a2.*(x.^2) + a3.*(x.^3) ;
rq = yq - y;
f = sum(rq.^2);
fa0 = diff(f,a0);
fa1 = diff(f,a1);
fa2 = diff(f,a2);
fa3 = diff(f,a3);
sol = solve(fa0 == 0, fa1 == 0, fa2 == 0, a0, a1, a2, a3);
a0 = sol.a0;
a1 = sol.a1;
a2 = sol.a2;
a3 = sol.a3;
% Cubic Regression Curve Function
f =#(t)a0 + a1.*t + a2.*(t.^2)+ a3.*(t.^3);
% Plot Data and Cubic Regression Curve
h = figure(1);
% Data
plot3 = scatter(x, y, 100, '+', 'MarkerEdgeColor', 'red', 'linewidth', 5);
hold on
% cubic Regression Curve
xx = linspace(0,n,100);
plot4 = plot(xx, f(xx), 'linewidth', 5);
[~,b] = legend([plot3 plot4],{'Real Data','Cubic Regression'}, 'FontSize',30);
set(findobj(b,'-property','MarkerSize'),'MarkerSize',30);
xlabel('x-axis','color', 'k', 'fontSize', 25)
ylabel('y-axis', 'color','k', 'fontSize', 25)
hYLabel = get(gca,'YLabel');
set(hYLabel,'rotation',0,'VerticalAlignment','middle', 'HorizontalAlignment','right')
grid on
grid minor
set(gca,'FontSize',20)
set(get(h,'CurrentAxes'),'GridAlpha',0.8,'MinorGridAlpha',0.5);
xticks(x);
title('Cubic Regression', 'color', 'r');
whitebg('w');
end
n = 5
n = 20
Related
So I have a script which executes coordinate descent algorithm for a quadratic function. I also created a function to make different plots, this is the first part I add. The code executes without any error, but I'm unable to see the surface, I can only see the path of my algorithm descending.
The function updater:
function [f,delta] = fcalculator (Q, x0, c, p)
a = size(x0);
n = a(2);
f = (x0*Q*x0') - (c * x0') + p ;
delta = (Q*x0')- c';
endfunction
The main program:
clear all, close all,
fprintf(' 0 = probleme specifique \n 1 = probleme random \n 2 = Tapez votre propre probleme\n')
choix = input ('Choix : ');
n=0;
if (choix == 0)
[Q, x0, c, p] = quadfunctiongenerator(n,choix)
maxiter = input ( 'Nombre de iterations :');
[x, z] = coordinatedescent(Q,c,p,x0,maxiter);
visualizer(x, z, Q, c, p);
else
n = input ('Choix des dimensions: n = ');
[Q, x0, c, p] = quadfunctiongenerator(n,choix);
endif
The module to create the plots:
function [x1, x2, fuf] = visualizer(x, z, Q, c, p)
clf;
% Pour le cas le plus general, apres on fera:
% iters = 1:size(x)(1);
% plot(iters,x(:,1))
if size(x)(2)
% Afficher les iterees:
plot3(x(:,1), x(:,2), z)
hold on;
% fcalculator (Q, x0, c, p)
% Display the function's surface:
%% Calculate limits:
x1_low = x(1,1);
x1_hi = x(size(x)(1),1) + x1_low;
x2_low = x(1,2);
x2_hi = x(size(x)(1),2) + x2_low;
% Resolution will be the number of points:
resolution = 100;
x1 = (linspace(x1_low, x1_hi, resolution))';
x2 = (linspace(x2_low, x2_hi, resolution))';
f = [];
[xx, yy] = meshgrid (x1, x2);
for i=1:resolution
for j=1:resolution
[_tmp, _] = fcalculator(Q, [x1(i),x2(j)], c, p);
f(i,j) = _tmp;
endfor
endfor
_string = sprintf('%d ', size(x1));
fprintf('Answer: %s\n', _string);
_string = sprintf('%d ', size(x2));
fprintf('Answer: %s\n', _string);
_string = sprintf('%d ', size(f));
fprintf('Answer: %s\n', _string);
mesh(x1, x2, f);
endif
endfunction
I believe the problem is my call to mesh() as I didn't use the variables xx and yy created when calling meshgrid() but the dimensions of x1, x2 and f are the same as those of the variables used to create the famous sombrero plot:
tx = ty = linspace (-8, 8, 41)';
[xx, yy] = meshgrid (tx, ty);
r = sqrt (xx .^ 2 + yy .^ 2) + eps;
tz = sin (r) ./ r;
mesh (tx, ty, tz);
Am I supposed to create f as an elementwise operation as shown in the sombrero plot example?
Is there any octave function to help me create the surface of the function I am optimizing?
I found the problem. The call to mesh() was correct. The problem was the definition of the boundaries.
x1_low = x(1,1);
x1_hi = x(size(x)(1),1) + x1_low;
x2_low = x(1,2);
x2_hi = x(size(x)(1),2) + x2_low;
Yielded x1_low == x1_hi. The code was replaced with:
x1_low = min(x(:,1));
x1_hi = max(x(:,1));
x2_low = min(x(:,2));
x2_hi = max(x(:,2));
Which yielded the desired surface.
I have three vectors x,y,t. For each combination x,y,t there is a (u,v) value associated with it. How to plot this in matlab? Actually I'm trying to plot the solution of 2d hyperbolic equation
vt = A1vx + A2vy where A1 and A2 are 2*2 matrices and v is a 2*1 vector. I was trying scatter3 and quiver3 but being new to matlab I'm not able to represent the solution correctly.
In the below code I have plot at only a particular time-level. How to show the complete solution in just one plot? Any help?
A1 = [5/3 2/3; 1/3 4/3];
A2 = [-1 -2; -1 0];
M = 10;
N = 40;
delta_x = 1/M;
delta_y = delta_x;
delta_t = 1/N;
x_points = 0:delta_x:1;
y_points = 0:delta_y:1;
t_points = 0:delta_t:1;
u = zeros(M+1,M+1,N+1,2);
for i=1:M+1,
for j=1:M+1,
u(i,j,1,1) = (sin(pi*x_points(i)))*sin(2*pi*y_points(j)) ;
u(i,j,1,2) = cos(2*pi*x_points(i));
end
end
for j=1:M+1,
for t=1:N+1,
u(M+1,j,t,1) = sin(2*t);
u(M+1,j,t,2) = cos(2*t);
end
end
for i=1:M+1
for t=1:N+1
u(i,1,t,1) = sin(2*t);
u(i,M+1,t,2) = sin(5*t) ;
end
end
Rx = delta_t/delta_x;
Ry = delta_t/delta_y;
for t=2:N+1
v = zeros(M+1,M+1,2);
for i=2:M,
for j=2:M,
A = [(u(i+1,j,t-1,1) - u(i-1,j,t-1,1)) ; (u(i+1,j,t-1,2) - u(i-1,j,t-1,2))];
B = [(u(i+1,j,t-1,1) -2*u(i,j,t-1,1) +u(i-1,j,t-1,1)) ; (u(i+1,j,t-1,2) -2*u(i,j,t-1,2) +u(i-1,j,t-1,2))];
C = [u(i,j,t-1,1) ; u(i,j,t-1,2)];
v(i,j,:) = C + Rx*A1*A/2 + Rx*Rx*A1*A1*B/2;
end
end
for i=2:M,
for j=2:M,
A = [(v(i,j+1,1) - v(i,j-1,1)) ; (v(i,j+1,2) - v(i,j-1,2)) ];
B = [(v(i,j+1,1) - 2*v(i,j,1) +v(i,j-1,1)) ; (v(i,j+1,2) - 2*v(i,j,2) +v(i,j-1,2))];
C = [v(i,j,1) ; v(i,j,2)];
u(i,j,t,:) = C + Ry*A2*A/2 + Ry*Ry*A2*A2*B/2;
end
end
if j==2
u(i,1,t,2) = u(i,2,t,2);
end
if j==M
u(i,M+1,t,1) = u(i,M,t,1);
end
if i==2
u(1,j,t,:) = u(2,j,t,:) ;
end
end
time_level = 2;
quiver(x_points, y_points, u(:,:,time_level,1), u(:,:,time_level,2))
You can plot it in 3D, but personally I think it would be hard to make sense of.
There's a quiver3 equivalent for your plotting function. z-axis in this case would be time (say, equally spaced), and z components of the vectors would be zero. Unlike 2D version of this function, it does not support passing in coordinate vectors, so you need to create the grid explicitly using meshgrid:
sz = size(u);
[X, Y, Z] = meshgrid(x_points, y_points, 1:sz(3));
quiver3(X, Y, Z, u(:,:,:,1), u(:,:,:,2), zeros(sz(1:3)));
You may also color each timescale differently by plotting them one at a time, but it's still hard to make sense of the results:
figure(); hold('all');
for z = 1:sz(3)
[X, Y, Z] = meshgrid(x_points, y_points, z);
quiver3(X, Y, Z, u(:,:,z,1), u(:,:,z,2), zeros([sz(1:2),1]));
end
I have two binary circles of one object.They don't connect together. I finished fill color for a circle. Now, I want to fill same color into two circles that don't connect together. This is my code. But it does work. Could you edit help me please?
figure
[xx yy] = meshgrid(1:384,1:384);
phi1 = (sqrt(((xx - 190).^2 + (yy - 260).^2 )) - 15);
phi2 = (sqrt(((xx - 270).^2 + (yy - 200).^2 )) - 20);
phi= sign(phi1).*sign(phi2);
phi(phi==-1)=0;
imshow(phi);
cont = contourc(phi, [0 0])';
cont = cont(2 : end, :);
patch(cont(:, 1), cont(:, 2), 'g', 'EdgeColor', 'w')
Here is a little script to draw a filled circle. You can make it into a function and use hold on and hold off to draw many circles.
r = 2;
xc = 1;
yc = 1;
st = r/100;
x1 = (-r+xc):st:(r+xc);
y1 = yc+sqrt(r^2-(x1-xc).^2);
x2 = x1(end:-1:1);
y2 = yc-sqrt(r^2-(x2-xc).^2);
x = [x1 x2];
y = [y1 y2];
patch(x,y,'g','FaceColor', 'g');
If you want to create a more general shape using implicit definition of the curve, the following works too:
[xx, yy] = meshgrid(1:384,1:384);
phi1 = 15^2 < ((xx-190).^2 + (yy-260).^2);
phi2 = 20^2 < ((xx-270).^2 + (yy-200).^2);
phi = phi1 .* phi2;
contourf(phi, [0,1]);
colormap([0,1,0;1,1,1]);
Got one more problem with matrix multiplication in Matlab. I have to plot Taylor polynomials for the given function. This question is similar to my previous one (but this time, the function is f: R^2 -> R^3) and I can't figure out how to make the matrices in order to make it work...
function example
clf;
M = 40;
N = 20;
% domain of f(x)
x1 = linspace(0,2*pi,M).'*ones(1,N);
x2 = ones(M,1)*linspace(0,2*pi,N);
[y1,y2,y3] = F(x1,x2);
mesh(y1,y2,y3,...
'facecolor','w',...
'edgecolor','k');
axis equal;
axis vis3d;
axis manual;
hold on
% point for our Taylor polynom
xx1 = 3;
xx2 = 0.5;
[yy1,yy2,yy3] = F(xx1,xx2);
% plots one discrete point
plot3(yy1,yy2,yy3,'ro');
[y1,y2,y3] = T1(xx1,xx2,x1,x2);
mesh(y1,y2,y3,...
'facecolor','w',...
'edgecolor','g');
% given function
function [y1,y2,y3] = F(x1,x2)
% constants
R=2; r=1;
y1 = (R+r*cos(x2)).*cos(x1);
y2 = (R+r*cos(x2)).*sin(x1);
y3 = r*sin(x2);
function [y1,y2,y3] = T1(xx1,xx2,x1,x2)
dy = [
-(R + r*cos(xx2))*sin(xx1) -r*cos(xx1)*sin(xx2)
(R + r*cos(xx2))*cos(xx1) -r*sin(xx1)*sin(xx2)
0 r*cos(xx2) ];
y = F(xx1, xx2) + dy.*[x1-xx1; x2-xx2];
function [y1,y2,y3] = T2(xx1,xx2,x1,x2)
% ?
I know that my code is full of mistakes (I just need to fix my T1 function). dy represents Jacobian matrix (total derivation of f(x) - I hope I got it right...). I am not sure how would the Hessian matrix in T2 look, by I hope I will figure it out, I'm just lost in Matlab...
edit: I tried to improve my formatting - here's my Jacobian matrix
[-(R + r*cos(xx2))*sin(xx1), -r*cos(xx1)*sin(xx2)...
(R + r*cos(xx2))*cos(xx1), -r*sin(xx1)*sin(xx2)...
0, r*cos(xx2)];
function [y1,y2,y3]=T1(xx1,xx2,x1,x2)
R=2; r=1;
%derivatives
y1dx1 = -(R + r * cos(xx2)) * sin(xx1);
y1dx2 = -r * cos(xx1) * sin(xx2);
y2dx1 = (R + r * cos(xx2)) * cos(xx1);
y2dx2 = -r * sin(xx1) * sin(xx2);
y3dx1 = 0;
y3dx2 = r * cos(xx2);
%T1
[f1, f2, f3] = F(xx1, xx2);
y1 = f1 + y1dx1*(x1-xx1) + y1dx2*(x2-xx2);
y2 = f2 + y2dx1*(x1-xx1) + y2dx2*(x2-xx2);
y3 = f3 + y3dx1*(x1-xx1) + y3dx2*(x2-xx2);
I am trying to implement least squares circle fitting following this paper (sorry I can't publish it). The paper states, that we could fit a circle, by calculating the geometric error as the euclidean distance (Xi'') between a specific point (Xi) and the corresponding point on the circle (Xi'). We have three parametres: Xc (a vector of coordinates the center of circle), and R (radius).
I came up with the following MATLAB code (note that I am trying to fit circles, not spheres as it is indicated on the images):
function [ circle ] = fit_circle( X )
% Kör paraméterstruktúra inicializálása
% R - kör sugara
% Xc - kör középpontja
circle.R = NaN;
circle.Xc = [ NaN; NaN ];
% Kezdeti illesztés
% A köz középpontja legyen a súlypont
% A sugara legyen az átlagos négyzetes távolság a középponttól
circle.Xc = mean( X );
d = bsxfun(#minus, X, circle.Xc);
circle.R = mean(bsxfun(#hypot, d(:,1), d(:,2)));
circle.Xc = circle.Xc(1:2)+random('norm', 0, 1, size(circle.Xc));
% Optimalizáció
options = optimset('Jacobian', 'on');
out = lsqnonlin(#ort_error, [circle.Xc(1), circle.Xc(2), circle.R], [], [], options, X);
end
%% Cost function
function [ error, J ] = ort_error( P, X )
%% Calculate error
R = P(3);
a = P(1);
b = P(2);
d = bsxfun(#minus, X, P(1:2)); % X - Xc
n = bsxfun(#hypot, d(:,1), d(:,2)); % || X - Xc ||
res = d - R * bsxfun(#times,d,1./n);
error = zeros(2*size(X,1), 1);
error(1:2:2*size(X,1)) = res(:,1);
error(2:2:2*size(X,1)) = res(:,2);
%% Jacobian
xdR = d(:,1)./n;
ydR = d(:,2)./n;
xdx = bsxfun(#plus,-R./n+(d(:,1).^2*R)./n.^3,1);
ydy = bsxfun(#plus,-R./n+(d(:,2).^2*R)./n.^3,1);
xdy = (d(:,1).*d(:,2)*R)./n.^3;
ydx = xdy;
J = zeros(2*size(X,1), 3);
J(1:2:2*size(X,1),:) = [ xdR, xdx, xdy ];
J(2:2:2*size(X,1),:) = [ ydR, ydx, ydy ];
end
The fitting however is not too good: if I start with the good parameter vector the algorithm terminates at the first step (so there is a local minima where it should be), but if I perturb the starting point (with a noiseless circle) the fitting stops with very large errors. I am sure that I've overlooked something in my implementation.
For what it's worth, I implemented these methods in MATLAB a while ago. However, I did it apparently before I knew about lsqnonlin etc, as it uses a hand-implemented regression. This is probably slow, but may help to compare with your code.
function [x, y, r, sq_error] = circFit ( P )
%# CIRCFIT fits a circle to a set of points using least sqaures
%# P is a 2 x n matrix of points to be fitted
per_error = 0.1/100; % i.e. 0.1%
%# initial estimates
X = mean(P, 2)';
r = sqrt(mean(sum((repmat(X', [1, length(P)]) - P).^2)));
v_cen2points = zeros(size(P));
niter = 0;
%# looping until convergence
while niter < 1 || per_diff > per_error
%# vector from centre to each point
v_cen2points(1, :) = P(1, :) - X(1);
v_cen2points(2, :) = P(2, :) - X(2);
%# distacnes from centre to each point
centre2points = sqrt(sum(v_cen2points.^2));
%# distances from edge of circle to each point
d = centre2points - r;
%# computing 3x3 jacobean matrix J, and solvign matrix eqn.
R = (v_cen2points ./ [centre2points; centre2points])';
J = [ -ones(length(R), 1), -R ];
D_rXY = -J\d';
%# updating centre and radius
r_old = r; X_old = X;
r = r + D_rXY(1);
X = X + D_rXY(2:3)';
%# calculating maximum percentage change in values
per_diff = max(abs( [(r_old - r) / r, (X_old - X) ./ X ])) * 100;
%# prevent endless looping
niter = niter + 1;
if niter > 1000
error('Convergence not met in 1000 iterations!')
end
end
x = X(1);
y = X(2);
sq_error = sum(d.^2);
This is then run with:
X = [1 2 5 7 9 3];
Y = [7 6 8 7 5 7];
[x_centre, y_centre, r] = circFit( [X; Y] )
And plotted with:
[X, Y] = cylinder(r, 100);
scatter(X, Y, 60, '+r'); axis equal
hold on
plot(X(1, :) + x_centre, Y(1, :) + y_centre, '-b', 'LineWidth', 1);
Giving: