gpytorch icon indicating copy to clipboard operation
gpytorch copied to clipboard

Matrix not PD issue in Variational GP Multiple Inputs/Outputs with Non-stationary kernel.

Open Ganesh1009 opened this issue 2 years ago • 4 comments

I am using Variational GP and using Multidimensional input and output. I created a non-stationary version of RBF kernel k(x,x') * k(x,-x') which works perfectly fine when input is 1D. When the input is multidimensional, I get the below error:

NotPSDError(f"Matrix not positive definite after repeatedly adding jitter up to {jitter_new:.1e}.")
gpytorch.utils.errors.NotPSDError: Matrix not positive definite after repeatedly adding jitter up to 1.0e-06.

after 100 iterations.

Below is my custom kernel:

def postprocess_rbf ( dist_mat ) :
	return dist_mat.div_ ( -2 ).exp_ ( )


class TestKernel ( gpytorch.kernels.RBFKernel ) :

	def forward ( self ,
	              x1 ,
	              x2 ,
	              diag = False ,
	              last_dim_is_batch = False ,
	              **params ) :
		diff = self.covar_dist ( x1 ,
		                         torch.neg ( x2 ) ,
		                         square_dist = True ,
		                         diag = diag ,
		                         postprocess = True ,
		                         dist_postprocess_func = postprocess_rbf ,
		                         **params )
		return diff

where x1 and x2 are 6D rotation representations.

The forward method is as below

	def forward ( self , x ) :

		mean_x = self.mean_module ( x )

		if self.config [ 'kernel' ] == 'non_stationary' :
			covariance_x = self.covariance_module ( x ) * self.covariance_module_ ( x )
		else :
			covariance_x = self.covariance_module ( x )

		return gpytorch.distributions.MultivariateNormal ( mean = mean_x ,
		                                                   covariance_matrix = covariance_x
		                                                   )

and covariance module is defined as below:

self.covariance_module = gpytorch.kernels.ScaleKernel (
					base_kernel = gpytorch.kernels.RBFKernel ( batch_shape = torch.Size ( [ self.config [ 'Dy' ] ] ) ,
					                                           ard_num_dims = self.config [ 'Dy' ] ) ,
					batch_shape = torch.Size ( [ self.config [ 'Dy' ] ] )
					)


self.covariance_module_ = gpytorch.kernels.ScaleKernel (
					base_kernel = TestKernel ( batch_shape = torch.Size ( [ config [ 'Dy' ] ] ) ,
					                           ard_num_dims = config [ 'Dy' ] ) ,
					batch_shape = torch.Size ( [ config [ 'Dy' ] ] )
					)

Ganesh1009 avatar Mar 16 '22 11:03 Ganesh1009

For one, I don't think you'd need to implement anything custom here:

you could just define the kernel as a function of a standard kernel:

self._covariance_module = RBFKernel()

def covariance_module(self, x, xp=None):
    if xp is not None:
        neg_xp = -xp
    else:
        neg_xp = None
    return self._covariance_module(x, xp) * self._covariance_module(x, neg_xp)

but, more generally, I'm not sure that this kernel would necessarily be positive definite any more and you should probably try to verify if it is (in several dimensions).

wjmaddox avatar Mar 28 '22 15:03 wjmaddox

@wjmaddox, if K is stationary, then K'=K(x-y)*K(x+y) -> K' is non-stationary and that is what I have tried to accomplish in my above code. I am not understanding why it would not be a PD anymore.

And, the code does work for a few iterations when the rotation is represented in 6D and after a few iterations, it fails.

The same rotation matrix when represented in quaternion, it works all fine.

Also, I would like to attach a reference issue that we discussed earlier which might make this clear:

https://github.com/cornellius-gp/gpytorch/issues/1843

Ganesh1009 avatar Mar 29 '22 14:03 Ganesh1009

My issue is that in general, i'm pretty sure K(x - y) isn't positive definite any more. see the counter example https://github.com/cornellius-gp/gpytorch/discussions/1894 .

Can you evaluate the covariance matrix when it fails? If so, how largely negative are the eigenvalues? If they're basically zero, then you can just hackily fix these issues by evaluating the covariance matrix and manually trimming the negative eigenvalues.

wjmaddox avatar Mar 29 '22 14:03 wjmaddox

@wjmaddox, thank you for your response. Could you please let me know how can I construct non-stationary kernels?

Regards, Ganesh S. K

Ganesh1009 avatar Mar 30 '22 12:03 Ganesh1009