Study of the Curve fitting using Python
AIM:-
To perform curve fitting using Linear fitting and Cubic fitting from a given dataset. And find the best fit and perfect fit.
OBJECTIVE:-
- Write code to fit a linear and cubic polynomial for the Cp data.
- Plot the linear and cubic fit curves along with the raw data points. Title and axes labels are a must, legends could be shown if necessary.
- Explain the parameters used to measure the fitness characteristics for both the curves.
CURVE FITTING:-
Curve fitting is the process of constructing a curve, or mathematical function, that has the best fit to a series of data points, possibly subject to constraints. Curve fitting can involve either interpolation, where an exact fit to the data is required, or smoothing, in which a "smooth" function is constructed that approximately fits the data.
A related topic is regression analysis, which focuses more on questions of statistical inference such as how much uncertainty is present in a curve that is fit to data observed with random errors. Fitted curves can be used as an aid for data visualization, to infer values of a function where no data are available, and to summarize the relationships among two or more variables.
Extrapolation refers to the use of a fitted curve beyond the range of the observed data, and is subject to a degree of uncertainty since it may reflect the method used to construct the curve as much as it reflects the observed data.
Curve fitting is a process of determining a best possible curve for a given data. This method is useful for extrapolation or interpolation of data. In simple words, curve fitting process can be used to find a data outside the given range.
There are various types of curve fitting process and the use of these process depends on the type of data given. Some of them are as follows -
1. Linear Curve Fitting (Fitting of first order polynomial to a data)
2. Cubic Curve Fitting (Fitting of third order polynomial to a data)
3. Higher Order Curve Fitting (Fitting of higher order polynomial to a data)
4. Curve Fitting using a Splitwise Polynomial Method (Using different/same order polynomial for the different divisions (parts) of given data range)
Parameters used to measure the fitness characteristics for the curve :-
There are four characteristics used to measure the fitness of the curve -
1. SSE (Sum of Sqaured Errors) - It is the sum of square of the errors(i.e difference between individual values). For example, there is dataset with n points having individual error and assuming the best fit for the dataset to be y = f(x).
The error for general 'i' point can be given by the function:
Error = |y(i) - value of f(x) at x(i)| = |y(i) - f(x(i))|
In order to remove the modulus sign we have to square the error term. So, squaring each error and adding them gives error for complete dataset.
SSE = ∑">∑∑(y(i) - f(x(i)))^">^^2 (for i = 1 to n)
Fit with value of SSE closer to zero indicates that the model has a smaller random error component, and that the fit will be more useful for prediction.
2. R-square - It is the square of the corelation between original and predicted response values. It is the quantity that measures how successful is the fit in explaining the variation of the data.
R-square for the dataset with assumed fit as y = f(x),
R-square or R^">^^2 = SSR/SST
where, SSR = ∑">∑∑(f(x(i) - Mean)^">^^2 (for i = 1 to n)
f(x(i)) - value of fitting function at a given point
Mean - arithmetic mean of the dataset
SST = SSR + SSE
Value of R-square varies from 0 to 1.
0 for worst possible fit for the data set and 1 for best possible fit for the data set.
Fit with value of R-square closer to 1 indicating that a greater proportion of variance is accounted for by the model and indicating it is a better fit.
3. Adjusted R-square - It is a normalizing variation of R-square which neglects the vafiation of R-square due to insignificant independent variables.
If value of x(i) contribute to the o/p y, then x(i) is a significant independent variable and if value of x(i) does not contribute to the o/p y, then x(i) is an insignificant independent variable.
Adjusted R-square = 1-(((1 - R-square)*(n - 1))/(n - k - 1))
where, n - no of datapoints
k - number of independent variables
The adjusted R-square statistic can take on any value less than or equal to 1, with a value closer to 1 indicating a better fit. Negative values can occur when the model contains terms that do not help to predict the response.
4. RMSE (Root Mean Squared Error) - Aso known as the fit standard error and the standard error of the regression. It is an estimate of the standard deviation of the random component in the data, and is defined as
RMSE = ">√(( ∑">∑∑(y(i) - f(x(i)))^">^^2)/n) (for i = 1 to n)
where, n - no of datapoints
RMSE value closer to 0 indicates a fit that is more useful for prediction and indicates that it is a better fit.
popt:-
First output argument i.e 'popt' is a 2D array which consists the optimal (best fit) values of coefficients of a polynomial, used for curve fitting process, for which the sum of squared residuals for a given data is minimized. 'popt' can be used to extract the coefficients of a polynomial.
pcov :-
Second output argument i.e 'pcov' is also a 2D array which gives an estimated values of covariance of coefficients (popt) of a polynomial. The diagonal elements of an array/matrix gives the value of covariance of a coefficient with itself which is also called as variance of that coefficent. Other non-diagonal elements of the matrix gives the covariance of a coefficient with other coefficient. It is a square matrix (no. of rows = no. of columns). This array/matrix indicates the uncertainities and correlation between the coefficients of a polynomial and it is mostly useful when the data has uncertainities. 'pcov' can be used to find the standard deviation (square root of the value of diagonal elements) of a given dataset.
np.array(temperature):-
The command 'np.array(temperature)' is used for accessing the individual elements of the temperature array with the help of numpy module. Numpy module/library is imported as 'np' and used to perform mathematical operations like addition, subtraction, multiplication, division, etc. on each element of an array or between the arrays.
* in *popt mean:-
The star i.e '*' in '*popt' unpacks the 'popt' array so that the optimized coefficients (parameters) values can be accessed from the array 'popt'. In other words, '*' (* means all) aids in referring to all the values stored in the array 'popt'.
CODE USING PYTHON :-
Linear Fit :-
# PROGRAM TO CALCULATE TO CURVE FIT USING LINEAR POLYNOMIAL
# Importing required libraries
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
# Reading the 'data' file inputs by defining thid function
# Assigning empty array of temperature
temperature = []
# Assigning empty array of cp
cp = []
def read_file():
for line in open('data','r'): # Reading the data file
val = line.split(',') # splitting the comma to make an array of temperature and cp
temperature.append(float(val[0]))
cp.append(float(val[1]))
return[temperature, cp]
# Defining linear polynomial
def function(t, a, b):
return(a*t+b)
# Calling the function read_file to get temperature and cp
temperature, cp = read_file()
# This command used to find the coefficients of the polynomial
popt, pcov = curve_fit(function, temperature, cp)
# To create an array of the temperature and refering each value using *popt
cp_fit = function(np.array(temperature), *popt)
# Plotting our desired fit
plt.plot(temperature, cp, linewidth = 2, color = 'b', label = 'Actual fit') # Creating an Actual fit of the data file
plt.plot(temperature, cp_fit, linewidth = 2, color = 'r', label = 'Curve fit') # Creating an curve fit using polynomial
plt.xlabel('Temperature(K)')
plt.ylabel('Specific Heat')
plt.legend()
plt.show()
Cubic Fit :-
# PROGRAM TO CALCULATE TO CURVE FIT USING CUBIC POLYNOMIAL
# Importing required libraries
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
# Reading the 'data' file inputs by defining thid function
# Assigning empty array of temperature
temperature = []
# Assigning empty array of cp
cp = []
def read_file():
for line in open('data','r'): # Reading the data file
val = line.split(',') # splitting the comma to make an array of temperature and cp
temperature.append(float(val[0]))
cp.append(float(val[1]))
return[temperature, cp]
# Defining Cubic polynomial
def function(t, a, b, c, d):
return(pow(t, 3)*a+pow(t,2)*b+c*t+d)
# Calling the function read_file to get temperature and cp
temperature, cp = read_file()
# This command used to find the coefficients of the polynomial
popt, pcov = curve_fit(function, temperature, cp)
# To create an array of the temperature and refering each value using *popt
cp_fit = function(np.array(temperature), *popt)
# Plotting our desired fit
plt.plot(temperature, cp, linewidth = 2, color = 'b', label = 'Actual fit') # Creating an Actual fit of the data file
plt.plot(temperature, cp_fit, linewidth = 2, color = 'r', label = 'Curve fit') # Creating an curve fit using polynomial
plt.xlabel('Temperature(K)')
plt.ylabel('Specific Heat')
plt.legend()
plt.show()
STEPS :-
1. Import the basic modules like math, matploltib, numpy and scipy.
2. Defining the function 'read_file' which is further called for reading the thermodynamic data file line by line using the 'for' loop with 'line' as a counter variable and storing the data i.e temperature and specific heat into two arrays 'temperature' and 'cp' respectively after splitting each line using the command 'line.split(',')' where line is the variable having string format containing the data from each line and comma(,), the delimeter, used as a seperator.
3. The function 'read_file' is called then to get the arrays 'temperature' and 'cp'.
4. 'popt' (best fit value of coefficients) and 'pcov'(estimated value of covariance of coefficients) are obtained as output arguments by calling the Python's inbuilt function named as 'curve_fit' and passing the function named as 'linear' and the arrays 'temperature' and 'cp' inside the function 'curve_fit' as an input arguments. Then, the new value of cp according to the linear polynomial i.e 'linear_fit_cp' is calculated by calling the function 'linear' (defined earlier) and passing 'temperature' array element wise using numpy module and all the coefficients of the linear polynomial using '*popt' as an input arguments.
5. Maximum percentage error is calculated by extracting the maximum value from the array 'error' which is calculated using the arrays 'cp' and 'linear_fit_cp'. It is printed in the command window using the command 'print()'.
6. A figure of compsarison is obtained by plotting the original dataset plot i.e (temperature vs cp) and the curve fit plot i.e (temperature vs linear_fit_cp) in a single figure window.
7. Similarly, the cubic polynomial is fitted to the data except the fourth step in which a cubic polynomial is defined which is further passed as an input argument inside the 'curve_fit' function and used for calculating the new value of cp i.e 'cubic_fit_cp'.
8. Also, a figure of compsarison is obtained by plotting the original dataset plot i.e (temperature vs cp) and the curve fit plot i.e (temperature vs cubic_fit_cp) in a single figure window.
OUTPUT:-
Required Graph:-
Linear fit:-
Cubic fit :-
COMPARISON OF OUR ABOVE OUTPUT:-
We can compare the above result by seeing it for which result is better but for higher order polynomial, we have to compare above result good or bad by calculating its SSE, R-square, Adjusted R-square and RMSE values.
For Linear fit:-
# Calculating its SSE, R-square, Adjusted R-square and RMSE values.
# Importing desired libraries
import numpy as np
from scipy.optimize import curve_fit
# Reading the 'data' file inputs by defining thid function
# Assigning empty array of temperature
temperature = []
# Assigning empty array of cp
cp = []
def read_file():
for line in open('data','r'): # Reading the data file
val = line.split(',') # splitting the comma to make an array of temperature and cp
temperature.append(float(val[0]))
cp.append(float(val[1]))
return[temperature, cp]
# Defining Cubic polynomial
def function(t, a, b):
return(a*t+b)
# Calling the function read_file to get temperature and cp
temperature, cp = read_file()
#No. of data poinnts
n = len(temperature)
#No of Independent variables
j = 0
# This command used to find the coefficients of the polynomial
popt, pcov = curve_fit(function, temperature, cp)
# To create an array of the temperature and refering each value using *popt
cp_fit = function(np.array(temperature), *popt)
# CALCULATION OF FITNESS CHARACTERISTICS
print('Fitness Characteristic of the fit')
print('\n')
# Calculating SSE
SSE = np.sum(pow((np.array(np.array(cp) - np.array(cp_fit))), 2))
print('SSE Value',SSE)
print('\t')
# Calculating SSR
SSR = np.sum(pow((np.array(np.array(cp_fit) - np.mean(cp))), 2))
#Total sum of squares (SST)
SST = SSE + SSR
#R-square
R_square = SSR/SST
print('R-square Value =',R_square)
print('\t')
#Adjusted R-square
Adjusted_R_square = 1 - ((1 - R_square)*(n - 1)/(n - j - 1))
print('Adjusted_R_square Value =', Adjusted_R_square)
print('\t')
#Root Mean Squared Error(RMSE)
RMSE = np.sqrt((np.sum(pow((np.array(np.array(cp) - np.array(cp_fit))), 2)))/n);
print('RMSE Value =', RMSE)
print('\t')
Output:-
Cubic fit :-
# Calculating its SSE, R-square, Adjusted R-square and RMSE values.
# Importing desired libraries
import numpy as np
from scipy.optimize import curve_fit
# Reading the 'data' file inputs by defining thid function
# Assigning empty array of temperature
temperature = []
# Assigning empty array of cp
cp = []
def read_file():
for line in open('data','r'): # Reading the data file
val = line.split(',') # splitting the comma to make an array of temperature and cp
temperature.append(float(val[0]))
cp.append(float(val[1]))
return[temperature, cp]
# Defining Cubic polynomial
def function(t, a, b, c, d):
return(pow(t, 3)*a+pow(t,2)*b+c*t+d)
# Calling the function read_file to get temperature and cp
temperature, cp = read_file()
#No. of data poinnts
n = len(temperature)
#No of Independent variables
j = 0
# This command used to find the coefficients of the polynomial
popt, pcov = curve_fit(function, temperature, cp)
# To create an array of the temperature and refering each value using *popt
cp_fit = function(np.array(temperature), *popt)
# CALCULATION OF FITNESS CHARACTERISTICS
print('Fitness Characteristic of the fit')
print('\n')
# Calculating SSE
SSE = np.sum(pow((np.array(np.array(cp) - np.array(cp_fit))), 2))
print('SSE Value',SSE)
print('\t')
# Calculating SSR
SSR = np.sum(pow((np.array(np.array(cp_fit) - np.mean(cp))), 2))
#Total sum of squares (SST)
SST = SSE + SSR
#R-square
R_square = SSR/SST
print('R-square Value =',R_square)
print('\t')
#Adjusted R-square
Adjusted_R_square = 1 - ((1 - R_square)*(n - 1)/(n - j - 1))
print('Adjusted_R_square Value =', Adjusted_R_square)
print('\t')
#Root Mean Squared Error(RMSE)
RMSE = np.sqrt((np.sum(pow((np.array(np.array(cp) - np.array(cp_fit))), 2)))/n);
print('RMSE Value =', RMSE)
print('\t')
Output:-
What needs to be done in order to make the curve fit perfect?
Firstly, we can increase the degree of the polynomial to make the curve fit perfect. So we plot the highesgt degree of polynomial which gives perfect fit of the curve. But this is very complicated.
Plots of Higher order Polynomial:-
Fifth order polynomial:-
Seventh order polynimial:-
Ninth order Polynomial:-
Therefore, 9th order Polynomial giver perfect fit.
But the above method of Higher order curve fitting method is very time consuming and not very efficient. So there is another good method to make curve fit perfect that is Curve fitting by Splitwise Polynomial method.
Code to perform splitwise method for curve fitting :-
# PROGRAM TO CALCULATE TO CURVE FIT USING CUBIC POLYNOMIAL
# Importing required libraries
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
# Reading the 'data' file inputs by defining thid function
# Assigning empty array of temperature
temperature = []
# Assigning empty array of cp
cp = []
def read_file():
for line in open('data','r'): # Reading the data file
val = line.split(',') # splitting the comma to make an array of temperature and cp
temperature.append(float(val[0]))
cp.append(float(val[1]))
return[temperature, cp]
# Defining Cubic polynomial
def function(t, a, b, c, d):
return(a*pow(t, 3) + b*pow(t, 2) + c*t + d)
# Calling the function read_file to get temperature and cp
temperature, cp = read_file()
#Splitting the temperature and cp arrays
#Temperature and cp values for Ranges
temperature1 = temperature[0:800]
cp1 = cp[0:800]
temperature2 = temperature[800:1600]
cp2 = cp[800:1600]
temperature3 = temperature[1600:2400]
cp3 = cp[1600:2400]
temperature4 = temperature[2400:3200]
cp4 = cp[2400:3200]
# This command used to find the coefficients of the polynomial
# Curve Fitting
popt1, pcov1 = curve_fit(function, temperature1, cp1)
cp_fit1 = function(np.array(temperature1), *popt1)
popt2, pcov2 = curve_fit(function, temperature2, cp2)
cp_fit2 = function(np.array(temperature2), *popt2)
popt3, pcov3 = curve_fit(function, temperature3, cp3)
cp_fit3 = function(np.array(temperature3), *popt3)
popt4, pcov4 = curve_fit(function, temperature4, cp4)
cp_fit4 = function(np.array(temperature4), *popt4)
#Creating splitwise cp_fit array
cp_fit = np.concatenate((cp_fit1, cp_fit2, cp_fit3, cp_fit4))
# Plotting our desired fit
plt.plot(temperature, cp, color = 'b', label = 'Actual fit') # Creating an Actual fit of the data file
plt.plot(temperature, cp_fit, color = 'r', label = 'Curve fit') # Creating an curve fit using polynomial
plt.xlabel('Temperature(K)')
plt.ylabel('Specific Heat')
plt.legend()
plt.show()
OUTPUT:-
Therefore, above output concludes that Splitwise Curve fitting method produces perfect fit in Efficient way.