In [1]:
%matplotlib inline
# Using gradient descent for linear regression
# Ideas from https://spin.atomicobject.com/2014/06/24/gradient-descent-linear-regression/
# We will attempt to predict the college admission test score based
# on the high school math score (following on Chapter 3 of "Doing Math with Python")
# Known data
x_data = [83, 85, 84, 96, 94, 86, 87, 97, 97, 85]
y_data = [85, 87, 86, 97, 96, 88, 89, 98, 98, 87]
from sympy import Symbol, Derivative
import matplotlib.pyplot as plt
# Assumed linear model
# x = math score in high school
# y = admission test score
# y = m*x + c
def estimate_y(x, m, c):
y_estimated = m*x + c
return y_estimated
def estimate_theta(m_current, c_current, max_iterations=50000):
learning_rate = 0.0001
m_gradient = 0
c_gradient = 0
N = len(x_data)
m = Symbol('m')
c = Symbol('c')
y = Symbol('y')
x = Symbol('x')
# Error term
error_term = (y - (m*x+c))**2
# Error function = 1/n*sum(error_term)
for i in range(max_iterations):
for i in range(0, N):
m_gradient += (1/N)*Derivative(error_term, m).doit().subs({x:x_data[i], y:y_data[i], m:m_current, c:c_current})
c_gradient += (1/N)*Derivative(error_term, c).doit().subs({x:x_data[i], y:y_data[i], m:m_current, c:c_current})
m_new = m_current - (learning_rate * m_gradient)
c_new = c_current - (learning_rate * c_gradient)
if abs(m_new - m_current) < 1e-5 or abs(c_new - c_current) < 1e-5:
break
else:
m_current = m_new
c_curret = c_new
return m_new, c_new
m, c = estimate_theta(1, 1)
# Let's try and unknown set of data
# This data set is different and widely spread,
# but they are very similarly correlated
x_data = [63, 61, 98, 76, 74, 59, 40, 87, 71, 75]
y_data = [65, 62, 99, 78, 75, 60, 42, 89, 71, 77]
y_estimated = [estimate_y(x, m, c) for x in x_data]
plt.plot(x_data, y_data, 'ro')
plt.plot(x_data, y_estimated, 'b*')
plt.legend(['Actual', 'Estimated'], loc='best')
plt.show()
In [ ]: