Path: blob/main/C1 - Supervised Machine Learning - Regression and Classification/week1/Optional Labs/lab_utils_uni.py
2201 views
"""1lab_utils_uni.py2routines used in Course 1, Week2, labs1-3 dealing with single variables (univariate)3"""4import numpy as np5import matplotlib.pyplot as plt6from matplotlib.ticker import MaxNLocator7from matplotlib.gridspec import GridSpec8from matplotlib.colors import LinearSegmentedColormap9from ipywidgets import interact10from lab_utils_common import compute_cost11from lab_utils_common import dlblue, dlorange, dldarkred, dlmagenta, dlpurple, dlcolors1213plt.style.use('./deeplearning.mplstyle')14n_bin = 515dlcm = LinearSegmentedColormap.from_list(16'dl_map', dlcolors, N=n_bin)1718##########################################################19# Plotting Routines20##########################################################2122def plt_house_x(X, y,f_wb=None, ax=None):23''' plot house with aXis '''24if not ax:25fig, ax = plt.subplots(1,1)26ax.scatter(X, y, marker='x', c='r', label="Actual Value")2728ax.set_title("Housing Prices")29ax.set_ylabel('Price (in 1000s of dollars)')30ax.set_xlabel(f'Size (1000 sqft)')31if f_wb is not None:32ax.plot(X, f_wb, c=dlblue, label="Our Prediction")33ax.legend()343536def mk_cost_lines(x,y,w,b, ax):37''' makes vertical cost lines'''38cstr = "cost = (1/m)*("39ctot = 040label = 'cost for point'41addedbreak = False42for p in zip(x,y):43f_wb_p = w*p[0]+b44c_p = ((f_wb_p - p[1])**2)/245c_p_txt = c_p46ax.vlines(p[0], p[1],f_wb_p, lw=3, color=dlpurple, ls='dotted', label=label)47label='' #just one48cxy = [p[0], p[1] + (f_wb_p-p[1])/2]49ax.annotate(f'{c_p_txt:0.0f}', xy=cxy, xycoords='data',color=dlpurple,50xytext=(5, 0), textcoords='offset points')51cstr += f"{c_p_txt:0.0f} +"52if len(cstr) > 38 and addedbreak is False:53cstr += "\n"54addedbreak = True55ctot += c_p56ctot = ctot/(len(x))57cstr = cstr[:-1] + f") = {ctot:0.0f}"58ax.text(0.15,0.02,cstr, transform=ax.transAxes, color=dlpurple)5960##########61# Cost lab62##########636465def plt_intuition(x_train, y_train):6667w_range = np.array([200-200,200+200])68tmp_b = 1006970w_array = np.arange(*w_range, 5)71cost = np.zeros_like(w_array)72for i in range(len(w_array)):73tmp_w = w_array[i]74cost[i] = compute_cost(x_train, y_train, tmp_w, tmp_b)7576@interact(w=(*w_range,10),continuous_update=False)77def func( w=150):78f_wb = np.dot(x_train, w) + tmp_b7980fig, ax = plt.subplots(1, 2, constrained_layout=True, figsize=(8,4))81fig.canvas.toolbar_position = 'bottom'8283mk_cost_lines(x_train, y_train, w, tmp_b, ax[0])84plt_house_x(x_train, y_train, f_wb=f_wb, ax=ax[0])8586ax[1].plot(w_array, cost)87cur_cost = compute_cost(x_train, y_train, w, tmp_b)88ax[1].scatter(w,cur_cost, s=100, color=dldarkred, zorder= 10, label= f"cost at w={w}")89ax[1].hlines(cur_cost, ax[1].get_xlim()[0],w, lw=4, color=dlpurple, ls='dotted')90ax[1].vlines(w, ax[1].get_ylim()[0],cur_cost, lw=4, color=dlpurple, ls='dotted')91ax[1].set_title("Cost vs. w, (b fixed at 100)")92ax[1].set_ylabel('Cost')93ax[1].set_xlabel('w')94ax[1].legend(loc='upper center')95fig.suptitle(f"Minimize Cost: Current Cost = {cur_cost:0.0f}", fontsize=12)96plt.show()9798# this is the 2D cost curve with interactive slider99def plt_stationary(x_train, y_train):100# setup figure101fig = plt.figure( figsize=(9,8))102#fig = plt.figure(constrained_layout=True, figsize=(12,10))103fig.set_facecolor('#ffffff') #white104fig.canvas.toolbar_position = 'top'105#gs = GridSpec(2, 2, figure=fig, wspace = 0.01)106gs = GridSpec(2, 2, figure=fig)107ax0 = fig.add_subplot(gs[0, 0])108ax1 = fig.add_subplot(gs[0, 1])109ax2 = fig.add_subplot(gs[1, :], projection='3d')110ax = np.array([ax0,ax1,ax2])111112#setup useful ranges and common linspaces113w_range = np.array([200-300.,200+300])114b_range = np.array([50-300., 50+300])115b_space = np.linspace(*b_range, 100)116w_space = np.linspace(*w_range, 100)117118# get cost for w,b ranges for contour and 3D119tmp_b,tmp_w = np.meshgrid(b_space,w_space)120z=np.zeros_like(tmp_b)121for i in range(tmp_w.shape[0]):122for j in range(tmp_w.shape[1]):123z[i,j] = compute_cost(x_train, y_train, tmp_w[i][j], tmp_b[i][j] )124if z[i,j] == 0: z[i,j] = 1e-6125126w0=200;b=-100 #initial point127### plot model w cost ###128f_wb = np.dot(x_train,w0) + b129mk_cost_lines(x_train,y_train,w0,b,ax[0])130plt_house_x(x_train, y_train, f_wb=f_wb, ax=ax[0])131132### plot contour ###133CS = ax[1].contour(tmp_w, tmp_b, np.log(z),levels=12, linewidths=2, alpha=0.7,colors=dlcolors)134ax[1].set_title('Cost(w,b)')135ax[1].set_xlabel('w', fontsize=10)136ax[1].set_ylabel('b', fontsize=10)137ax[1].set_xlim(w_range) ; ax[1].set_ylim(b_range)138cscat = ax[1].scatter(w0,b, s=100, color=dlblue, zorder= 10, label="cost with \ncurrent w,b")139chline = ax[1].hlines(b, ax[1].get_xlim()[0],w0, lw=4, color=dlpurple, ls='dotted')140cvline = ax[1].vlines(w0, ax[1].get_ylim()[0],b, lw=4, color=dlpurple, ls='dotted')141ax[1].text(0.5,0.95,"Click to choose w,b", bbox=dict(facecolor='white', ec = 'black'), fontsize = 10,142transform=ax[1].transAxes, verticalalignment = 'center', horizontalalignment= 'center')143144#Surface plot of the cost function J(w,b)145ax[2].plot_surface(tmp_w, tmp_b, z, cmap = dlcm, alpha=0.3, antialiased=True)146ax[2].plot_wireframe(tmp_w, tmp_b, z, color='k', alpha=0.1)147plt.xlabel("$w$")148plt.ylabel("$b$")149ax[2].zaxis.set_rotate_label(False)150ax[2].xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))151ax[2].yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))152ax[2].zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))153ax[2].set_zlabel("J(w, b)\n\n", rotation=90)154plt.title("Cost(w,b) \n [You can rotate this figure]", size=12)155ax[2].view_init(30, -120)156157return fig,ax, [cscat, chline, cvline]158159160#https://matplotlib.org/stable/users/event_handling.html161class plt_update_onclick:162def __init__(self, fig, ax, x_train,y_train, dyn_items):163self.fig = fig164self.ax = ax165self.x_train = x_train166self.y_train = y_train167self.dyn_items = dyn_items168self.cid = fig.canvas.mpl_connect('button_press_event', self)169170def __call__(self, event):171if event.inaxes == self.ax[1]:172ws = event.xdata173bs = event.ydata174cst = compute_cost(self.x_train, self.y_train, ws, bs)175176# clear and redraw line plot177self.ax[0].clear()178f_wb = np.dot(self.x_train,ws) + bs179mk_cost_lines(self.x_train,self.y_train,ws,bs,self.ax[0])180plt_house_x(self.x_train, self.y_train, f_wb=f_wb, ax=self.ax[0])181182# remove lines and re-add on countour plot and 3d plot183for artist in self.dyn_items:184artist.remove()185186a = self.ax[1].scatter(ws,bs, s=100, color=dlblue, zorder= 10, label="cost with \ncurrent w,b")187b = self.ax[1].hlines(bs, self.ax[1].get_xlim()[0],ws, lw=4, color=dlpurple, ls='dotted')188c = self.ax[1].vlines(ws, self.ax[1].get_ylim()[0],bs, lw=4, color=dlpurple, ls='dotted')189d = self.ax[1].annotate(f"Cost: {cst:.0f}", xy= (ws, bs), xytext = (4,4), textcoords = 'offset points',190bbox=dict(facecolor='white'), size = 10)191192#Add point in 3D surface plot193e = self.ax[2].scatter3D(ws, bs,cst , marker='X', s=100)194195self.dyn_items = [a,b,c,d,e]196self.fig.canvas.draw()197198199def soup_bowl():200""" Create figure and plot with a 3D projection"""201fig = plt.figure(figsize=(8,8))202203#Plot configuration204ax = fig.add_subplot(111, projection='3d')205ax.xaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))206ax.yaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))207ax.zaxis.set_pane_color((1.0, 1.0, 1.0, 0.0))208ax.zaxis.set_rotate_label(False)209ax.view_init(45, -120)210211#Useful linearspaces to give values to the parameters w and b212w = np.linspace(-20, 20, 100)213b = np.linspace(-20, 20, 100)214215#Get the z value for a bowl-shaped cost function216z=np.zeros((len(w), len(b)))217j=0218for x in w:219i=0220for y in b:221z[i,j] = x**2 + y**2222i+=1223j+=1224225#Meshgrid used for plotting 3D functions226W, B = np.meshgrid(w, b)227228#Create the 3D surface plot of the bowl-shaped cost function229ax.plot_surface(W, B, z, cmap = "Spectral_r", alpha=0.7, antialiased=False)230ax.plot_wireframe(W, B, z, color='k', alpha=0.1)231ax.set_xlabel("$w$")232ax.set_ylabel("$b$")233ax.set_zlabel("$J(w,b)$", rotation=90)234ax.set_title("$J(w,b)$\n [You can rotate this figure]", size=15)235236plt.show()237238def inbounds(a,b,xlim,ylim):239xlow,xhigh = xlim240ylow,yhigh = ylim241ax, ay = a242bx, by = b243if (ax > xlow and ax < xhigh) and (bx > xlow and bx < xhigh) \244and (ay > ylow and ay < yhigh) and (by > ylow and by < yhigh):245return True246return False247248def plt_contour_wgrad(x, y, hist, ax, w_range=[-100, 500, 5], b_range=[-500, 500, 5],249contours = [0.1,50,1000,5000,10000,25000,50000],250resolution=5, w_final=200, b_final=100,step=10 ):251b0,w0 = np.meshgrid(np.arange(*b_range),np.arange(*w_range))252z=np.zeros_like(b0)253for i in range(w0.shape[0]):254for j in range(w0.shape[1]):255z[i][j] = compute_cost(x, y, w0[i][j], b0[i][j] )256257CS = ax.contour(w0, b0, z, contours, linewidths=2,258colors=[dlblue, dlorange, dldarkred, dlmagenta, dlpurple])259ax.clabel(CS, inline=1, fmt='%1.0f', fontsize=10)260ax.set_xlabel("w"); ax.set_ylabel("b")261ax.set_title('Contour plot of cost J(w,b), vs b,w with path of gradient descent')262w = w_final; b=b_final263ax.hlines(b, ax.get_xlim()[0],w, lw=2, color=dlpurple, ls='dotted')264ax.vlines(w, ax.get_ylim()[0],b, lw=2, color=dlpurple, ls='dotted')265266base = hist[0]267for point in hist[0::step]:268edist = np.sqrt((base[0] - point[0])**2 + (base[1] - point[1])**2)269if(edist > resolution or point==hist[-1]):270if inbounds(point,base, ax.get_xlim(),ax.get_ylim()):271plt.annotate('', xy=point, xytext=base,xycoords='data',272arrowprops={'arrowstyle': '->', 'color': 'r', 'lw': 3},273va='center', ha='center')274base=point275return276277278def plt_divergence(p_hist, J_hist, x_train,y_train):279280x=np.zeros(len(p_hist))281y=np.zeros(len(p_hist))282v=np.zeros(len(p_hist))283for i in range(len(p_hist)):284x[i] = p_hist[i][0]285y[i] = p_hist[i][1]286v[i] = J_hist[i]287288fig = plt.figure(figsize=(12,5))289plt.subplots_adjust( wspace=0 )290gs = fig.add_gridspec(1, 5)291fig.suptitle(f"Cost escalates when learning rate is too large")292#===============293# First subplot294#===============295ax = fig.add_subplot(gs[:2], )296297# Print w vs cost to see minimum298fix_b = 100299w_array = np.arange(-70000, 70000, 1000, dtype="int64")300cost = np.zeros_like(w_array,float)301302for i in range(len(w_array)):303tmp_w = w_array[i]304cost[i] = compute_cost(x_train, y_train, tmp_w, fix_b)305306ax.plot(w_array, cost)307ax.plot(x,v, c=dlmagenta)308ax.set_title("Cost vs w, b set to 100")309ax.set_ylabel('Cost')310ax.set_xlabel('w')311ax.xaxis.set_major_locator(MaxNLocator(2))312313#===============314# Second Subplot315#===============316317tmp_b,tmp_w = np.meshgrid(np.arange(-35000, 35000, 500),np.arange(-70000, 70000, 500))318tmp_b = tmp_b.astype('int64')319tmp_w = tmp_w.astype('int64')320z=np.zeros_like(tmp_b,float)321for i in range(tmp_w.shape[0]):322for j in range(tmp_w.shape[1]):323z[i][j] = compute_cost(x_train, y_train, tmp_w[i][j], tmp_b[i][j] )324325ax = fig.add_subplot(gs[2:], projection='3d')326ax.plot_surface(tmp_w, tmp_b, z, alpha=0.3, color=dlblue)327ax.xaxis.set_major_locator(MaxNLocator(2))328ax.yaxis.set_major_locator(MaxNLocator(2))329330ax.set_xlabel('w', fontsize=16)331ax.set_ylabel('b', fontsize=16)332ax.set_zlabel('\ncost', fontsize=16)333plt.title('Cost vs (b, w)')334# Customize the view angle335ax.view_init(elev=20., azim=-65)336ax.plot(x, y, v,c=dlmagenta)337338return339340# draw derivative line341# y = m*(x - x1) + y1342def add_line(dj_dx, x1, y1, d, ax):343x = np.linspace(x1-d, x1+d,50)344y = dj_dx*(x - x1) + y1345ax.scatter(x1, y1, color=dlblue, s=50)346ax.plot(x, y, '--', c=dldarkred,zorder=10, linewidth = 1)347xoff = 30 if x1 == 200 else 10348ax.annotate(r"$\frac{\partial J}{\partial w}$ =%d" % dj_dx, fontsize=14,349xy=(x1, y1), xycoords='data',350xytext=(xoff, 10), textcoords='offset points',351arrowprops=dict(arrowstyle="->"),352horizontalalignment='left', verticalalignment='top')353354def plt_gradients(x_train,y_train, f_compute_cost, f_compute_gradient):355#===============356# First subplot357#===============358fig,ax = plt.subplots(1,2,figsize=(12,4))359360# Print w vs cost to see minimum361fix_b = 100362w_array = np.linspace(-100, 500, 50)363w_array = np.linspace(0, 400, 50)364cost = np.zeros_like(w_array)365366for i in range(len(w_array)):367tmp_w = w_array[i]368cost[i] = f_compute_cost(x_train, y_train, tmp_w, fix_b)369ax[0].plot(w_array, cost,linewidth=1)370ax[0].set_title("Cost vs w, with gradient; b set to 100")371ax[0].set_ylabel('Cost')372ax[0].set_xlabel('w')373374# plot lines for fixed b=100375for tmp_w in [100,200,300]:376fix_b = 100377dj_dw,dj_db = f_compute_gradient(x_train, y_train, tmp_w, fix_b )378j = f_compute_cost(x_train, y_train, tmp_w, fix_b)379add_line(dj_dw, tmp_w, j, 30, ax[0])380381#===============382# Second Subplot383#===============384385tmp_b,tmp_w = np.meshgrid(np.linspace(-200, 200, 10), np.linspace(-100, 600, 10))386U = np.zeros_like(tmp_w)387V = np.zeros_like(tmp_b)388for i in range(tmp_w.shape[0]):389for j in range(tmp_w.shape[1]):390U[i][j], V[i][j] = f_compute_gradient(x_train, y_train, tmp_w[i][j], tmp_b[i][j] )391X = tmp_w392Y = tmp_b393n=-2394color_array = np.sqrt(((V-n)/2)**2 + ((U-n)/2)**2)395396ax[1].set_title('Gradient shown in quiver plot')397Q = ax[1].quiver(X, Y, U, V, color_array, units='width', )398ax[1].quiverkey(Q, 0.9, 0.9, 2, r'$2 \frac{m}{s}$', labelpos='E',coordinates='figure')399ax[1].set_xlabel("w"); ax[1].set_ylabel("b")400401402