Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- class stochastic_gradient_descent:
- def __init__ (self,
- initial_position,
- objective_function_handle,
- c = 0.25,
- beta = 0.0,
- sample_count_scale = 3,
- max_iter = 60,
- max_step_size = 0.25,
- stopping_slope = 0.001,
- gamma = 0.101,
- degrees_of_freedom = 2,
- verbose = True):
- self.x = initial_position
- self.x_old = initial_position
- self.xs = initial_position.reshape((1,2))
- self.w = initial_position
- self.objective_function = objective_function_handle
- self.beta = beta
- self.gamma = gamma
- self.c = c
- self.dofs = degrees_of_freedom
- self.max_iter = max_iter
- self.verbose = verbose
- self.diffs = 0
- self.f_evals = 0
- self.multiplier = sample_count_scale
- self.k = 0
- self.max_step_size = max_step_size
- self.stopping_slope = stopping_slope
- self.get_angle_scales()
- def get_angle_scales(self):
- self.angle_scales = np.pi * np.ones(self.dofs-1)
- self.angle_scales[self.dofs-2] = 2.0 * np.pi
- def sample_sphere(self):
- n = self.multiplier * self.dofs
- sample = np.ones((n,self.dofs))
- for indx in range(n):
- angles = np.random.random(self.dofs-1) * self.angle_scales
- for jndx in range(self.dofs-1):
- sample[indx,jndx] = sample[indx,jndx] * np.cos(angles[jndx])
- for kndx in range(jndx):
- sample[indx,jndx] = sample[indx,jndx] * np.sin(angles[kndx])
- for jndx in range(self.dofs-1):
- sample[indx,self.dofs-1] = sample[indx,self.dofs-1] * np.sin(angles[jndx])
- self.sphere_samples = sample
- def evaluate_sphere_sample(self):
- n_samples = self.multiplier * self.dofs
- self.w_vals = np.zeros((n_samples, self.dofs))
- self.y_raw = np.zeros(n_samples)
- ycenters = np.zeros(n_samples+1)
- for indx in range(n_samples):
- self.w_vals[indx,:] = self.w + self.c_k * self.sphere_samples[indx]
- ycenters[indx] = self.objective_function(self.w)
- self.y_raw[indx] = self.objective_function(self.w_vals[indx,:])
- ycenters[n_samples] = self.objective_function(self.w)
- self.y = self.y_raw# - 0.5*(ycenters[0:n_samples] + ycenters[1:n_samples+1])
- def compute_gradient(self):
- n_samples = self.multiplier * self.dofs
- self.sample_sphere()
- self.evaluate_sphere_sample()
- #d_vals = hooks_distance(self.w_vals, self.y)
- #mean_d = np.mean(d_vals)
- #std_d = np.std(d_vals)
- #indices = np.abs(d_vals - mean_d) < 2.5*std_d
- #indices = indices.reshape(np.max(indices.shape))
- A = np.ones((n_samples,self.dofs+1))
- A[:,0:self.dofs] = self.w_vals
- #self.gradient = np.linalg.lstsq(self.w_vals[indices,:],self.y[indices],rcond=-1)[0]
- #self.gradient =
- lstsq_res = np.linalg.lstsq(A,self.y,rcond=-1)[0]
- self.gradient = lstsq_res[0:self.dofs]
- def next_step(self):
- self.x = self.beta*self.x_old + self.gradient
- if self.k < 1:
- self.a_k = 0.00005
- self.grad_test = np.array([np.linalg.norm(self.gradient)])
- else:
- self.a_k = np.linalg.norm(self.x - self.x_old)**2 / np.sum((self.x - self.x_old)*(self.gradient - self.gradient_old))
- self.grad_test = np.append(self.grad_test,np.linalg.norm(self.gradient)/self.k)
- self.gradient_old = self.gradient
- temp = - self.a_k * self.x
- tnorm = np.linalg.norm(temp)
- if tnorm > self.max_step_size:
- self.w = self.w + self.max_step_size * (temp/tnorm)
- else:
- self.w = self.w + temp
- def optimize(self):
- converged = False
- while not converged:
- self.c_k = self.c / (((self.k) + 1)**self.gamma)
- self.compute_gradient()
- self.x_old = self.x
- self.next_step()
- self.xs = np.append(self.xs, self.w.reshape((1,2)), axis=0)
- self.k += 1
- converged = self.convergence_criteria()
- def convergence_criteria(self):
- out = False
- if self.k > self.max_iter:
- out = True
- self.reason = "Max Iterations Reached"
- num_samples = np.max(np.shape(self.xs))
- all_x = self.xs[:,0].reshape((num_samples,))
- all_y = self.xs[:,1].reshape((num_samples,))
- self.diff_r = np.sqrt((self.xs[:,:]-self.xs[0,:])**2)
- self.diff_x = all_x[:]-all_x[0]
- self.diff_y = all_y[:]-all_y[0]
- self.diff_dx = all_x[1:] - all_x[0:-1]
- self.diff_dy = all_y[1:] - all_y[0:-1]
- self.diff_dr = np.sqrt((self.diff_dx**2 + self.diff_dy**2))
- """
- out = False
- if self.k > 16:
- y_vals = all_y[-15:]
- x_vals = all_x[-15:]
- r_vals = np.sqrt(x_vals**2 + y_vals**2)
- horiz = np.ones((15,2))
- horiz[:,0] = np.linspace(0,1,15)
- xlstsq = np.linalg.lstsq(horiz,x_vals,rcond=-1)
- ylstsq = np.linalg.lstsq(horiz,y_vals,rcond=-1)
- rlstsq = np.linalg.lstsq(horiz,r_vals,rcond=-1)
- x_slope = xlstsq[0][0]
- y_slope = ylstsq[0][0]
- outflagxy = (x_slope < self.stopping_slope) and (y_slope < self.stopping_slope)
- if outflagxy:
- out = True
- self.reason = 'Regression'
- """
- return out
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement