Repository: cornellius-gp/gpytorch

Issue:
Compute BIC with Costume Kernel
Hi, 
I'm very new to gpytorch, maybe this is very easy but I want some guidance to implement it. I defined a custom kernel which could be a sum or product of default gpytorch kernels. In principle it seems easy just to add the term  k*log(n) to the likelihood, n is easy to extract, however k the number of parameters of the kernel, I'm not sure to extract it. 

Also once I get the k*log(n) term how I can add it to the likelihood properly to minimize it with the adam or any other optimizer. 

Best Regards  


Discussion:
Try something like `len(list(covar_module.parameters()))`.

You can just add your term to the mll you compute. That being said, it's constant and so won't affect optimization if you are doing something with Adam -- usually people use BIC for model selection.
Hi Jacob, 
Thanks for your answer, sorry I just have time to check this until now. I learned a lot from the line you suggested, however it doesnt work when you have ard_num_dims>1. Then, I did something very similar: 

number=0
for i in list(model.parameters()):
    if i.requires_grad:
        a=np.array([],dtype=np.int32);
        for j in range(len(i.size())):
            a=np.hstack((a,i.size(j)));
        print(i,"has size",a, "shape tensor",a.shape,"the sum",a.sum(axis=0),"the product",a.prod(axis=0))
        number+=a.prod(axis=0);
        print("number of parameters ...",number)
print("number of parameters",number)

I defined a function to pass any composite kernel I define as:

class ExactGPModel(gpytorch.models.ExactGP):
    def __init__(self, train_x, train_y, likelihood, kernel):
        super(ExactGPModel, self).__init__(train_x, train_y, likelihood)
        self.mean_module = gpytorch.means.ConstantMean()
        self.covar_module = kernel
        
    def forward(self, x):
        mean_x = self.mean_module(x)
        covar_x=self.covar_module(x);
        
        return gpytorch.distributions.MultivariateNormal(mean_x, covar_x)

I passed the kernel: 

#kernel model
K1=gpytorch.kernels.AdditiveKernel(gpytorch.kernels.ScaleKernel(gpytorch.kernels.MaternKernel())+gpytorch.kernels.ScaleKernel(gpytorch.kernels.RBFKernel()))

# initialize likelihood and model
likelihood = gpytorch.likelihoods.GaussianLikelihood()
model = ExactGPModel(train_x, train_y, likelihood,K1)

but I notice I get the error 

 563     def _exact_predictive_covar_inv_quad_form_cache(self, train_train_covar_inv_root, test_train_covar):
--> 564         test_train_covar = test_train_covar.evaluate_kernel()
    565         if not isinstance(test_train_covar, SumLazyTensor):
    566             return super(SumPredictionStrategy, self)._exact_predictive_covar_inv_quad_form_cache(

AttributeError: 'Tensor' object has no attribute 'evaluate_kernel'


when evaluating the predictive posterior with the option gpytorch.settings.fast_pred_var()
whithout that option it works, however I'm interested to use that option since I pretend to build complex kernels nd it is useful do fast evaluations of the posterior. 

I also test that defining the covariance directly in the forward function solve the problem, however I pretend to build kernels in a complete automatic way, so it is not useful. 

I put an adapted example of your basic tutorial with that modifications in: 

https://github.com/josuelandinez/Example-Gpytorch-BIC/blob/master/GPCrashTest.ipynb

best regards
  




 

Resolving patch:
diff --git a/gpytorch/models/exact_prediction_strategies.py b/gpytorch/models/exact_prediction_strategies.py
--- a/gpytorch/models/exact_prediction_strategies.py
+++ b/gpytorch/models/exact_prediction_strategies.py
@@ -564,7 +564,7 @@ def _sub_strategies(self):
         return sub_strategies
 
     def _exact_predictive_covar_inv_quad_form_cache(self, train_train_covar_inv_root, test_train_covar):
-        test_train_covar = test_train_covar.evaluate_kernel()
+        test_train_covar = lazify(test_train_covar).evaluate_kernel()
         if not isinstance(test_train_covar, SumLazyTensor):
             return super(SumPredictionStrategy, self)._exact_predictive_covar_inv_quad_form_cache(
                 train_train_covar_inv_root, test_train_covar
@@ -578,7 +578,7 @@ def _exact_predictive_covar_inv_quad_form_cache(self, train_train_covar_inv_root
     def _exact_predictive_covar_inv_quad_form_root(self, precomputed_cache, test_train_covar):
         # Here the precomputed cache is a list
         # where each component in the list is the precomputed cache for each component lazy tensor
-        test_train_covar = test_train_covar.evaluate_kernel()
+        test_train_covar = lazify(test_train_covar).evaluate_kernel()
         if not isinstance(test_train_covar, SumLazyTensor):
             return super(SumPredictionStrategy, self)._exact_predictive_covar_inv_quad_form_root(
                 precomputed_cache, test_train_covar


Test patch: