def test_project_to_psd_cone(self): """ Tests projection onto PSD cone. """ self.report('Testing projection to PSD cone.') M1 = np.random.random((10, 10)) M1 = M1 + M1.T M2 = M1.dot(M1.T) M1_proj = general_utils.project_symmetric_to_psd_cone(M1) M2_proj = general_utils.project_symmetric_to_psd_cone(M2) eigvals_M1, _ = np.linalg.eigh(M1_proj) assert np.all(eigvals_M1 > -1e-10) assert np.linalg.norm(M2_proj - M2) < 1e-5
def _get_cholesky_decomp(K_trtr_wo_noise, noise_var, handle_non_psd_kernels): """ Computes cholesky decomposition after checking how to handle non-psd kernels. """ if handle_non_psd_kernels == 'try_before_project': K_trtr_w_noise = K_trtr_wo_noise + noise_var * np.eye( K_trtr_wo_noise.shape[0]) try: # If the cholesky decomposition on the (noise added) matrix succeeds, return! L = stable_cholesky(K_trtr_w_noise, add_to_diag_till_psd=False) return L except np.linalg.linalg.LinAlgError: # otherwise, project and return return _get_cholesky_decomp(K_trtr_wo_noise, noise_var, 'project_first') elif handle_non_psd_kernels == 'project_first': # project the Kernel (without noise) to the PSD cone and return K_trtr_wo_noise = project_symmetric_to_psd_cone(K_trtr_wo_noise) return _get_cholesky_decomp(K_trtr_wo_noise, noise_var, 'guaranteed_psd') elif handle_non_psd_kernels == 'guaranteed_psd': K_trtr_w_noise = K_trtr_wo_noise + noise_var * np.eye( K_trtr_wo_noise.shape[0]) return stable_cholesky(K_trtr_w_noise) else: raise ValueError('Unknown option for handle_non_psd_kernels: %s' % (handle_non_psd_kernels))
def _get_post_covar_from_raw_covar(raw_post_covar, noise_var, is_guaranteed_psd): """ Computes the posterior covariance from the raw_post_covar. This is mostly to account for the fact that the kernel may not be psd. """ if is_guaranteed_psd: return raw_post_covar else: epsilon = 0.05 * noise_var return project_symmetric_to_psd_cone(raw_post_covar, epsilon=epsilon)