Polynomial
We can use polynomial basis expansion to add
non-linear features.

import numpy as np
import matplotlib.pyplot as plt
X1 = [30, 46, 60, 65, 77, 95]
y1 = [31, 30, 80, 49, 70, 118]
X2 = [17, 40, 55, 57, 70, 85]
y2 = [19, 50, 60, 32, 90, 110]
def pred_polinomial(degree, x_unknown, X1, y1):
p = np.poly1d(np.polyfit(X1, y1, degree))
t = np.linspace(0, 100, 100)
plt.figure(figsize=(6,4))
plt.scatter(X1, y1, color='blue', label='Training set')
plt.scatter(X2, y2, color='red', label='Test set')
plt.plot(t, p(t), color='orange')
SSR1 = sum((p(X1) - y1) ** 2).round()
SSR2 = sum((p(X2) - y2) ** 2).round()
weight = round(sum(abs(p.coef)))
xa = x_unknown
ya = round(p(xa),2)
plt.scatter(xa, ya, color='r', marker='x')
plt.annotate(f'({xa}, {ya}, SSR1 = {SSR1}) SSR2 = {SSR2})', (xa+0.1, ya-10))
plt.title(f'{degree}-degree polynomial')
plt.legend(loc='best')
plt.xlabel('Area (m^2)')
plt.ylabel('Price (10,000$)')
plt.xlim((0, 100))
plt.ylim((0, 130))
xf1 = "{:.1f}x + {:.1f}"
xf2 = "{:.1f}x^2 + " + xf1
xf3 = "{:.1f}x^3 + " + xf2
xf4 = "{:.1f}x^4 + " + xf3
xf5 = "{:.1f}x^5 + " + xf4
if degree == 1:
print(("p(x) = " + xf1).format(p[1], p[0]))
elif degree == 2:
print(("p(x) = " + xf2).format(p[2], p[1], p[0]))
elif degree == 3:
print(("p(x) = " + xf3).format(p[3], p[2], p[1], p[0]))
elif degree == 4:
print(("p(x) = " + xf4).format(p[4], p[3], p[2], p[1], p[0]))
elif degree == 5:
print(("p(x) = " + xf5).format(p[5], p[4], p[3], p[2], p[1], p[0]))
print('SSR1 =', SSR1, ' / ', 'SSR2 =', SSR2)
print('weight = ', weight, '\n')
return
x_unknown = 50
pred_polinomial(1, x_unknown, X1, y1)
pred_polinomial(2, x_unknown, X1, y1)
pred_polinomial(3, x_unknown, X1, y1)
pred_polinomial(4, x_unknown, X1, y1)
pred_polinomial(5, x_unknown, X1, y1)
plt.show()

$$ f(x) = w_0 + w_1 x $$

$$ f(x) = w_0 + w_1 x + w_2 x^2 $$

$$ f(x) = w_0 + w_1 x + w_2 x^2 + w_3 x^3 $$

$$ f(x) = w_0 + w_1 x + w_2 x^2 + w_3 x^3 + w_4 x^4 $$

$$ f(x) = w_0 + w_1 x + w_2 x^2 + w_3 x^3 + w_4 x^4 + w_5 x^5 $$