Higher order polynomial fitting is not so handy surprisingly - matlab

I have a simple question but was not able to fix it by myself. I want to use the MATLAB curvefitting toolbox and fit higher order polynomials. It works if I want to fit polynomials of order 1 to 9. But, to my surprise it does not work for polynomials with degree higher than 9. To make it simple, can you just see the following simple code which does not work for me, unfortunately.
l=1:0.01:10;y=l.^10;
[xData, yData] = prepareCurveData(l,y);
ft = fittype( 'poly10' );
[Fit, gof] = fit( xData, yData, ft, 'Normalize', 'on' );
Thanks in advance,
Babak

It might be surprising, but it is documented: List of Library Models for Curve and Surface Fitting. You can always use polyfit, but as per the warning it issues, once you start getting polynomials of that degree, the fit is likely to be problematic anyway.

This answer is some supplement to the Phil Goddard's answer.
There is no poly10 in the function fit. But there are at least two alternative ways to fit any degree of the polynomial: something like polyX, where x could be 1,2,...,M, (if it is necessary).
clc; clear;
%%data
l=1:0.01:10;y=l.^10;
[xData, yData] = prepareCurveData(l,y);
%%High degree polynomial fitting
%set the degree of the polunomial
Degree=10;
%Fit with customize option
%generate the cell array from 'x^Degree' to 'x^0'
syms x
Str=char(power(x,Degree:-1:0));
%set the fitting type & options, then call fit
HighPoly = fittype(strsplit(Str(10:end-3),','));
options = fitoptions('Normalize', 'off','Method','LinearLeastSquares','Robust','off');
[curve,gof] = fit(xData,yData,HighPoly,options)
%Polyfit with the degree of Degree
p = polyfit(xData,yData,Degree)
But both fit and polyfit show some warnings, in my humble opinion, it is due to the Runge's phenomenon, which is a problem of oscillation at the edges of an interval that occurs when using polynomial interpolation with polynomials of high degree over a set of equispaced interpolation points.
Discard the data in this situation or some similar ones, where the true function is polynomial with high degree, says something in the Pn[R], high degree polynomial is not recommended in the fitting of the complex function.
Edit: generalized the code.

Related

Log-Log Graph, Curve Fit on Matlab

Im im trying to validate my engineering work using Matlab. I have a series of x and y data that I have plotted on a Log-Log Graph.
The result is a curve.
What I need to do is to apply a curve fit to this graph, and show what the equation of the fit is?
I have tried other answers on here and tried using polyfit and polyval but they aren't really doing what I need but what I lack is the forthwith understanding.
Kind regards
Apply polyfit to logx and logy instead of x and y, and then, to use the fitted result apply polyval to log(x) and use exp() on the result to get the actual fitted y:
logx = log(x);
logy = log(y);
fitp = polyfit(logx, logy, n);
newy = exp(polyval(fitp, log(newx)));
Fitting in the log-space may be undesirable. Most likely you want to show the equation that best fits the data, not a transformation of the data. As a result, I would fit the linear data, then transform it for visualization as necessary. If that's acceptable, polyfit and polyval should work.
If you believe fitting in the log-space is important, I've used lsqcurvefit before, but this requires both the optimization toolbox and some idea of which function you'd like to fit (i.e. is your data best represented by 10^x or x^2?). There's also the curve-fitting toolbox, which might be worth looking into if there are issues you could identify interactively with a GUI but not easily put into words. This provides a 'fit' function that could be useful too.

Remove base line drift with peicewise cubic spline algorithm using MATLAB

I have a signal which I want to remove the basline drift using the picewise cubic spline algorithm in MATLAB.
d=load(file, '-mat');
t=1:length(a);
xq1=1:0.01:length(a);
p = pchip(t,a,xq1);
s = spline(t,a,xq1);
%
figure, hold on, plot(a, 'g'), plot(t,a,'o',xq1,p,'-',xq1,s,'-.')
legend('Sample Points','pchip','spline','Location','SouthEast')
But I cant see any basline removal..The orginal data is exactly on the interpolated one.
or in the other signal as we can see no base line is removed.
The question is how I can "use peicewise cubic spline interpolation to
remove basline drift" in MATLAB.
Thank you
It seems likely that you are looking to fit a polynomial to your data to estimate baseline drift due to thermal variations. The problem with spline is that it will always perfectly fit your data (similar to pchip) because it is an interpolation technique. You probably want a courser fit which you can get using polyfit. The following code sample shows how you could use polyfit to estimate the drift. In this case I fit a 3rd-order polynomial.
% generate some fake data
t = 0:60;
trend = 0.003*t.^2;
x = trend + sin(0.1*2*pi*t) + randn(1,numel(t))*0.5;
% estimate trend using polyfit
p_est = polyfit(t,x,3);
trend_est = polyval(p_est,t);
% plot results
plot(t,x,t,trend,t,trend_est,t,x-trend_est);
legend('data','trend','estimated trend','trend removed','Location','NorthWest');
Update
If you have the curve fitting toolbox you can fit a cubic spline with an extra smoothing constraint. In the example above you could use
trend_est = fnval(csaps(t,x,0.01),t);
instead of polyfit and polyval. You will have to play with the smoothing parameter, 0 being completely linear and 1 giving the same results as spline.
I think you should reduce the number of points at which you calculate the spline fit (this avoids over-fitting) and successively interpolate the fit on the original x-data.
t = 0:60;
trend = 0.003*t.^2;
x = trend + sin(0.1*2*pi*t) + randn(1,numel(t))*0.5;
figure;hold on
plot(t,x,'.-')
%coarser x-data
t2=[1:10:max(t) t(end)]; %%quick and dirty. You probably wanna do better than this
%spline fit here
p = pchip(t,x,t2);
s = spline(t,x,t2);
plot(t2,s,'-.','color' ,'g')
%interpolate back
trend=interp1(t2,s,t);
%remove the trend
plot(t,x-trend,'-.','color' ,'c')

How to scale data before fitting in matlab 2016b

I use the fit() function of matlab 2016b to fit a complicate exponential function to data x,y.
The x values are very small (1e-3) and the y values are in the order of 1.
The fitting works well, if I multiply x by a constant factor 1000 to 100000.
This effect is described in the mathworks online help in section "Using Normalize or Center and Scale".
The Normalize: 'on' setting fails here (1) even with very narrow upper and lower limits.
Is the Normalize option transparent for the user, or will I have to change my boundaries after enabling it?
For now I help my self by multiplying x and correct the coefficients in the fit results afterwards.
ScalingFactor = 1000;
[xData, yData] = prepareCurveData( myx * ScalingFactor, myy );
ft = fittype(..)
[fitresult, gof] = fit( xData, yData, ft, opts );
%% now correct the results
This does not look very elegant to me for a quite expensive software.
4 years ago there was a similar question on sx without a handy solution.
Is there a better solution today?
1) Perhaps the error message helps other users to find this question/answer some day, so I paste it here:
Error using fit>iFit (line 340)
Complex value computed by model function, fitting cannot continue.
Try using or tightening upper and lower bounds on coefficients.
You might consider placing the scaling factor inside the function itself as a fitted parameter. For example, instead of:
scaledX = x * 1000
y = f(scaledX)
you would instead directly fit to:
y = f(scalingFactor * x)
so that the fitting (hopefully) finds the optimum scaling factor for you.

MATLAB curve fitting - least squares method - wrong "fit" using high degrees

Anyone here that could help me with the following problem?
The following code calculates the best polynomial fit to a given data-set, that is; a polynomial of a specified degree.
Unfortunately, whatever the data-set may be, usually at degree 6 or higher, MATLAB gets a totally wrong fit. Usually the fit curves totally away from the data in a sort of exponantial-looking-manner downwards. (see the example: degree = 8).
x=[1.0 1.5 2.0 2.5 3.0 3.5 4.0 4.5] % experimental x-values
y=[4.3 6.2 10.1 13.5 19.8 22.6 24.7 29.2] % experimental y-values
degree=8; % specify the degree
A = zeros(length(x),degree);
for exponent=0:degree;
for data=1:length(x);
A(data,exponent+1)=x(data).^exponent; % create matrix A
end;
end;
a=inv((transpose(A)*A))*transpose(A)*y'; % a are the coƫfficients of the polynom
a=flipud(a);
fitpolynoom=polyval(a,x);
error=sum((y-fitpolynoom).^2); % calculates the fit-error using the least-squares method
fitpolynoom=polyval(a,x);
figure;
plot(x,y,'black*',x,fitpolynoom,'g-');
error % displays the value of the fit-error in the Matlab command window
Thanks in advance.
First, some remarks: for least-squares fitting polynomials in Matlab, you could use the existingpolyfit function instead. Furthermore (this may depend on your application) you probably should not be fitting $8$th degree polynomials, especially when you have $8$ data points. In this answer, I assume you have good reasons to fit polynomials to your data (e.g., just for self-study purposes).
The issue is a numeric problem arising from matrix inversion. For solving equations of type $Ax=b$ where $A$ is a square matrix, actually inverting $A$ is not recommended (See Blogpost 'Don't invert that matrix' by John D. Cook). In the least-squares case, instead of
\begin{equation}
a = (A^\mathrm{T} A)^{-1} A^\mathrm{T} y^\mathrm{T}
\end{equation}
it is better to solve
\begin{equation}
(A^\mathrm{T} A)a = A^\mathrm{T} y^\mathrm{T}
\end{equation}
by other means. In your MATLAB code, you may replace
a=inv((transpose(A)*A))*transpose(A)*y';
by
a = (transpose(A) * A) \ (transpose(A) * y');
By this modification to your code, I obtained a fit going through the data points.

how to find the line of best fit for precision recall curves in matlab

I have calculated points for a recall-precision curve by varying a threshold and calculating recall and precision. I have plotted these points in a scatter graph as follows:
scatter(recall', precision')
I am trying to find the curve of best fit, but am not sure of the best way. I have tried this:
p = polyfit(recall', precision', 5)
r = polyval(p, recall')
plot(recall', precision', 'x');
hold on
plot(recall', r, '-');
hold off
But the problem with this is I have to estimate the degree of the polynomial (in this case 5).
you can try the program Eureqa Formulize. Its a free and easy to use tool for symbolic regression developed at Cornell Creative Machines Lab.
Regards,
Ben
You can try to take the logarithm of recall and precision variables and fit a line through them. The slope then should give a rough idea about the degree of the polynomial you might want to use, i.e.
p2 = polyfit(log(recall), log(precision), 1)