def _solve_corr(self, HH, HT): """Solve a linear system from correlation matrices. """ if self.accelerator == "GPU": Beta = self.magma_solver.gpu_solve(HH, HT, self.alpha) else: Beta = cpu_solve(HH, HT, sym_pos=True) return Beta
def _calculate_beta_cpu(self, num_neurons, num_batches): # We first calculate H.transpose * H and H.transpose * Targets # We never actually have H in memory # Since H=hidden_layer_output and is num_samples x num_neurons # H.transpose * H is of size num_neurons x num_neurons HTH = np.zeros((num_neurons, num_neurons)) # Since H.transpose is num_neurons x num_samples and output matrix # is num_samples x num_output_dimensions that gives us this shape HTT = np.zeros((num_neurons, self.num_output_dimensions)) # Adds to the matrix diagonal # Adding a small amount to the matrix diagonal improves numerical stability # Huang, G.-B., Zhou, H., Ding, X., Zhang, R.: Extreme learning machine for regression and HTH.ravel()[::num_neurons + 1] += self.alpha # Divide the data up into the batches # This part is extremely parallelizable for data_batch, output_batch in zip(np.array_split(self.data, num_batches), np.array_split(self.targets, num_batches)): batch_hidden_layer_output = self.calculate_neuron_outputs(np.asarray(data_batch)) # H.T * H is of size num_neurons by num_neurons - this is cheap to store # H.T * T is of size num_neurons by num_output_dimensions - also cheap to store # We never actually store all of H at once # This is a piece of H.T * H HTH += np.dot(batch_hidden_layer_output.T, batch_hidden_layer_output) # This is a piece of H.T * T HTT += np.dot(batch_hidden_layer_output.T, output_batch) # Solve for beta using scipy.linalg.cpu_solve # H * Beta = Target # H.T * H * Beta = H.T * T # (H.T * H) * Beta = (H.T * T), solve for beta by doing (H.T * H)^-1 * (H.T * T) beta_matrix = cpu_solve(HTH, HTT, sym_pos=True) return HTH, HTT, beta_matrix