def predict( self, X: np.ndarray = None, first_layer: np.ndarray = None, training: bool = False, ): if first_layer is None and self.model_trained is False: msg = "Model has not been trained yet" raise ModelError(msg) elif first_layer is not None: # Calculate the dot product + bias out = np.dot(X, first_layer[1:, :]) + first_layer[0] activated_layer = self.activate(out) last_layer = self.calculate_linear(activated_layer) elif first_layer is None: first_layer = self._first_layer last_layer = self._last_layer # Calculate the dot product + bias out = np.dot(X, first_layer[1:, :]) + first_layer[0] activated_layer = self.activate(out) else: msg = "How did you get here?" raise ModelError(msg) y_pred = np.dot(activated_layer, last_layer[1:, :]) + last_layer[0] if training: return y_pred else: return y_pred[:, 0], np.zeros_like(y_pred[:, 0])
def _model_performance( self, first_layer: np.ndarray = None, X: np.ndarray = None, y_true: np.ndarray = None, ): if first_layer is None and self.model_trained is False: msg = "Model has not been trained yet" raise ModelError(msg) if first_layer is None: first_layer = self._first_layer if X is None: X = self.X y = self.y if np.ndim(first_layer) == 3: loss = [] complexity = [] for actual_first_layer in first_layer: y_predict = self.predict(X=X, first_layer=actual_first_layer, training=True) loss.append(self.loss_function(y, y_predict)) complexity.append(np.count_nonzero(actual_first_layer)) elif np.ndim(first_layer) == 2: y_predict = self.predict(X=X, first_layer=first_layer, training=True) loss = self.loss_function(y, y_predict) complexity = np.count_nonzero(first_layer) return np.asarray((loss, complexity)).T
def _model_performance( self, individuals: np.ndarray = None, X: np.ndarray = None, y_true: np.ndarray = None, ): if individuals is None and self.model_trained is False: msg = "Model has not been trained yet" raise ModelError(msg) if individuals is None: individuals = self._subnets if X is None: X = self.X y = self.y if len(individuals) > 1: loss = [] complexity = [] for individual in individuals: penultimate_y_pred, ind_complexity = self._feed_forward(individual, X) y_pred, _ = self._calculate_linear(penultimate_y_pred) loss.append(self.loss_function(y, y_pred)) complexity.append(ind_complexity) else: penultimate_y_pred, ind_complexity = self._feed_forward(individuals, X) y_pred, _ = self._calculate_linear(penultimate_y_pred) loss = self.loss_function(y, y_pred) complexity = ind_complexity return np.asarray((loss, complexity)).T
def fit(self, X: np.ndarray, y: np.ndarray): if isinstance(X, (pd.DataFrame, pd.Series)): X = X.values if isinstance(y, (pd.DataFrame, pd.Series)): y = y.values.reshape(-1, 1) if X.shape[0] != y.shape[0]: msg = (f"Ensure that the number of samples in X and y are the same" f"Number of samples in X = {X.shape[0]}" f"Number of samples in y = {y.shape[0]}") raise ModelError(msg) self.X = X self.y = y if self.subsets is None: self.subsets = [] # Create random subsets of decision variables for each subnet for i in range(self.num_subnets): n = random.randint(1, self.X.shape[1]) self.subsets.append(random.sample(range(self.X.shape[1]), n)) # Ensure that each decision variable is used as an input in at least one subnet for n in list(range(self.X.shape[1])): if not any(n in k for k in self.subsets): self.subsets[random.randint(0, self.num_subnets - 1)].append(n) # Create problem problem = surrogateProblem( performance_evaluator=self._model_performance) problem.n_of_objectives = 2 # Create Population initial_pop = self._create_individuals() population = SurrogatePopulation(problem, self.pop_size, initial_pop, None, None, None) # Do evolution evolver = self.training_algorithm(problem, initial_population=population) recombinator = EvoDN2Recombination(evolver=evolver) evolver.population.recombination = recombinator figure = animate_init_(evolver.population.objectives, filename="EvoDN2.html") while evolver.continue_evolution(): evolver.iterate() figure = animate_next_( evolver.population.objectives, figure, filename="EvoDN2.html", generation=evolver._iteration_counter, ) self.model_population = evolver.population # Selection self.select() self.model_trained = True
def select(self): if self.model_selection_criterion == "min_error": # Return the model with the lowest error selected = np.argmin(self.model_population.objectives[:, 0]) else: raise ModelError( "Selection criterion not recognized. Use 'min_error'.") self.tree = self.model_population.individuals[selected][0] y_pred = self.predict(X=self.X) self.performance["RMSE"] = np.sqrt(mean_squared_error(self.y, y_pred)) self.performance["R^2"] = r2_score(self.y, y_pred)
def activate(self, x): if self.activation_function == "sigmoid": return expit(x) elif self.activation_function == "relu": return np.maximum(x, 0) elif self.activation_function == "tanh": return np.tanh(x) else: msg = ( f"Given activation function not recognized: {self.activation_function}" f"\nActivation function should be one of ['relu', 'sigmoid', 'tanh']" ) raise ModelError(msg)
def select(self): if self.model_selection_criterion == "min_error": # Return the model with the lowest error selected = np.argmin(self.model_population.objectives[:, 0]) else: raise ModelError("Selection criterion not recognized. Use 'min_error'.") self.subnets = self.model_population.individuals[selected] penultimate_y_pred, complexity = self._feed_forward(self.subnets, self.X) y_pred, linear_layer = self._calculate_linear(penultimate_y_pred) self._last_layer = linear_layer self.performance["RMSE"] = np.sqrt(mean_squared_error(self.y, y_pred)) self.performance["R^2"] = r2_score(self.y, y_pred) self.performance["Complexity"] = complexity
def self_distance(self, arr): if arr.ndim == 1: dist = np.abs(np.subtract(arr[None, :], arr[:, None])) elif arr.ndim == 2: dist = np.sum(np.abs(np.subtract(arr[None, :, :], arr[:, None, :])), axis=2) else: msg = ( f"Array of wrong dimension. Expected dimension = 1 or 2. Recieved " f"dimension = {arr.ndim}") raise ModelError(msg) return dist
def fit(self, X: np.ndarray, y: np.ndarray): if isinstance(X, (pd.DataFrame, pd.Series)): X = X.values if isinstance(y, (pd.DataFrame, pd.Series)): y = y.values.reshape(-1, 1) if X.shape[0] != y.shape[0]: msg = (f"Ensure that the number of samples in X and y are the same" f"Number of samples in X = {X.shape[0]}" f"Number of samples in y = {y.shape[0]}") raise ModelError(msg) self.X = X self.y = y # Create problem problem = surrogateProblem( performance_evaluator=self._model_performance) problem.n_of_objectives = 2 # Create Population initial_pop = self._create_individuals() population = SurrogatePopulation(problem, self.pop_size, initial_pop, None, None, None) # Do evolution evolver = self.training_algorithm(problem, initial_population=population) recombinator = EvoNNRecombination(evolver=evolver, mutation_type=self.mutation_type) evolver.population.recombination = recombinator figure = animate_init_(evolver.population.objectives, filename="EvoNN.html") while evolver.continue_evolution(): evolver.iterate() figure = animate_next_( evolver.population.objectives, figure, filename="EvoNN.html", generation=evolver._iteration_counter, ) self.model_population = evolver.population # Selection self.select() self.model_trained = True
def _model_performance(self, trees: LinearNode, X: np.ndarray = None, y: np.ndarray = None): if trees is None and self.model_trained is False: msg = "Model has not been trained yet" raise ModelError(msg) if trees is None: trees = self.tree if X is None: X = self.X y = self.y if len(trees) > 1: loss = [] complexity = [] for tree in trees: y_pred, ind_complexity = tree[0].calculate_linear(X, y) loss.append(self.loss_function(y, y_pred)) complexity.append(ind_complexity) else: y_pred, complexity = trees[0].calculate_linear(X, y) loss = self.loss_function(y, y_pred) return np.asarray((loss, complexity)).T
def fit(self, X: pd.DataFrame, y: pd.DataFrame): if X.shape[0] != y.shape[0]: msg = (f"Ensure that the number of samples in X and y are the same" f"Number of samples in X = {X.shape[0]}" f"Number of samples in y = {y.shape[0]}") raise ModelError(msg) self.X = X self.y = y if self.terminal_set is None: self.terminal_set = X.columns.tolist() # Create problem problem = surrogateProblem( performance_evaluator=self._model_performance) problem.n_of_objectives = 2 # Create Population initial_pop = self._create_individuals() population = SurrogatePopulation(problem, self.pop_size, initial_pop, None, None, None) population.xover = BioGP_xover( probability_crossover=self.probability_crossover) population.mutation = BioGP_mutation( probability_mutation=self.probability_mutation) # Do single objective evolution tournament_evolver = TournamentEA( problem, initial_population=population, population_size=self.pop_size, n_gen_per_iter=self.single_obj_generations, n_iterations=1, ) figure = animate_init_(tournament_evolver.population.objectives, filename="BioGP.html") while tournament_evolver.continue_evolution(): tournament_evolver.iterate() figure = animate_next_( tournament_evolver.population.objectives, figure, filename="BioGP.html", generation=tournament_evolver._iteration_counter, ) population = tournament_evolver.population # Do bi-objective evolution evolver = self.training_algorithm( problem, initial_population=population, population_size=self.pop_size, n_gen_per_iter=10, n_iterations=10, ) while evolver.continue_evolution(): evolver.iterate() figure = animate_next_( evolver.population.objectives, figure, filename="BioGP.html", generation=evolver._iteration_counter + tournament_evolver._iteration_counter, ) self.model_population = evolver.population # Selection self.select() self.model_trained = True