from sklearn.linear_model import LinearRegression
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
# Retina display
%config InlineBackend.figure_format = 'retina'
Basis Functions Regression
= lambda x: np.cos(1.5 * np.pi * x) + (1+x)*np.sin(0.5 * np.pi * x)
f_true = lambda x: f_true(x) + np.random.randn(*x.shape) * 0.3
f
= np.linspace(0, 1, 100)
x = f(x)
y 'o', label='data')
plt.plot(x, y, ='true')
plt.plot(x, f_true(x), label='best') plt.legend(loc
<matplotlib.legend.Legend at 0x7f883e31b850>
# Fit a phi function transformed linear model
def y_hat_basis(x_train, y_train, x_test, phi):
= LinearRegression()
model
model.fit(phi(x_train), y_train)return model.predict(phi(x_test))
= lambda x: x.reshape(-1, 1)
phi_linear
= lambda x, d: np.stack([x**i for i in range(1, d+1)], axis=1) phi_poly
3).shape phi_linear(x).shape, phi_poly(x,
((100, 1), (100, 3))
= 5
d
plt.plot(x, phi_poly(x, d))# add legend
fr'$x^{i+1}$' for i in range(d)], loc='best') plt.legend([
<matplotlib.legend.Legend at 0x7f88340ee580>
# Fit a linear model (identity basis)
= y_hat_basis(x, y, x, phi_linear)
y_hat_linear = y_hat_basis(x, y, x, lambda x: phi_poly(x, 2))
y_hat_poly_2 = y_hat_basis(x, y, x, lambda x: phi_poly(x, 5))
y_hat_poly_5 'o', label='data')
plt.plot(x, y, ='linear')
plt.plot(x, y_hat_linear, label='poly 2')
plt.plot(x, y_hat_poly_2, label='poly 5')
plt.plot(x, y_hat_poly_5, label='best') plt.legend(loc
<matplotlib.legend.Legend at 0x7f882f704580>
# sine basis
def phi_sine(x, d):
= [x]
out for i in range(1, d+1):
2*np.pi*x*i))
out.append(np.sin(# Append cosine
2*np.pi*x*i))
out.append(np.cos(return np.stack(out, axis=1)
# Plot sine basis
= 3
d plt.plot(x, phi_sine(x, d))
# fit sine basis model
= y_hat_basis(x, y, x, lambda x: phi_sine(x, 15))
y_hat_sine_3
'o', label='data')
plt.plot(x, y, ='linear')
plt.plot(x, y_hat_linear, label#plt.plot(x, y_hat_poly_2, label='poly 2')
#plt.plot(x, y_hat_poly_5, label='poly 5')
='sine 3')
plt.plot(x, y_hat_sine_3, label='best') plt.legend(loc
<matplotlib.legend.Legend at 0x7f882f0f3130>
# Gaussian basis
def phi_gaussian(x, d, mu, sigma):
"""
x: (n,) denotes the input
d: (int) denotes the dimension of the basis
mu: (d,) denotes the mean of the basis
sigma: (d,) denotes the standard deviation of the basis
"""
= []
out for i in range(d):
-(x-mu[i])**2 / (2*sigma[i]**2)))
out.append(np.exp(return np.stack(out, axis=1)
0.5]), 1, np.array([0.5]), np.array([0.1])) phi_gaussian(np.array([
array([[1.]])
1]), 1, np.array([0.5]), np.array([0.1])) phi_gaussian(np.array([
array([[3.72665317e-06]])
1]), 1, np.array([0.8]), np.array([0.1])) phi_gaussian(np.array([
array([[0.13533528]])
1]), 1, np.array([0.5]), np.array([4])) phi_gaussian(np.array([
array([[0.99221794]])
# Now, let us visualize the basis for different x but a single mu and sigma
= np.linspace(0, 1, 100)
x
1, np.array([0.5]), np.array([0.1]))) plt.plot(x, phi_gaussian(x,
# Now, let us plot the basis for three different mu and sigma
= 3
d = np.linspace(0, 1, d)
mu = np.ones(d) * 0.1
sigma plt.plot(x, phi_gaussian(x, d, mu, sigma))
# We are seeking coefficients for the basis functions
# Let us plot the basis functions for different coefficients
= 3
d = np.linspace(0, 1, d)
mu = np.ones(d) * 0.1
sigma = np.array([0.2, -0.1, 0.6])
coeffs @ coeffs)
plt.plot(x, phi_gaussian(x, d, mu, sigma)
# Now, let us fit a Gaussian basis model
= 5
d = np.linspace(0, 1, d)
mu = np.ones(d) * 0.1
sigma = y_hat_basis(x, y, x, lambda x: phi_gaussian(x, d, mu, sigma))
y_hat_gaussian_5 'o', label='data')
plt.plot(x, y, ='linear')
plt.plot(x, y_hat_linear, label#plt.plot(x, y_hat_poly_2, label='poly 2')
#plt.plot(x, y_hat_poly_5, label='poly 5')
='sine 1')
plt.plot(x, y_hat_sine_3, label='gaussian 5')
plt.plot(x, y_hat_gaussian_5, label='best') plt.legend(loc
<matplotlib.legend.Legend at 0x7f882ed85c70>
# Now, let us visualize the different Gaussian basis functions and their coefficients
= 5
d = np.linspace(0, 1, d)
mu = np.ones(d) * 0.1
sigma
= phi_gaussian(x, d, mu, sigma)
X plt.plot(x, X)
= LinearRegression()
lr
lr.fit(X, y) lr.coef_, lr.intercept_
(array([-0.03558785, -0.09144039, -0.92094484, -0.32654565, 0.75825773]),
1.0918335515196196)
# Plot the predictions
'o', label='data')
plt.plot(x, y, ='gaussian 5')
plt.plot(x, lr.predict(X), label='best') plt.legend(loc
<matplotlib.legend.Legend at 0x7f882eb83040>
# Plot each of the scaled basis functions (scaling by the coefficients)
for i in range(d):
* X[:, i], label=f'basis {i} coefficient {lr.coef_[i]:.2f}')
plt.plot(x, lr.coef_[i]
'o', label='data')
plt.plot(x, y, ='gaussian 5', lw = 5)
plt.plot(x, lr.predict(X), label
# Legend outside the plot
='center left', bbox_to_anchor=(1, 0.5))
plt.legend(loc
<matplotlib.legend.Legend at 0x7f882e8b6cd0>
# plot high degree Gaussian basis
= 15
d = np.linspace(0, 1, d)
mu = np.ones(d) * 0.1
sigma
= lambda x: phi_gaussian(x, d, mu, sigma)
fit_phi_gaussian = y_hat_basis(x, y, x, fit_phi_gaussian)
y_hat_gaussian_15 'o', label='data', alpha=0.1)
plt.plot(x, y,
='gaussian 5')
plt.plot(x, y_hat_gaussian_5, label='gaussian 15')
plt.plot(x, y_hat_gaussian_15, label
= 30
d = np.linspace(0, 1, d)
mu = np.ones(d) * 0.1
sigma
= lambda x: phi_gaussian(x, d, mu, sigma)
fit_phi_gaussian = y_hat_basis(x, y, x, fit_phi_gaussian)
y_hat_gaussian_30
='gaussian 30')
plt.plot(x, y_hat_gaussian_30, label='best') plt.legend(loc
<matplotlib.legend.Legend at 0x7f882e085c10>