def add_data_logistic(self, event): if event.inaxes == self.ax[0]: x0_coord = event.xdata x1_coord = event.ydata if event.key is None: #shift not pressed self.ax[0].scatter(x0_coord, x1_coord, marker='x', s=10, c='red', label="y=1") self.y = np.append(self.y, 1) else: self.ax[0].scatter(x0_coord, x1_coord, marker='o', s=10, label="y=0", facecolors='none', edgecolors=dlc['dlblue'], lw=3) self.y = np.append(self.y, 0) self.X = np.append(self.X, np.array([[x0_coord, x1_coord]]), axis=0) self.fig.canvas.draw()
def mk_cost_lines(self, firsttime=False): ''' makes vertical cost lines''' if not firsttime: for artist in self.cost_items: artist.remove() self.cost_items = [] cstr = f"cost = (1/{self.m})*(" ctot = 0 label = 'cost for point' addedbreak = False for p in zip(self.x_train, self.y_train): f_wb_p = sigmoid(self.w * p[0] + self.b) c_p = compute_cost_matrix(p[0].reshape(-1, 1), p[1], np.array(self.w), self.b, logistic=True, lambda_=0, safe=True) c_p_txt = c_p a = self.ax.vlines(p[0], p[1], f_wb_p, lw=3, color=dlc["dlpurple"], ls='dotted', label=label) label = '' #just one cxy = [p[0], p[1] + (f_wb_p - p[1]) / 2] b = self.ax.annotate(f'{c_p_txt:0.1f}', xy=cxy, xycoords='data', color=dlc["dlpurple"], xytext=(5, 0), textcoords='offset points') cstr += f"{c_p_txt:0.1f} +" if len(cstr) > 38 and addedbreak is False: cstr += "\n" addedbreak = True ctot += c_p self.cost_items.extend((a, b)) ctot = ctot / (len(self.x_train)) cstr = cstr[:-1] + f") = {ctot:0.2f}" ## todo.. figure out how to get this textbox to extend to the width of the subplot c = self.ax.text(0.05, 0.02, cstr, transform=self.ax.transAxes, color=dlc["dlpurple"]) self.cost_items.append(c)
def update_contour_wb_lines(self, w, b, firsttime=False): self.w = w self.b = b cst = compute_cost_matrix(self.x_train.reshape(-1, 1), self.y_train, np.array(self.w), self.b, logistic=True, lambda_=0, safe=True) # remove lines and re-add on contour plot and 3d plot if not firsttime: for artist in self.dyn_items: artist.remove() a = self.axc.scatter(self.w, self.b, s=100, color=dlc["dlblue"], zorder=10, label="cost with \ncurrent w,b") b = self.axc.hlines(self.b, self.axc.get_xlim()[0], self.w, lw=4, color=dlc["dlpurple"], ls='dotted') c = self.axc.vlines(self.w, self.axc.get_ylim()[0], self.b, lw=4, color=dlc["dlpurple"], ls='dotted') d = self.axc.annotate(f"Cost: {cst:0.2f}", xy=(self.w, self.b), xytext=(4, 4), textcoords='offset points', bbox=dict(facecolor='white'), size=10) #Add point in 3D surface plot e = self.axs.scatter3D(self.w, self.b, cst, marker='X', s=100) self.dyn_items = [a, b, c, d, e]
def calc_logistic(self, event): ''' called on run gradient event ''' for it in [1, 8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096]: w, self.b, J_hist = gradient_descent(self.x_train.reshape(-1, 1), self.y_train.reshape(-1, 1), np.array(self.w).reshape( -1, 1), self.b, 0.1, it, logistic=True, lambda_=0, verbose=False) self.w = w[0, 0] self.dplot.update(self.w, self.b) self.con_plot.update_contour_wb_lines(self.w, self.b) self.con_plot.path.add_path_item(self.w, self.b) self.cplot.add_cost(J_hist) time.sleep(0.3) self.fig.canvas.draw()
def __init__(self, x_train, y_train, w_range, b_range): # setup figure fig = plt.figure(figsize=(10, 6)) fig.canvas.toolbar_visible = False fig.canvas.header_visible = False fig.canvas.footer_visible = False fig.set_facecolor('#ffffff') #white gs = GridSpec(2, 2, figure=fig) ax0 = fig.add_subplot(gs[0, 0]) ax1 = fig.add_subplot(gs[0, 1]) ax2 = fig.add_subplot(gs[1, 0], projection='3d') ax3 = fig.add_subplot(gs[1, 1]) pos = ax3.get_position().get_points() ##[[lb_x,lb_y], [rt_x, rt_y]] h = 0.05 width = 0.2 axcalc = plt.axes([pos[1, 0] - width, pos[1, 1] - h, width, h]) #lx,by,w,h ax = np.array([ax0, ax1, ax2, ax3, axcalc]) self.fig = fig self.ax = ax self.x_train = x_train self.y_train = y_train self.w = 0. #initial point, non-array self.b = 0. # initialize subplots self.dplot = data_plot(ax[0], x_train, y_train, self.w, self.b) self.con_plot = contour_and_surface_plot(ax[1], ax[2], x_train, y_train, w_range, b_range, self.w, self.b) self.cplot = cost_plot(ax[3]) # setup events self.cid = fig.canvas.mpl_connect('button_press_event', self.click_contour) self.bcalc = Button(axcalc, 'Run Gradient Descent \nfrom current w,b (click)', color=dlc["dlorange"]) self.bcalc.on_clicked(self.calc_logistic)
def plt_prob(ax, w_out, b_out): """ plots a decision boundary but include shading to indicate the probability """ #setup useful ranges and common linspaces x0_space = np.linspace(0, 4, 100) x1_space = np.linspace(0, 4, 100) # get probability for x0,x1 ranges tmp_x0, tmp_x1 = np.meshgrid(x0_space, x1_space) z = np.zeros_like(tmp_x0) for i in range(tmp_x0.shape[0]): for j in range(tmp_x1.shape[1]): z[i, j] = sigmoid( np.dot(w_out, np.array([tmp_x0[i, j], tmp_x1[i, j]])) + b_out) cmap = plt.get_cmap('Blues') new_cmap = truncate_colormap(cmap, 0.0, 0.5) pcm = ax.pcolormesh(tmp_x0, tmp_x1, z, norm=cm.colors.Normalize(vmin=0, vmax=1), cmap=new_cmap, shading='nearest', alpha=0.9) ax.figure.colorbar(pcm, ax=ax)