%matplotlib inline
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from Data import Data
from LinearModel import LinearModel
Create 20 data points with a 10/10 train/test split.
X values are uniform in the interval [0,1]
See Data.py for Y values and noise generation.
data = Data(20)
Generate and train 10 models, 1 for each degree from [0,9]
Model weights are calculated using scikit-learn. See LinearModel.py
models = [LinearModel(x) for x in range(10)]
for model in models:
model.train(data)
Print the weights for models with degrees ${0, 1, 3, 9}$
orders = [0, 1, 3, 9]
weights = pd.DataFrame()
for order in orders:
temp = pd.DataFrame({f'M={order}': models[order].weights})
weights = pd.concat([weights, temp], axis=1)
weights.round(2).fillna('')
Plot models with degrees ${0, 1, 3, 9}$
fig, ax = plt.subplots(2, 2)
for i, order in enumerate(orders):
models[order].plot(ax[i // 2][ i % 2], data)
plt.show()
Notice the plot for $M = 9$ being overfit.
Plot the RMS error for each model
train_errors = []
test_errors = []
degrees = list(range(len(models)))
for model in models:
train_errors.append(model.error(data.X_train, data.Y_train))
test_errors.append(model.error(data.X_test, data.Y_test))
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(degrees, train_errors, color='blue', marker='o', markerfacecolor='none', label='Training')
ax.plot(degrees, test_errors, color='red', marker='o', markerfacecolor='none', label='Testing')
ax.set_ylabel('Erms')
ax.set_xlabel('M')
ax.legend(loc='upper left')
plt.show()
Generate 200 new data points and fit 9th degree model using 100 train data points.
data_big = Data(200)
model9 = LinearModel(9)
model9.train(data_big)
fig, ax = plt.subplots()
model9.plot(ax, data_big)
plt.title('N = 100')
plt.show()
Notice that this model does not seem overfit.
Train 6 new models using regularization with $λ \in {1, 1/10, 1/100, 1/1000, 1/10000, 1/100000}$
hyper_parameters = list(10 ** -x for x in range(6))
models = [LinearModel(9, hp) for hp in hyper_parameters]
for model in models:
model.train(data)
for i, hp in enumerate(hyper_parameters):
fig, ax = plt.subplots()
models[i].plot(ax, data)
plt.title(f'λ = 1/{1/hp:.0f}')
plt.show()
Train some new models using hyper parameters such that $ln(λ) \in [-30, -5]$
hyper_parameters = np.arange(-30,-4)
models = [LinearModel(9, np.exp(hp)) for hp in hyper_parameters]
for model in models:
model.train(data)
Plot train and test error for these new models.
train_errors = []
test_errors = []
for model in models:
train_errors.append(model.error(data.X_train, data.Y_train))
test_errors.append(model.error(data.X_test, data.Y_test))
fig = plt.figure()
ax = fig.add_subplot(1, 1, 1)
ax.plot(hyper_parameters, train_errors, color='blue', label='Training')
ax.plot(hyper_parameters, test_errors, color='red', label='Testing')
ax.set_ylabel('Erms')
ax.set_xlabel('ln λ')
ax.legend(loc='upper left')
plt.show()
Find the model with lowest test error.
min_index = np.argmin(test_errors)
best_model = models[min_index]
with np.printoptions(precision=3, suppress=True):
print(f'Based on the test performance, the best model with degree 9 is ln λ = {np.log(best_model.hyper_parameter)}')
print(f'Weights: {best_model.weights}')
Plot the best model found above.
fig, ax = plt.subplots()
best_model.plot(ax, data)
plt.title('Best Model')
plt.show()