165 lines
5.1 KiB
Python
165 lines
5.1 KiB
Python
import sys
|
|
import numpy as np
|
|
from scipy import optimize
|
|
from matplotlib import pyplot
|
|
|
|
sys.path.append('..')
|
|
from submission import SubmissionBase
|
|
|
|
|
|
def trainLinearReg(linearRegCostFunction, X, y, lambda_=0.0, maxiter=200):
|
|
"""
|
|
Trains linear regression using scipy's optimize.minimize.
|
|
|
|
Parameters
|
|
----------
|
|
X : array_like
|
|
The dataset with shape (m x n+1). The bias term is assumed to be concatenated.
|
|
|
|
y : array_like
|
|
Function values at each datapoint. A vector of shape (m,).
|
|
|
|
lambda_ : float, optional
|
|
The regularization parameter.
|
|
|
|
maxiter : int, optional
|
|
Maximum number of iteration for the optimization algorithm.
|
|
|
|
Returns
|
|
-------
|
|
theta : array_like
|
|
The parameters for linear regression. This is a vector of shape (n+1,).
|
|
"""
|
|
# Initialize Theta
|
|
initial_theta = np.zeros(X.shape[1])
|
|
|
|
# Create "short hand" for the cost function to be minimized
|
|
costFunction = lambda t: linearRegCostFunction(X, y, t, lambda_)
|
|
|
|
# Now, costFunction is a function that takes in only one argument
|
|
options = {'maxiter': maxiter}
|
|
|
|
# Minimize using scipy
|
|
res = optimize.minimize(costFunction, initial_theta, jac=True, method='TNC', options=options)
|
|
return res.x
|
|
|
|
|
|
def featureNormalize(X):
|
|
"""
|
|
Normalizes the features in X returns a normalized version of X where the mean value of each
|
|
feature is 0 and the standard deviation is 1. This is often a good preprocessing step to do when
|
|
working with learning algorithms.
|
|
|
|
Parameters
|
|
----------
|
|
X : array_like
|
|
An dataset which is a (m x n) matrix, where m is the number of examples,
|
|
and n is the number of dimensions for each example.
|
|
|
|
Returns
|
|
-------
|
|
X_norm : array_like
|
|
The normalized input dataset.
|
|
|
|
mu : array_like
|
|
A vector of size n corresponding to the mean for each dimension across all examples.
|
|
|
|
sigma : array_like
|
|
A vector of size n corresponding to the standard deviations for each dimension across
|
|
all examples.
|
|
"""
|
|
mu = np.mean(X, axis=0)
|
|
X_norm = X - mu
|
|
|
|
sigma = np.std(X_norm, axis=0, ddof=1)
|
|
X_norm /= sigma
|
|
return X_norm, mu, sigma
|
|
|
|
|
|
def plotFit(polyFeatures, min_x, max_x, mu, sigma, theta, p):
|
|
"""
|
|
Plots a learned polynomial regression fit over an existing figure.
|
|
Also works with linear regression.
|
|
Plots the learned polynomial fit with power p and feature normalization (mu, sigma).
|
|
|
|
Parameters
|
|
----------
|
|
polyFeatures : func
|
|
A function which generators polynomial features from a single feature.
|
|
|
|
min_x : float
|
|
The minimum value for the feature.
|
|
|
|
max_x : float
|
|
The maximum value for the feature.
|
|
|
|
mu : float
|
|
The mean feature value over the training dataset.
|
|
|
|
sigma : float
|
|
The feature standard deviation of the training dataset.
|
|
|
|
theta : array_like
|
|
The parameters for the trained polynomial linear regression.
|
|
|
|
p : int
|
|
The polynomial order.
|
|
"""
|
|
# We plot a range slightly bigger than the min and max values to get
|
|
# an idea of how the fit will vary outside the range of the data points
|
|
x = np.arange(min_x - 15, max_x + 25, 0.05).reshape(-1, 1)
|
|
|
|
# Map the X values
|
|
X_poly = polyFeatures(x, p)
|
|
X_poly -= mu
|
|
X_poly /= sigma
|
|
|
|
# Add ones
|
|
X_poly = np.concatenate([np.ones((x.shape[0], 1)), X_poly], axis=1)
|
|
|
|
# Plot
|
|
pyplot.plot(x, np.dot(X_poly, theta), '--', lw=2)
|
|
|
|
|
|
class Grader(SubmissionBase):
|
|
# Random test cases
|
|
X = np.vstack([np.ones(10),
|
|
np.sin(np.arange(1, 15, 1.5)),
|
|
np.cos(np.arange(1, 15, 1.5))]).T
|
|
y = np.sin(np.arange(1, 31, 3))
|
|
Xval = np.vstack([np.ones(10),
|
|
np.sin(np.arange(0, 14, 1.5)),
|
|
np.cos(np.arange(0, 14, 1.5))]).T
|
|
yval = np.sin(np.arange(1, 11))
|
|
|
|
def __init__(self):
|
|
part_names = ['Regularized Linear Regression Cost Function',
|
|
'Regularized Linear Regression Gradient',
|
|
'Learning Curve',
|
|
'Polynomial Feature Mapping',
|
|
'Validation Curve']
|
|
super().__init__('regularized-linear-regression-and-bias-variance', part_names)
|
|
|
|
def __iter__(self):
|
|
for part_id in range(1, 6):
|
|
try:
|
|
func = self.functions[part_id]
|
|
# Each part has different expected arguments/different function
|
|
if part_id == 1:
|
|
res = func(self.X, self.y, np.array([0.1, 0.2, 0.3]), 0.5)
|
|
elif part_id == 2:
|
|
theta = np.array([0.1, 0.2, 0.3])
|
|
res = func(self.X, self.y, theta, 0.5)[1]
|
|
elif part_id == 3:
|
|
res = np.hstack(func(self.X, self.y, self.Xval, self.yval, 1)).tolist()
|
|
elif part_id == 4:
|
|
res = func(self.X[1, :].reshape(-1, 1), 8)
|
|
elif part_id == 5:
|
|
res = np.hstack(func(self.X, self.y, self.Xval, self.yval)).tolist()
|
|
else:
|
|
raise KeyError
|
|
except KeyError:
|
|
yield part_id, 0
|
|
yield part_id, res
|
|
|