Path: blob/main/C2 - Advanced Learning Algorithms/week3/C2W3A1/assigment_utils.py
3520 views
"""1assignment_utils.py2contains routines used by C2_W3 Assignments3"""4import copy5import math6import numpy as np7import matplotlib.pyplot as plt8import matplotlib as mpl9from matplotlib.patches import FancyArrowPatch10from matplotlib.colors import ListedColormap, LinearSegmentedColormap11from matplotlib.widgets import Button, CheckButtons12from sklearn.linear_model import LinearRegression, Ridge13from sklearn.preprocessing import StandardScaler, PolynomialFeatures14from sklearn.metrics import mean_squared_error15from sklearn.model_selection import train_test_split16from sklearn.datasets import make_blobs1718from ipywidgets import Output19np.set_printoptions(precision=2)2021dlc = dict(dlblue = '#0096ff', dlorange = '#FF9300', dldarkred='#C00000', dlmagenta='#FF40FF', dlpurple='#7030A0', dldarkblue = '#0D5BDC')22dlblue = '#0096ff'; dlorange = '#FF9300'; dldarkred='#C00000'; dlmagenta='#FF40FF'; dlpurple='#7030A0'; dldarkblue = '#0D5BDC'23dlcolors = [dlblue, dlorange, dldarkred, dlmagenta, dlpurple]24plt.style.use('./deeplearning.mplstyle')2526# --- Assignment ----------------------------------------27def gen_data(m, seed=1, scale=0.7):28""" generate a data set based on a x^2 with added noise """29c = 030x_train = np.linspace(0,49,m)31np.random.seed(seed)32y_ideal = x_train**2 + c33y_train = y_ideal + scale * y_ideal*(np.random.sample((m,))-0.5)34x_ideal = x_train #for redraw when new data included in X35return x_train, y_train, x_ideal, y_ideal3637def gen_blobs():38classes = 639m = 80040std = 0.441centers = np.array([[-1, 0], [1, 0], [0, 1], [0, -1], [-2,1],[-2,-1]])42X, y = make_blobs(n_samples=m, centers=centers, cluster_std=std, random_state=2, n_features=2)43return (X, y, centers, classes, std)4445class lin_model:46def __init__(self, degree, regularization = False, lambda_=0):47if regularization:48self.linear_model = Ridge(alpha=lambda_)49else:50self.linear_model = LinearRegression()51self.poly = PolynomialFeatures(degree, include_bias=False)52self.scaler = StandardScaler()5354def fit(self, X_train,y_train):55''' just fits the data. mapping and scaling are not repeated '''56X_train_mapped = self.poly.fit_transform(X_train.reshape(-1,1))57X_train_mapped_scaled = self.scaler.fit_transform(X_train_mapped)58self.linear_model.fit(X_train_mapped_scaled, y_train )5960def predict(self, X):61X_mapped = self.poly.transform(X.reshape(-1,1))62X_mapped_scaled = self.scaler.transform(X_mapped)63yhat = self.linear_model.predict(X_mapped_scaled)64return(yhat)6566def mse(self, y, yhat):67err = mean_squared_error(y,yhat)/2 #sklean doesn't have div by 268return (err)6970def plt_train_test(X_train, y_train, X_test, y_test, x, y_pred, x_ideal, y_ideal, degree):71fig, ax = plt.subplots(1,1, figsize=(4,4))72fig.canvas.toolbar_visible = False73fig.canvas.header_visible = False74fig.canvas.footer_visible = False7576ax.set_title("Poor Performance on Test Data",fontsize = 12)77ax.set_xlabel("x")78ax.set_ylabel("y")7980ax.scatter(X_train, y_train, color = "red", label="train")81ax.scatter(X_test, y_test, color = dlc["dlblue"], label="test")82ax.set_xlim(ax.get_xlim())83ax.set_ylim(ax.get_ylim())84ax.plot(x, y_pred, lw=0.5, label=f"predicted, degree={degree}")85ax.plot(x_ideal, y_ideal, "--", color = "orangered", label="y_ideal", lw=1)86ax.legend(loc='upper left')87plt.tight_layout()88plt.show()8990def plt_optimal_degree(X_train, y_train, X_cv, y_cv, x, y_pred, x_ideal, y_ideal, err_train, err_cv, optimal_degree, max_degree):91fig, ax = plt.subplots(1,2,figsize=(8,4))92fig.canvas.toolbar_visible = False93fig.canvas.header_visible = False94fig.canvas.footer_visible = False9596ax[0].set_title("predictions vs data",fontsize = 12)97ax[0].set_xlabel("x")98ax[0].set_ylabel("y")99100ax[0].plot(x_ideal, y_ideal, "--", color = "orangered", label="y_ideal", lw=1)101ax[0].scatter(X_train, y_train, color = "red", label="train")102ax[0].scatter(X_cv, y_cv, color = dlc["dlorange"], label="cv")103ax[0].set_xlim(ax[0].get_xlim())104ax[0].set_ylim(ax[0].get_ylim())105for i in range(0,max_degree):106ax[0].plot(x, y_pred[:,i], lw=0.5, label=f"{i+1}")107ax[0].legend(loc='upper left')108109ax[1].set_title("error vs degree",fontsize = 12)110cpts = list(range(1, max_degree+1))111ax[1].plot(cpts, err_train[0:], marker='o',label="train error", lw=2, color = dlc["dlblue"])112ax[1].plot(cpts, err_cv[0:], marker='o',label="cv error", lw=2, color = dlc["dlorange"])113ax[1].set_ylim(*ax[1].get_ylim())114ax[1].axvline(optimal_degree, lw=1, color = dlc["dlmagenta"])115ax[1].annotate("optimal degree", xy=(optimal_degree,80000),xycoords='data',116xytext=(0.3, 0.8), textcoords='axes fraction', fontsize=10,117arrowprops=dict(arrowstyle="->", connectionstyle="arc3",118color=dlc['dldarkred'], lw=1))119ax[1].set_xlabel("degree")120ax[1].set_ylabel("error")121ax[1].legend()122fig.suptitle("Find Optimal Degree",fontsize = 12)123plt.tight_layout()124125plt.show()126127def plt_tune_regularization(X_train, y_train, X_cv, y_cv, x, y_pred, err_train, err_cv, optimal_reg_idx, lambda_range):128fig, ax = plt.subplots(1,2,figsize=(8,4))129fig.canvas.toolbar_visible = False130fig.canvas.header_visible = False131fig.canvas.footer_visible = False132133ax[0].set_title("predictions vs data",fontsize = 12)134ax[0].set_xlabel("x")135ax[0].set_ylabel("y")136137ax[0].scatter(X_train, y_train, color = "red", label="train")138ax[0].scatter(X_cv, y_cv, color = dlc["dlorange"], label="cv")139ax[0].set_xlim(ax[0].get_xlim())140ax[0].set_ylim(ax[0].get_ylim())141# ax[0].plot(x, y_pred[:,:], lw=0.5, label=[f"$\lambda =${i}" for i in lambda_range])142for i in (0,3,7,9):143ax[0].plot(x, y_pred[:,i], lw=0.5, label=f"$\lambda =${lambda_range[i]}")144ax[0].legend()145146ax[1].set_title("error vs regularization",fontsize = 12)147ax[1].plot(lambda_range, err_train[:], label="train error", color = dlc["dlblue"])148ax[1].plot(lambda_range, err_cv[:], label="cv error", color = dlc["dlorange"])149ax[1].set_xscale('log')150ax[1].set_ylim(*ax[1].get_ylim())151opt_x = lambda_range[optimal_reg_idx]152ax[1].vlines(opt_x, *ax[1].get_ylim(), color = "black", lw=1)153ax[1].annotate("optimal lambda", (opt_x,150000), xytext=(-80,10), textcoords="offset points",154arrowprops={'arrowstyle':'simple'})155ax[1].set_xlabel("regularization (lambda)")156ax[1].set_ylabel("error")157fig.suptitle("Tuning Regularization",fontsize = 12)158ax[1].text(0.05,0.44,"High\nVariance",fontsize=12, ha='left',transform=ax[1].transAxes,color = dlc["dlblue"])159ax[1].text(0.95,0.44,"High\nBias", fontsize=12, ha='right',transform=ax[1].transAxes,color = dlc["dlblue"])160ax[1].legend(loc='upper left')161plt.tight_layout()162plt.show()163164def tune_m():165""" tune the number of examples to reduce overfitting """166m = 50167m_range = np.array(m*np.arange(1,16))168num_steps = m_range.shape[0]169degree = 16170err_train = np.zeros(num_steps)171err_cv = np.zeros(num_steps)172y_pred = np.zeros((100,num_steps))173174for i in range(num_steps):175X, y, y_ideal, x_ideal = gen_data(m_range[i],5,0.7)176x = np.linspace(0,int(X.max()),100)177X_train, X_, y_train, y_ = train_test_split(X,y,test_size=0.40, random_state=1)178X_cv, X_test, y_cv, y_test = train_test_split(X_,y_,test_size=0.50, random_state=1)179180lmodel = lin_model(degree) # no regularization181lmodel.fit(X_train, y_train)182yhat = lmodel.predict(X_train)183err_train[i] = lmodel.mse(y_train, yhat)184yhat = lmodel.predict(X_cv)185err_cv[i] = lmodel.mse(y_cv, yhat)186y_pred[:,i] = lmodel.predict(x)187return(X_train, y_train, X_cv, y_cv, x, y_pred, err_train, err_cv, m_range,degree)188189def plt_tune_m(X_train, y_train, X_cv, y_cv, x, y_pred, err_train, err_cv, m_range, degree):190191fig, ax = plt.subplots(1,2,figsize=(8,4))192fig.canvas.toolbar_visible = False193fig.canvas.header_visible = False194fig.canvas.footer_visible = False195196ax[0].set_title("predictions vs data",fontsize = 12)197ax[0].set_xlabel("x")198ax[0].set_ylabel("y")199200ax[0].scatter(X_train, y_train, color = "red", s=3, label="train", alpha=0.4)201ax[0].scatter(X_cv, y_cv, color = dlc["dlorange"], s=3, label="cv", alpha=0.4)202ax[0].set_xlim(ax[0].get_xlim())203ax[0].set_ylim(ax[0].get_ylim())204for i in range(0,len(m_range),3):205ax[0].plot(x, y_pred[:,i], lw=1, label=f"$m =${m_range[i]}")206ax[0].legend(loc='upper left')207ax[0].text(0.05,0.5,f"degree = {degree}", fontsize=10, ha='left',transform=ax[0].transAxes,color = dlc["dlblue"])208209ax[1].set_title("error vs number of examples",fontsize = 12)210ax[1].plot(m_range, err_train[:], label="train error", color = dlc["dlblue"])211ax[1].plot(m_range, err_cv[:], label="cv error", color = dlc["dlorange"])212ax[1].set_xlabel("Number of Examples (m)")213ax[1].set_ylabel("error")214fig.suptitle("Tuning number of examples",fontsize = 12)215ax[1].text(0.05,0.5,"High\nVariance", fontsize=12, ha='left',transform=ax[1].transAxes,color = dlc["dlblue"])216ax[1].text(0.95,0.5,"Good \nGeneralization", fontsize=12, ha='right',transform=ax[1].transAxes,color = dlc["dlblue"])217ax[1].legend()218plt.tight_layout()219plt.show()220221dkcolors = plt.cm.Paired((1,3,7,9,5,11))222ltcolors = plt.cm.Paired((0,2,6,8,4,10))223dkcolors_map = mpl.colors.ListedColormap(dkcolors)224ltcolors_map = mpl.colors.ListedColormap(ltcolors)225226def plt_mc_data(ax, X, y, classes, class_labels=None, map=plt.cm.Paired, legend=False,size=50, m='o'):227for i in range(classes):228idx = np.where(y == i)229col = len(idx[0])*[i]230label = class_labels[i] if class_labels else "c{}".format(i)231ax.scatter(X[idx, 0], X[idx, 1], marker=m,232c=col, vmin=0, vmax=map.N, cmap=map,233s=size, label=label)234if legend: ax.legend()235ax.axis('equal')236237238#Plot a multi-class categorical decision boundary239# This version handles a non-vector prediction (adds a for-loop over points)240def plot_cat_decision_boundary(ax, X,predict , class_labels=None, legend=False, vector=True, color='g', lw = 1):241242# create a mesh to points to plot243pad = 0.5244x_min, x_max = X[:, 0].min() - pad, X[:, 0].max() + pad245y_min, y_max = X[:, 1].min() - pad, X[:, 1].max() + pad246h = max(x_max-x_min, y_max-y_min)/200247xx, yy = np.meshgrid(np.arange(x_min, x_max, h),248np.arange(y_min, y_max, h))249points = np.c_[xx.ravel(), yy.ravel()]250#print("points", points.shape)251#make predictions for each point in mesh252if vector:253Z = predict(points)254else:255Z = np.zeros((len(points),))256for i in range(len(points)):257Z[i] = predict(points[i].reshape(1,2))258Z = Z.reshape(xx.shape)259260#contour plot highlights boundaries between values - classes in this case261ax.contour(xx, yy, Z, colors=color, linewidths=lw)262ax.axis('tight')263264def recat(pt, origins):265""" categorize a point based on distance from origin of clusters """266nclusters = len(origins)267min_dist = 10000268y_new = None269for j in range(nclusters):270temp = origins[j] - pt.reshape(2,)271#print(temp.shape,origins[j].shape)272dist = np.sqrt(np.dot(temp.T, temp))273if dist < min_dist:274y_new = j275min_dist = dist276return(y_new)277278def plt_train_eq_dist(X_train,y_train,classes, X_cv, y_cv, centers, std):279css = np.unique(y_train)280fig,ax = plt.subplots(1,2,figsize=(8,4))281fig.canvas.toolbar_visible = False282fig.canvas.header_visible = False283fig.canvas.footer_visible = False284plt_mc_data(ax[0], X_train,y_train,classes, map=dkcolors_map, legend=True, size=50)285plt_mc_data(ax[0], X_cv, y_cv, classes, map=ltcolors_map, legend=True, m="<")286ax[0].set_title("Training, CV Data")287for c in css:288circ = plt.Circle(centers[c], 2*std, color=dkcolors_map(c), clip_on=False, fill=False, lw=0.5)289ax[0].add_patch(circ)290291292#make a model for plotting routines to call293cat_predict = lambda pt: recat(pt.reshape(1,2), centers)294plot_cat_decision_boundary(ax[1], X_train, cat_predict, vector=False, color = dlc["dlmagenta"], lw=0.75)295ax[1].set_title("ideal performance", fontsize=14)296297#add the original data to the decison boundary298plt_mc_data(ax[1], X_train,y_train, classes, map=dkcolors_map, legend=True, size=50)299ax[1].set_xlabel('x0') ; ax[1].set_ylabel("x1");300plt.show()301302303def plt_nn(model_predict,X_train,y_train, classes, X_cv, y_cv, suptitle=""):304#plot the decison boundary.305fig,ax = plt.subplots(1,2, figsize=(8,4))306fig.canvas.toolbar_visible = False307fig.canvas.header_visible = False308fig.canvas.footer_visible = False309plot_cat_decision_boundary(ax[0], X_train, model_predict, vector=True)310ax[0].set_title("training data", fontsize=14)311312#add the original data to the decison boundary313plt_mc_data(ax[0], X_train,y_train, classes, map=dkcolors_map, legend=True, size=75)314ax[0].set_xlabel('x0') ; ax[0].set_ylabel("x1");315316plot_cat_decision_boundary(ax[1], X_train, model_predict, vector=True)317ax[1].set_title("cross-validation data", fontsize=14)318plt_mc_data(ax[1], X_cv,y_cv, classes,319map=ltcolors_map, legend=True, size=100, m='<')320ax[1].set_xlabel('x0') ; ax[1].set_ylabel("x1");321fig.suptitle(suptitle,fontsize = 12)322plt.show()323324325def eval_cat_err(y, yhat):326"""327Calculate the categorization error328Args:329y : (ndarray Shape (m,) or (m,1)) target value of each example330yhat : (ndarray Shape (m,) or (m,1)) predicted value of each example331Returns:|332err: (scalar)333"""334m = len(y)335incorrect = 0336for i in range(m):337if yhat[i] != y[i]:338incorrect += 1339err = incorrect/m340return(err)341342def plot_iterate(lambdas, models, X_train, y_train, X_cv, y_cv):343err_train = np.zeros(len(lambdas))344err_cv = np.zeros(len(lambdas))345for i in range(len(models)):346err_train[i] = eval_cat_err(y_train,np.argmax( models[i](X_train), axis=1))347err_cv[i] = eval_cat_err(y_cv, np.argmax( models[i](X_cv), axis=1))348349fig, ax = plt.subplots(1,1,figsize=(6,4))350fig.canvas.toolbar_visible = False351fig.canvas.header_visible = False352fig.canvas.footer_visible = False353ax.set_title("error vs regularization",fontsize = 12)354ax.plot(lambdas, err_train, marker='o', label="train error", color = dlc["dlblue"])355ax.plot(lambdas, err_cv, marker='o', label="cv error", color = dlc["dlorange"])356ax.set_xscale('log')357ax.set_ylim(*ax.get_ylim())358ax.set_xlabel("Regularization (lambda)",fontsize = 14)359ax.set_ylabel("Error",fontsize = 14)360ax.legend()361fig.suptitle("Tuning Regularization",fontsize = 14)362ax.text(0.05,0.14,"Training Error\nlower than CV",fontsize=12, ha='left',transform=ax.transAxes,color = dlc["dlblue"])363ax.text(0.95,0.14,"Similar\nTraining, CV", fontsize=12, ha='right',transform=ax.transAxes,color = dlc["dlblue"])364plt.show()365366# not used but will calculate the erro assuming an equal distance367def err_all_equal(X_train,X_cv,X_test, y_train,y_cv,y_test, centers):368X_all = np.concatenate((X_train,X_cv,X_test), axis=0)369y_all = np.concatenate((y_train,y_cv,y_test), axis=0)370m = len(X_all)371y_eq = np.zeros(m)372for i in range(m):373y_eq[i] = recat(X_all[i], centers)374err_all = eval_cat_err(y_all, y_eq)375return(err_all)376377def plt_compare(X,y, classes, simple, regularized, centers):378plt.close("all")379fig,ax = plt.subplots(1,3, figsize=(8,3))380fig.canvas.toolbar_visible = False381fig.canvas.header_visible = False382fig.canvas.footer_visible = False383384#plt simple385plot_cat_decision_boundary(ax[0], X, simple, vector=True)386ax[0].set_title("Simple Model", fontsize=14)387plt_mc_data(ax[0], X,y, classes, map=dkcolors_map, legend=True, size=75)388ax[0].set_xlabel('x0') ; ax[0].set_ylabel("x1");389390#plt regularized391plot_cat_decision_boundary(ax[1], X, regularized, vector=True)392ax[1].set_title("Regularized Model", fontsize=14)393plt_mc_data(ax[1], X,y, classes, map=dkcolors_map, legend=True, size=75)394ax[1].set_xlabel('x0') ; ax[0].set_ylabel("x1");395396#plt ideal397cat_predict = lambda pt: recat(pt.reshape(1,2), centers)398plot_cat_decision_boundary(ax[2], X, cat_predict, vector=False)399ax[2].set_title("Ideal Model", fontsize=14)400plt_mc_data(ax[2], X,y, classes, map=dkcolors_map, legend=True, size=75)401ax[2].set_xlabel('x0') ; ax[0].set_ylabel("x1");402403err_s = eval_cat_err(y, simple(X))404err_r = eval_cat_err(y, regularized(X))405ax[0].text(-2.75,3,f"err_test={err_s:0.2f}", fontsize=12)406ax[1].text(-2.75,3,f"err_test={err_r:0.2f}", fontsize=12)407m = len(X)408y_eq = np.zeros(m)409for i in range(m):410y_eq[i] = recat(X[i], centers)411err_eq = eval_cat_err(y, y_eq)412ax[2].text(-2.75,3,f"err_test={err_eq:0.2f}", fontsize=12)413plt.show()414415# --- End Assignment ----------------------------------------416417418