Week 5 - Curve fitting
AIM: Write code in order execute curve fitting in Python
OBJECTIVES:
- Read the data from the given file
- Fit a linear and cubic polynomial for the given cp data
- Plot the curves
- Measure fitness characteristics
QUESTIONS:
- What does popt and pcov mean?
- What does np.array(temperature) do?
- What does the * in *popt mean?
- What needs to be done in order to make the curve fit perfect?
CURVE FITTING:
The process of constructing a curve using the available data is known as curve fitting. Curve fitting may involve the following:
- Interpolation- where exact data fit is required
- Smoothing- where a smooth function is constructed and the data is approximately fitted
Once the curve is plotted, based on the existing relation between data (regression), the user can extrapolate and predict future data; which is a trending job in todays era.
The user is free to select the curve fitting methods based on the required accuracy.
MEASURING THE FITNESS CHARACTERISTICS:
The goodness of fit is a quantitative value that depends on the fitness criteria being evaluated:
Measuring the goodness of fit criteria:
Let us assume that we have data points (x1,y1), (x2,y2), (x3,y3), ..., (xn,yn) and the curve fitted is y=f(x).
The error is calculated as: Error= |y(i) - (f(x) at i)|
- Sum of Squares due to error (SSE)
It is obtained by squaring the error and adding the obtained value throughout the data points. ie. from i=1 to i=n.
SSE`= sum_(i=1) ^(n)`Error`(i)^2` - R-Square
It is the square of the correlation between the response values and the predicted response values.
R-square values range from 0-1.
If,
R-square = 0: Worst fit for data series
R-square = 1: Best fit for data series - Adjusted R-Square
This is a normalizing variation of R-square which neglects the variation of R-square due to insignificant independent variables.
`R_(adj)^2=``1-[((1-R^2)(n-1))/(n-k-1)]`
Where:
n- Number of data points
k- Number of independent variables - Root Mean Squared Error (RMSE)
This method is an estimate of the standard deviation of the random component in the data and defined as:
RMSE = `root()((SSE)/n`
Where:
n- Total number of datapoints available
BEST FIT: When the predicted curve has slight deviation from the original curve, it is known as best fit.
PERFECT FIT: When the predicted curve has no/slightest deviation from the original curve, it is known as best fit.
CODE:
import math
import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
#Reading thermodynamic data from file
def read_file():
temperature = []
cp = []
for line in open('data', 'r'):
values = line.split(',')
temperature.append(float(values[0]))
cp.append(float(values[1]))
return[temperature, cp]
temperature, cp = read_file() #Reading the file
#Curve Fitting using Linear Polynomial
#Function definition for linear polynomial
def linear(T, a, b):
return(a*T + b)
popt1, pcov1 = curve_fit(linear, temperature, cp)
linear_fit_cp = linear(np.array(temperature), *popt1)
#Maximum Percentage Error
error1 = (np.array(np.array(cp) - np.array(linear_fit_cp)))*100/(np.array(cp))
max_error1 = max(error1)
print('Maximum Percentage Error for Linear Polynomial =', '%.3f'%max_error1,'\n')
#Plotting both curves
plt.figure(1)
plt.plot(temperature, cp, linewidth = 3, label = 'Original Data')
plt.plot(temperature, linear_fit_cp, linewidth = 3, label = 'Curve Fit')
plt.title('Curve fit using linear polynomial')
plt.xlabel('Temperature [K]')
plt.ylabel('Specific Heat [kJ/kg-K]')
plt.legend(loc = 'lower right')
plt.savefig('Curve fit using linear polynomial.png')
plt.show()
#Curve Fitting using Cubic Polynomial
#Function definition for cubic polynomial
def cubic(T, a, b, c, d):
return(a*pow(T, 3) + b*pow(T, 2) + c*T + d)
popt2, pcov2 = curve_fit(cubic, temperature, cp)
cubic_fit_cp = cubic(np.array(temperature), *popt2)
#Maximum Percentage Error
error2 = (np.array(np.array(cp) - np.array(cubic_fit_cp)))*100/(np.array(cp))
max_error2 = max(error2)
print('Maximum Percentage Error Cubic Polynomial =', '%.3f'%max_error2,'\n')
#Plotting both curves
plt.figure(2)
plt.plot(temperature, cp, linewidth = 3, label = 'Original Data')
plt.plot(temperature, cubic_fit_cp, linewidth = 3, label = 'Curve Fit')
plt.title('Curve fit using cubic polynomial')
plt.xlabel('Temperature [K]')
plt.ylabel('Specific Heat [kJ/kg-K]')
plt.legend(loc = 'lower right')
plt.savefig('Curve fit using cubic polynomial.png')
plt.show()
#-----------------------------------------------------------------#
n = len(temperature) #Number of data points
k = 0 #Independent variables
#Goodness of Curve Fit
print('SSE, R-square, Adjusted R-square and RMSE Values for Polynomial of Degree = 1','\n')
#Sum of Square of Errors (SSE)
SSE = np.sum(pow((np.array(np.array(cp) - np.array(linear_fit_cp))), 2))
print('Value of SSE =','%.3f'%SSE,'\n')
# Sum of squares of regression (SSR)
SSR = np.sum(pow((np.array(np.array(linear_fit_cp) - np.mean(cp))), 2))
#Total sum of squares (SST)
SST = SSE + SSR
#R-square
R_square = SSR/SST
print('Value of R-square =', '%.3f'%R_square,'\n')
#Adjusted R-square
Adjusted_R_square = 1 - ((1 - R_square)*(n - 1)/(n - k - 1))
print('Value of Adjusted_R_square =', '%.3f'%Adjusted_R_square,'\n')
#Root Mean Squared Error(RMSE)
RMSE = np.sqrt((np.sum(pow((np.array(np.array(cp) - np.array(linear_fit_cp))), 2)))/n);
print('Value of RMSE =', '%.3f'%RMSE,'\n')
#Calculation of fitness characteristics
#Goodness of Curve Fit
print('SSE, R-square, Adjusted R-square and RMSE Values for Polynomial of Degree = 3','\n')
#Sum of Square of Errors (SSE)
SSE = np.sum(pow((np.array(np.array(cp) - np.array(cubic_fit_cp))), 2))
print('Value of SSE =', '%.3f'%SSE,'\n')
# Sum of squares of regression (SSR)
SSR = np.sum(pow((np.array(np.array(cubic_fit_cp) - np.mean(cp))), 2))
#Total sum of squares (SST)
SST = SSE + SSR
#R-square
R_square = SSR/SST
print('Value of R-square =', '%.3f'%R_square,'\n')
#Adjusted R-square
Adjusted_R_square = 1 - ((1 - R_square)*(n - 1)/(n - k - 1))
print('Value of Adjusted_R_square =', '%.3f'%Adjusted_R_square,'\n')
#Root Mean Squared Error(RMSE)
RMSE = np.sqrt((np.sum(pow((np.array(np.array(cp) - np.array(cubic_fit_cp))), 2)))/n);
print('Value of RMSE =', '%.3f'%RMSE,'\n')
EXPLANATION OF CODE:
- Define all libraries
- Define a function to read the file and extract values to the temperature and cp array(s) using the split()
- Call the function to read data
- Define a function for the linear polynomial ax+b
- Calculate its coefficients using the curve_fit()
- Calculate the error and display its maximum value
- Plot the figure that compares both curves
- Do the same with a cubic curve
- Define constants for the number of datapoints and the number of independent variables
- Calculate SSE, SSR, R square, adjusted R square, SST and RMSE as described in the above section
- Print all the values for linear and cubic polynomial
EXPLANATION OF CODE:
- Define all libraries
- Define a function to read the file and extract values to the temperature and cp array(s) using the split()
- Call the function to read data
- Define a function for the linear polynomial ax+b
- Calculate its coefficients using the curve_fit()
- Calculate the error and display its maximum value
- Plot the figure that compares both curves
- Do the same with a cubic curve
- Define constants for the number of datapoints and the number of independent variables
- Calculate SSE, SSR, R square, adjusted R square, SST and RMSE as described in the above section
- Print all the values for linear and cubic polynomial
RESULTS AND DISCUSSION:
1. Plots
2. Output console
From the above plot and the displayed output values. We can conclude that the cubic fit yields a better curve fit result over the linear one due to the low error percentage, better SSE, R-square, Adjusted R-square and RMSE values.
3.
popt contains the coeffecient values of the output of curve_fit().
pcov contains the covariance of the coefficients of the function.
4. np.array(temperature)
We have imported the numpy module as np, hence the function starts with np. Array() is used to access individual elements of the array temperature negating the use of a for loop.
5. In order to improve the curve fit,
- Higher order polynomials can be used
- Split function polynimials can be used where, 2-3 polynomials can be employed in different data ranges