Project

Curve Fitting

The objective of curve fitting is to find the parameters of a mathematical model that describes a set of (usually noisy) data in a way that minimizes the difference between the model and the data. The most common approach is the "linear least squares" method, also called "polynomial least squares", a well-known mathematical procedure for finding the coefficients of polynomial equations that are a "best fit" to a set of X, Y data. A polynomial equation expresses the dependent variable Y as a polynomial in the independent variable X, for example as a straight line (Y = a + bX, where a is the intercept and b is the slope), or a quadratic (Y = a + bX + cX2), or a cubic (Y = a + bX + cX2 + dX3), or higher-order polynomial. Those coefficients (a, b, c, etc) can be used to predict values of Y for each X. In all these cases, Y is a linear function of the parameters a, b, c, and/or d. This is why we call it a "linear" least-squares fit, not because the plot of X vs Y is linear. Only for the first-order polynomial is the plot of X vs Y linear. To find these coefficients of the polynomial equation (a, b, c, etc) in MATLAB we use function “polyfit”.

polyfit:

p = polyfit(x,y,n) ......(Syntax)

returns the coefficients for a polynomial p(x) of degree n that is a best fit (in a least-squares sense) for the data in y. The coefficients in p are in descending powers, and the length of p is n+1

p(x)=p1xn+p2xn−1+...+pnx + pn+1

[p,S] = polyfit(x,y,n) ……. (Syntax)

also returns a structure S that can be used as an input to polyval to obtain error estimates.

[p,S,mu] = polyfit(x,y,n) ……. (Syntax)

also returns mu, which is a two-element vector with centering and scaling values. mu(1) is mean(x), and mu(2) is std(x). Using these values, polyfit centers x at zero and scales it to have unit standard deviation,

.

This centering and scaling transformation improves the numerical properties of both the polynomial and the fitting algorithm.

How to make a curve fit perfectly?

In general, fitting any set of data with a higher order polynomial, like a quadratic, cubic or higher, will reduce the fitting error because a higher order model has more variable coefficients to adjust to the data. The danger is that you could be "fitting the noise", that is, adjusting to the random noise in that particular data set, whereas another measurement with different random noise might give markedly different results. To make a perfect fit we need the error between the original data and the curve fit to be zero.

How to find error estimates?

As we have seen in the polyfit function we get an output structure S which can be used to get error estimates when it is used as an input in the polyval function.

Polyval function evaluates the polynomial equation using coefficients found through the polyfit function and the independent variable X to give a predicted value of Y. In the polyval function we can also determine the error estimates by adding another input in the function which is structure S found through the polyfit function. This error, let’s call it delta, is an array of values which are the difference between the original Y values and predicted Y values

polyval:

y = polyval(p,x) ......(Syntax)

Here y is the predicted value found using the polynomial coefficients (p) and independent variable x as input.

[y,delta] = polyval(p,x,S) ......(Syntax)

This uses the optional output structure S produced by the polyfit function to generate error estimates. “delta” is an estimate of the standard error in predicting a future observation at x by p(x).

How to get the best fit?

The curve that gives minimum error between original data curve and fit curve is the best fit. Best fit” simply means that the differences between the actual measured Y values and the Y values predicted by the model equation are minimized. It does not mean a "perfect" fit; in most cases, a least-squares best fit does not go through all the points in the data set. Above all, a least-squares fit must conform to the selected model - for example, a straight line or a quadratic parabola - and there will almost always be some data points that do not fall exactly on the best-fit line, either because of random error in the data or because the model is not capable of describing the data exactly. It's not correct to say "fit data to ..." a straight line or to some other model; it's actually the other way around: you are fitting a model to the data. The data are not being modified in any way; it is the model that is being adjusted to fit the data.

Variables used in the code:

cp_data: holds the data loaded from the “data.txt” file

temperature: holds the temperature data from 1st column of “data.txt” file

temp1: holds the temperature data from 1st column of “data.txt” file for split 1

temp2: holds the temperature data from 1st column of “data.txt” file for split 2

temp3: holds the temperature data from 1st column of “data.txt” file for split 3

temp4: holds the temperature data from 1st column of “data.txt” file for split 4

cp: holds the specific heat data from 2nd column of “data.txt” file

cp1: holds the specific heat data from 2nd column of “data.txt” file for split 1

cp2: holds the specific heat data from 2nd column of “data.txt” file for split 2

cp3: holds the specific heat data from 2nd column of “data.txt” file for split 3

cp4: holds the specific heat data from 2nd column of “data.txt” file for split 4

co: coefficients of polynomial

co_1: coefficients of polynomial 1 (split 1)

co_3: coefficients of polynomial 2 (split 2)

co_3: coefficients of polynomial 3 (split 3)

co_4: coefficients of polynomial 4 (split 4)

S: structure output from polyfit

S1: structure output from polyfit for polynomial 1 (split1)

S2: structure output from polyfit for polynomial 2 (split2)

S3: structure output from polyfit for polynomial 3 (split3)

S4: structure output from polyfit for polynomial 4 (split4)

predicted_cp: output y which is predicted by the polyval function

predicted_cp_1: output y which is predicted by the polyval function for polynomial 1(split1)

predicted_cp_2: output y which is predicted by the polyval function for polynomial 2(split2)

predicted_cp_3: output y which is predicted by the polyval function for polynomial 3(split3)

predicted_cp_4: output y which is predicted by the polyval function for polynomial 4(split4)

delta: error estimates

delta1: error estimates for polynomial 1(split1)

delta2: error estimates for polynomial 2(split2)

delta3: error estimates for polynomial 3(split3)

delta4: error estimates for polynomial 4(split4)

mu: two-element vector with centering and scaling values

mu1: two-element vector with centering and scaling values for polynomial 1(split1)

mu2: two-element vector with centering and scaling values for polynomial 2(split2)

mu3: two-element vector with centering and scaling values for polynomial 3(split3)

mu4: two-element vector with centering and scaling values for polynomial 4(split4)

Code for Curve fit using linear equation (eg: Y = a + bX):

clear all
close all
clc
 
%Preparing the Data
cp_data = load('data.txt'); %Loading and storing data file
temperature = cp_data(:,1); %Loading and storing a column from data file(Temperature K)
cp = cp_data(:,2);%Loading and storing a column from data file(Specific Heat KJ/Kmole-K)
 
%Finding Coefficients for the polynomial
[co,S] = polyfit(temperature,cp,1); %Finding coefficients and optional structure output S of polynomial (1- degree of polynomial)
 
%Curve Fit
[predicted_cp,delta] = polyval(co,temperature,S); %Finding predicted value and error estimates using polynomial coefficients found in polyfit function
 
%Comparing Curve Fit with Orgignal Data
plot(temperature,cp,'linewidth',3,'color','b') %Plotting original data curve
hold on
plot(temperature,predicted_cp,'linewidth',3,'color','r') %Plotting curve fit using predicted data
xlabel('Temperature [K]')
ylabel('Specific Heat [KJ/Kmole-K]')
legend('Original Dataset','Curve Fit')

OUTPUT:

Code for Curve fit using cubic equation (eg: Y = a + bX + cX2 + dX3):

clear all
close all
clc
 
%Preparing the Data
cp_data = load('data.txt'); %Loading and storing data file
temperature = cp_data(:,1); %Loading and storing a column from data file(Temperature K)
cp = cp_data(:,2); );%Loading and storing a column from data file(Specific Heat KJ/Kmole-K)
 
%Finding Coefficients for the polynomial
[co,S,mu] = polyfit(temperature,cp,3); %Finding coefficients, optional structure output S and mu of polynomial (3- degree of polynomial)
 
%Curve Fit
[predicted_cp,delta] = polyval(co,temperature,S,mu); %Finding predicted value and error estimates using polynomial coefficients found in polyfit function
 
%Comparing Curve Fit with Orgignal Data
plot(temperature,cp,'linewidth',3,'color','b') %Plotting original data curve
hold on
plot(temperature,predicted_cp,'linewidth',3,'color','r') %Plotting curve fit using predicted data
xlabel('Temperature [K]')
ylabel('Specific Heat [KJ/Kmole-K]')
legend('Original Dataset','Curve Fit')

OUTPUT:

Cubic Curve fit:

As you can see the predicted curve does not coincide with the original curve at all point, meaning there is error between the two. We can see the error estimates by opening the delta variable through the workspace window.

Error Estimate for a cubic fit:

To reduce the error estimates, we can increase the order of polynomial. For e.g.:

Quartic Curve fit:

Error Estimate for a quartic fit:

As you can see the error estimates have reduced significantly with increasing order of polynomial giving a fit which is close than the original curve. Though this might seem a good fit it might not necessarily be one. Increasing order of polynomials also increases the number of coefficients which allows the curve to have more freedom and can bend easily giving us a closer to original curve, but the data we have can always have some noise in it, this causes an issue with the predicted curve since with higher order polynomial the noisy data point will have higher influence on the curve. And we don’t want this. So, it is best to have a curve fit which best defines the data even if it is not the perfect fit. To understand which order of polynomial best defines the data you need to have some observational skill and knowledge about the source of data.

What could be done to improve the cubic fit?

In the cubic fit graph, we can see that the original curve and the predicted curve have high error estimates. To improve the cubic fit, we need to reduce the error estimates without the increase in order of polynomial which will cause error in future predictions. Hence, we use the split method, here we split the original data into smaller clusters of data and solve the polynomial equations for each cluster separately.

Let’s look at the original data curve:

From the above graph we can see that there are 4 different ranges of x where y behaves differently. These four splits are:

Split 1: 1 - 460 K

Split 2: 461 - 1100 K

Split 3: 1101 - 2200 K

Split 4: 2201 - 3200 K

Now let’s try using this split method to fit curve:

Code for Cubic Curve fit using split method:

clear all
close all
clc
 
%Preparing the Data
cp_data = load('data.txt');
temperature = cp_data(:,1);
cp = cp_data(:,2);
 
%Splitting data
temp1 = cp_data(1:460,1);
cp1 = cp_data(1:460,2);
 
temp2 = cp_data(461:1100,1);
cp2 = cp_data(461:1100,2);
 
temp3 = cp_data(1101:2200,1);
cp3 = cp_data(1101:2200,2);
 
temp4 = cp_data(2201:3200,1);
cp4 = cp_data(2201:3200,2);
 
%Finding couefficients for the polynomials
[co_1,S1,mu1] = polyfit(temp1,cp1,3);
[co_2,S2,mu2] = polyfit(temp2,cp2,3);
[co_3,S3,mu3] = polyfit(temp3,cp3,3);
[co_4,S4,mu4] = polyfit(temp4,cp4,3);
 
%Curve Fit
[predicted_cp_1,delta1] = polyval(co_1,temp1,S1,mu1);
[predicted_cp_2,delta2] = polyval(co_2,temp2,S2,mu2);
[predicted_cp_3,delta3] = polyval(co_3,temp3,S3,mu3);
[predicted_cp_4,delta4] = polyval(co_4,temp4,S4,mu4);
 
%Comparing Curve Fit with Orgignal Data
plot(temperature,cp,'linewidth',3,'color','b')
hold on
plot(temp1,predicted_cp_1,'linewidth',2,'color','r')
hold on
plot(temp2,predicted_cp_2,'linewidth',2,'color','r')
hold on
plot(temp3,predicted_cp_3,'linewidth',2,'color','r')
hold on
plot(temp4,predicted_cp_4,'linewidth',2,'color','r')
xlabel('Temperature [K]')
ylabel('Specific Heat [KJ/Kmole-K]')
legend('Original Dataset','Curve Fit')

OUTPUT:

Error Estimate for a cubic fit (split method):

If you compare these error estimates from previous cubic curve fit (without split method used) we can see there is significant drop in the error estimates. This proves that using split method we can improve cubic fit without increasing the order of polynomial equation.

References:

https://www.mathworks.com/help/matlab/ref/polyfit.html

https://www.mathworks.com/help/matlab/ref/polyval.html

https://en.wikipedia.org/wiki/Curve_fitting

http://web.iitd.ac.in/~pmvs/courses/mel705/curvefitting.pdf

https://terpconnect.umd.edu/~toh/models/CurveFitting.html

Your portfolio, next

Ship work like this
in your own course.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.

Talk to a career counsellor

Free 20-minute call. We'll map the right course to where you want to work.

By submitting you agree to our Terms and Privacy Policy.