def __init__(self, laboratory, args): self.lab = laboratory # Get a list of every parameter to experiment with. target_parameters = [] for start in args.grid_search.split(','): node = self.lab.default_parameters.get(start) subtree = ParameterSet.enumerate(node) target_parameters.extend(start + end for end in subtree) # Suggest modifications to each parameter. self.experiments = [] for path in target_parameters: value = self.lab.default_parameters.get(path) for mod in self.mod_funcs: params = ParameterSet(self.lab.default_parameters) params.apply(path, mod(value)) X = self.lab.get_experiment(params) if not X.notes.strip(): X.notes += "Suggested by Grid Search.\n" self.experiments.append(X) self.lab.save( ) # Write all of the new grid-search experiments to the lab report.
class ParticleData: """ Attributes: p.parameters - ParameterSet p.velocities - ParameterSet full of float p.best - ParameterSet p.score - float p.age - Number of times this particle has been evaluated/updated. p.lock - Is this particle currently being evaluated? """ def __init__(self, initial_parameters, swarm=None): self.parameters = ParameterSet(initial_parameters) self.best = None self.best_score = None self.age = 0 self.initialize_velocities(swarm) self.lock = False def initialize_velocities(self, swarm=None): # Make a new parameter structure for the velocity data. self.velocities = ParameterSet(self.parameters) # Iterate through every field in the structure. for path in self.parameters.enumerate(): value = self.parameters.get(path) if swarm is not None: # Analyse the other particle velocities, so that the new # velocity is not too large or too small. data = [p.velocities.get(path) for p in swarm if p is not self] velocity = np.random.normal(np.mean(data), np.std(data)) else: # New swarm, start with a large random velocity. max_percent_change = .10 uniform = 2 * random.random() - 1 if isinstance(value, float): velocity = value * uniform * max_percent_change elif isinstance(value, int): if abs(value) < 1. / max_percent_change: velocity = uniform # Parameters are rounded, so 50% chance this will mutate. else: velocity = value * uniform * max_percent_change else: raise NotImplementedError() self.velocities.apply(path, velocity) def update_position(self): for path in self.parameters.enumerate(): position = self.parameters.get(path) velocity = self.velocities.get(path) self.parameters.apply(path, position + velocity) def update_velocity(self, global_best): for path in self.parameters.enumerate(): postition = self.parameters.get(path) velocity = self.velocities.get(path) particle_best = self.best.get( path) if self.best is not None else postition global_best_x = global_best.get( path) if global_best is not None else postition # Update velocity. particle_bias = (particle_best - postition) * particle_strength * random.random() global_bias = (global_best_x - postition) * global_strength * random.random() velocity = velocity * velocity_strength + particle_bias + global_bias self.velocities.apply(path, velocity) def update(self, score, global_best): self.age += 1 if self.best_score is not None: self.best_score *= 1 - score_decay_rate if self.best is None or score > self.best_score: self.best = ParameterSet(self.parameters) self.best_score = score print("New particle best score %g." % self.best_score) self.update_position() self.update_velocity(global_best)