Challenge

Week 5 - Curve fitting

Aim: To perform curve fitting using Python

Objective:
1) To code and obtain graph of cubic and linear functions for C_p data.
2) To get the coefficients of the equations and compare the futted data with the actual data to observe how well the curve fits.
3) To write a code that computes the characterics of the fitted data to check for errors.

Introduction:

Curve fitting is one of the most powerful and most widely used analysis tools in Origin. Curve fitting examines the relationship between one or more predictors (independent variables) and a response variable (dependent variable), with the goal of defining a "best fit" model of the relationship. For algebraic analysis of data, "fitting" usually means trying to find the curve that minimizes the vertical (y-axis) displacement of a point from the curve (e.g., ordinary least squares). However, for graphical and image applications geometric fitting seeks to provide the best visual fit; which usually means trying to minimize the orthogonal distance to the curve.

Linear curve fitting :
Linear curve fitting, or linear regression, is when the data is fit to a straight line. Although there might be some curve to your data, a straight line provides a reasonable enough fit to make predictions.

The first degree polynomial equation

`y = ax+b` is a line with slope a. A line will connect any two points, so a first degree polynomial equation is an exact fit through any two points with distinct x coordinates.

Polynomial curve fitting:
Polynomial curve fitting is when we fit out data to the graph of a polynomial function.
If the order of the equation is increased to a second degree polynomial, the following results:

`y = ax^2 + bx +c`

This will exactly fit a simple curve to three points.

If the order of the equation is increased to a third degree polynomial, the following is obtained:

`y = ax^3 + bx^2 + cx + d`


This will exactly fit four points.

Measurement of the curve characteristics:

After a curve is obtained through curve fitting , there are 4 quantiities which help us define the measurement of goodness of fit criteria which tells us how well a function represents an actual data.
1) The sum of squares due to error (SSE)
2) R - square
3) Adjusted R - Square
4) Root Mean Squared Error (RMSE)

Equations used :

Sum of Squared Errors (SSE): `Sigma(y_i - f(x_i))`

Sum of Squared Errors (SSR) = `Sigma(f(x_i) - Mean)^2`

SST = SSE + SSR

From these terms, `R^2` can be calculated

`R^2 = (SSR)/(SST`

RMSE = `sqrt((SSE)/n`

Python code:

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import math

#----------------------------------
#Linear curve-fitting
#----------------------------------


#defnition of linear function
def linear(t,a,b):
	return a*t+b

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()
popt,pocv = curve_fit(linear,temperature, cp)
fit_cp = linear(np.array(temperature), *popt)

#understanding the characteristics of curve-fit
s = np.sum(cp)
n = len(cp)
mean = s/n

Sum_of_squared_errors = 0
Sum_of_squared_regression = 0

for i in range(n):
	linear_error = cp[i]-fit_cp[i]
	linear_regress = fit_cp[i]-mean
	Sum_of_squared_errors = (Sum_of_squared_errors + np.sum(pow(linear_error,2)))
	Sum_of_squared_regression = (Sum_of_squared_regression + np.sum(pow(linear_regress,2)))

SSE = Sum_of_squared_errors
SSR = Sum_of_squared_regression

SST = SSE + SSR

R_squared = SSR/SST

Root_Mean_Square_Error = math.sqrt(SSE/n)

print('The RMSE for the linear function is :', Root_Mean_Square_Error)
print('The R_squared for the linear function is :', R_squared)

#plot of the obtained data and curve-fit data. 


plt.plot(temperature,cp,color = 'r', linewidth = 1)
plt.plot(temperature,fit_cp,color = 'b', linewidth = 2)
plt.legend(['actual-data', 'curve-fit data'])
plt.xlabel('temperature')
plt.ylabel('cp')

plt.show()


#----------------------------------
#Cubic and quartic curve-fitting
#----------------------------------

# definition of cubic function

def cube(t,a,b,c,d):
	return a*pow(t,3)+b*pow(t,2)+c*pow(t,1)+d

# definition of a quartic function

def quartic(t,a,b,c,d,e):
	return a*pow(t,4)+b*pow(t,3)+c*pow(t,2)+d*t+e

#reading file from folder

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()

#obtaining fit for the cubic function
popt_3,pocv_3 = curve_fit(cube,temperature, cp)
fit_cp_3 = cube(np.array(temperature), *popt_3)


# obtaining fit data for the quartic function
popt_4,pocv_4 = curve_fit(quartic,temperature, cp)
fit_cp_4 = quartic(np.array(temperature), *popt_4)




#understanding characteristics of the cubic curve
s_cubic = np.sum(cp)
n_cubic = len(cp)
mean_cubic = s_cubic/n_cubic

Sum_of_squared_errors_cubic = 0
Sum_of_squared_regression_cubic = 0

for i in range(n_cubic):
	cubic_error = cp[i]-fit_cp_3[i]
	cubic_regress = fit_cp_3[i]-mean_cubic
	Sum_of_squared_errors_cubic = (Sum_of_squared_errors_cubic + np.sum(pow(cubic_error,2)))
	Sum_of_squared_regression_cubic = (Sum_of_squared_regression_cubic + np.sum(pow(cubic_regress,2)))

SSE_cubic = Sum_of_squared_errors_cubic
SSR_cubic = Sum_of_squared_regression_cubic

SST_cubic = SSE_cubic + SSR_cubic

R_squared_cubic = SSR_cubic/SST_cubic

Root_Mean_Square_Error_cubic = math.sqrt(SSE_cubic/n_cubic)

print('The RMSE for the cubic function is :', Root_Mean_Square_Error_cubic)
print('The R_squared for the cubic function is :', R_squared_cubic)

#understanding characteristics of the quartic curve
s_quartic = np.sum(cp)
n_quartic = len(cp)
mean_quartic = s_quartic/n_quartic

Sum_of_squared_errors_quartic = 0
Sum_of_squared_regression_quartic = 0

for i in range(n_quartic):
	quartic_error = cp[i]-fit_cp_4[i]
	quartic_regress = fit_cp_4[i]-mean_quartic
	Sum_of_squared_errors_quartic = (Sum_of_squared_errors_quartic + np.sum(pow(quartic_error,2)))
	Sum_of_squared_regression_quartic = (Sum_of_squared_regression_quartic + np.sum(pow(quartic_regress,2)))

SSE_quartic = Sum_of_squared_errors_quartic
SSR_quartic = Sum_of_squared_regression_quartic

SST_quartic = SSE_quartic + SSR_quartic

R_squared_quartic = SSR_quartic/SST_quartic

Root_Mean_Square_Error_quartic = math.sqrt(SSE_quartic/n_quartic)

print('The RMSE for the quartic function is :', Root_Mean_Square_Error_quartic)
print('The R_squared for the quartic function is :', R_squared_quartic)


#plot of the obtained data vs the actual data for the cubic function
plt.plot(temperature,cp,color = 'r', linewidth = 1)
plt.plot(temperature,fit_cp_3,color = 'b', linewidth = 2)
plt.legend(['actual-data', 'curve-fit data'])
plt.xlabel('temperature')
plt.ylabel('cp')

plt.show()

#plot of the obtained data vs actual data for the quartic function

plt.plot(temperature,cp,color = 'r', linewidth = 1)
plt.plot(temperature,fit_cp_4,color = 'g', linewidth = 2)
plt.legend(['actual-data', 'curve-fit data'])
plt.xlabel('temperature')
plt.ylabel('cp')

plt.show()

Results:

1) Linear function curve:

2) Curve for a cubic polynomial:

3) Curve for quartic polynomial:




Results of curve characteristics:

RMSE = Root Mean Squared Error

The RMSE for the linear function is : 25.999093068195325
The R_squared for the linear function is : 0.9248776260524184


The RMSE for the cubic function is : 5.42770728878495
The R_squared for the cubic function is : 0.996725946714689


The RMSE for the quartic function is : 1.8599626013389154
The R_squared for the quartic function is : 0.9996155309982948

What does *popt and *pcov mean?
*POPT: popt is a one dimensional array of the best estimates for the parameter values, each entry matches the order in the function definition.

*PCOV: pcov is the covariance matrix showing the uncertainty and interdependence of each parameter in popt.

What does the * in *popt mean?
The '*' value returns each coefficient sotred in the popt array.

What can be done to get a better curve - fit?
If we increase the order of the polynomial, error grows smaller and eventually, we will get a perfect curve-fit.

Conclusion:
From the observed values of errors, as the polynomial order increases, the error decreases.

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.