Week 5 - Curve fitting
Attempted
Curve fitting in Python
Week 5
Answers for the questions:
- What does popt and pcov mean? (Watch the video to get some context)
popt – An array of optimal values for the parameters which minimizes the sum of squares of residual.
pcov – 2D array which contains the estimated covariance of popt. The diagonals provide the variance of the parameter estimate.
- What does np.array(temperature) do?
Converts the python list of temperature to a numpy array since operations like pow are allowed on numpy arrays and not python lists.
- What does the * in *popt mean?
*- reference to popt – the values are stored in the array popt.
- Write code to fit a linear and cubic polynomial for the Cp data. Explain if your results are good or bad.
Introduction:
Curve fitting is a process of constructing a curve or mathematical function that has the best fit to a series of data points possibly subject to certain 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.
Procedure for coding:
- Importing the math library for mathematical calculation, numpy to create the array for temperature ,matplotlib.pyplot for plotting and from scipy module importing curve fit to perform the curve fit.
- Using open command, for reading the file from which data to be extracted . We use letter ‘r’ to read the data. As there is a huge amount of data in our file, we use for loop to read every line and split the data with the comma “,” , in the lines of the data using split function.
- Defining the linear and cubic functions so that they can be called later in the program.
- Temperature and specific heat are stored in separate arrays , using numpy module.
- Curve fit is done in which it returns two arrays “popt” and “pcov”, popt is the array of optimal values for the parameters which minimizes the sum of squares of residual of f(xdata, *popt) -ydata is minimized.
- While passing the popt in the curve fit we have used it as the *popt, that is because the * is the pointer operator and points out all the elements in that array.
- The predicted cp is calculated as the fit_cp_linear and fit_cp_cubic for linear and cubic respectively.
- The graph is plotted using the predicted cp of the polynomials and compared with the original data set.
# CODE FOR CUBIC AND LINEAR FIT
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import math
#curve_fit
file =open('data','r')
def linfunc(t,a,b,c):
return a*t+b
def cubicfunc(t,a,b,c,d):
return a*pow(t,3)+b*pow(t,2)+c*t+d
def fourthfunc(t,a,b,c,d,e):
return a*pow(t,4)+b*pow(t,3)+c*pow(t,2)+d*t +e
def fifthfunc(t,a,b,c,d,e,f):
return a*pow(t,5)+b*pow(t,4)+c*pow(t,3)+d*pow(t,2) +e*t+f
def read_file():
temperature = []
cp =[]
for line in file:
value = line.split(',')
temperature.append(float(value[0]))
cp.append(float(value[1]))
return [temperature,cp]
temperature,cp = read_file()
popt,pcov = curve_fit(linfunc,temperature,cp) #popt -optimum parameters are returned which then can be passed into the function
fit_cp_linear = linfunc(np.array(temperature),*popt)
popt1,pcov1 = curve_fit(cubicfunc,temperature,cp)
fit_cp_cubic = cubicfunc(np.array(temperature),*popt1)
popt2,pcov2 = curve_fit(fourthfunc,temperature,cp)
fit_cp_fourth = fourthfunc(np.array(temperature),*popt2)
popt3,pcov3 = curve_fit(fifthfunc,temperature,cp)
fit_cp_fifth = fifthfunc(np.array(temperature),*popt3)
plt.figure(1)
plt.plot(temperature,cp,linewidth =3 ,color='red')
plt.plot(temperature,fit_cp_linear,linewidth=3, color ='blue')
plt.plot(temperature,fit_cp_cubic,linewidth=3, color ='green')
plt.plot(temperature,fit_cp_fourth,linewidth=3, color ='yellow')
plt.plot(temperature,fit_cp_fifth,linewidth=3, color ='orange')
plt.xlabel('Temperature in K')
plt.ylabel('Specific heat')
plt.legend(['actual fit','quadratic fit','cubic fit','fourth order' ,'fifth order'])
plt.grid()
plt.savefig('quadratic_fit')
plt.show()
plt.figure(2)
plt.plot(temperature,cp,linewidth =3 ,color='red')
plt.plot(temperature,fit_cp_linear,linewidth=3, color ='blue')
plt.xlabel('Temperature in K')
plt.ylabel('Specific heat')
plt.legend(['actual fit','linear fit'])
plt.grid()
plt.savefig('linear fit')
plt.show()
pltfigure(3)
plt.plot(temperature,cp,linewidth =3 ,color='red')
plt.plot(temperature,fit_cp_cubic,linewidth=3, color ='green')
plt.xlabel('Temperature in K')
plt.ylabel('Specific heat')
plt.legend(['actual fit','cubic fit'])
plt.grid()
plt.savefig('cubic_fit')
plt.show()
#Calculation of residuals r =data -fit
r1 = cp - linfunc(np.array(temperature),*popt)
r2 = cp - cubicfunc(np.array(temperature),*popt1)
r3 = cp - fourthfunc(np.array(temperature),*popt2)
r4 = cp - fifthfunc(np.array(temperature),*popt3)
print('Residual1=',r1)
print('Residual2=',r2)
print('Residual3=',r3)
print('Residual4=',r4)
#Standard deviation error of the co-efficients
per1 = np.sqrt(np.diag(pcov))
per2 = np.sqrt(np.diag(pcov1))
per3 = np.sqrt(np.diag(pcov2))
per4 = np.sqrt(np.diag(pcov3))
print('per1 =' , per1)
print('per2 =' , per2)
print('per3 =' , per3)
print('per4 =' , per4)
#CODE FOR BEST CURVE FIT - SPLIT DATA
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import math
#curve_fit
file =open('data','r')
def quadfunc(t,a,b,c):
return a*pow(t,2)+b*t+c
def cubicfunc(t,a,b,c,d):
return a*pow(t,3)+b*pow(t,2)+c*t+d
def fourthfunc(t,a,b,c,d,e):
return a*pow(t,4)+b*pow(t,3)+c*pow(t,2)+d*t +e
def fifthfunc(t,a,b,c,d,e,f):
return a*pow(t,5)+b*pow(t,4)+c*pow(t,3)+d*pow(t,2) +e*t+f
def read_file():
temperature = []
cp =[]
for line in file:
value = line.split(',')
temperature.append(float(value[0]))
cp.append(float(value[1]))
return [temperature,cp]
temperature,cp = read_file()
t1= np.array(temperature[0:800])
t2= np.array(temperature[800:1600])
t3= np.array(temperature[1600:2400])
t4= np.array(temperature[2400:3200])
popt,pcov = curve_fit(quadfunc,t1,cp[0:800])
popt1,pcov1 = curve_fit(cubicfunc,t2,cp[800:1600])
popt2,pcov2 = curve_fit(fourthfunc,t3,cp[1600:2400])
popt3,pcov3 = curve_fit(fifthfunc,t4,cp[2400:3200]) #popt -optimum parameters are returned which then can be passed into the function
fit_cp_quad = quadfunc(np.array(t1),*popt)
fit_cp_cubic = cubicfunc(np.array(t2),*popt1)
fit_cp_fourth = fourthfunc(np.array(t3),*popt2)
fit_cp_fifth = fifthfunc(np.array(t4),*popt3)
plt.figure(1)
plt.plot(temperature,cp,linewidth =3 ,color='red')
plt.plot(t1,fit_cp_quad,linewidth=3, color ='blue')
plt.plot(t2,fit_cp_cubic,linewidth=3, color ='green')
plt.plot(t3,fit_cp_fourth,linewidth=3, color ='yellow')
plt.plot(t4,fit_cp_fifth,linewidth=3, color ='orange')
plt.xlabel('Temperature in K')
plt.ylabel('Specific heat')
plt.legend(['actual fit','quadratic fit','cubic fit','fourth order' ,'fifth order'])
plt.grid()
plt.savefig('quadratic_fit')
plt.show()
#Calculation of residuals r =data -fit
r1 = cp[0:800] - quadfunc(np.array(t1),*popt)
r2 = cp[800:1600] - cubicfunc(np.array(t2),*popt1)
r3 = cp[1600:2400] - fourthfunc(np.array(t4),*popt2)
r4 = cp[2400:3200] - fifthfunc(np.array(t4),*popt3)
print('Residual1=',r1)
print('Residual2=',r2)
print('Residual3=',r3)
print('Residual4=',r4)
#Standard deviation error of the co-efficients
per1 = np.sqrt(np.diag(pcov))
per2 = np.sqrt(np.diag(pcov1))
per3 = np.sqrt(np.diag(pcov2))
per4 = np.sqrt(np.diag(pcov3))
print('per1 =' , per1)
print('per2 =' , per2)
print('per3 =' , per3)
print('per4 =' , per4)
Resuts & Discussion:
Residuals
The residuals from a fitted model are defined as the differences between the response data and the fit to the response data at each predictor value.
- residual = data – fit
In the code, the same concept is used to find the residual or error.
The standard deviation is also found for every interval and printed.
Conclusions:
- By using higher order polynomials, we minimize the error as we can see the cubic fit fits the curve best than the linear fit.
- We can also make the curve best fit using the different polynomials for different temperature range or splitting the data into the certain number of sets, here I have split into 4.