Repository: cornellius-gp/gpytorch

Issue:
Dimension out of range error
# 🐛 Bug



I am using using the Spectral mixture kernel, and initalizing it from the empircal spectrum of the data. However, I get an IndexError.
## To reproduce

**Minimal example:**
```python
class ExactGPModel(gpytorch.models.ExactGP):
    def __init__(self, train_x, train_y, likelihood):
        # Super interact to with teh gpytorch.models.ExactGP
        super(ExactGPModel, self).__init__(train_x, train_y, likelihood)
        self.mean_module = gpytorch.means.ConstantMean()
        self.covar_module = gpytorch.kernels.SpectralMixtureKernel(num_mixtures=4)
        #self.covar_module.initialize_from_data(train_x, train_y)
        self.covar_module.initialize_from_data_empspect(train_x, train_y)

    def forward(self, x):
        mean_x = self.mean_module(x)
        covar_x = self.covar_module(x)
        return gpytorch.distributions.MultivariateNormal(mean_x, covar_x)

train_x = np.arange(1,100)
train_y = np.random.rand(100)


for i in range(0,50):       
    

    # Convert to tensor
    train_x = torch.from_numpy(train_x)
    train_y = torch.from_numpy(train_y)
    train_x = train_x.type(torch.FloatTensor)
    train_y = train_y.type(torch.FloatTensor)

    likelihood = gpytorch.likelihoods.GaussianLikelihood()
    model = ExactGPModel(train_x, train_y, likelihood)

```

** Error message**
```
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-18-3796fe5ce2f5> in <module>
     19 
     20     likelihood = gpytorch.likelihoods.GaussianLikelihood()
---> 21     model = ExactGPModel(train_x, train_y, likelihood)

<ipython-input-5-6b823c7240a5> in __init__(self, train_x, train_y, likelihood)
      7         self.covar_module = gpytorch.kernels.SpectralMixtureKernel(num_mixtures=4)
      8         #self.covar_module.initialize_from_data(train_x, train_y)
----> 9         self.covar_module.initialize_from_data_empspect(train_x, train_y)
     10 
     11     def forward(self, x):

~/miniconda3/envs/GP/lib/python3.7/site-packages/gpytorch/kernels/spectral_mixture_kernel.py in initialize_from_data_empspect(self, train_x, train_y)
    159         from scipy.integrate import cumtrapz
    160 
--> 161         N = train_x.size(-2)
    162         emp_spect = np.abs(fft(train_y.cpu().detach().numpy())) ** 2 / N
    163         M = math.floor(N / 2)

IndexError: Dimension out of range (expected to be in range of [-1, 0], but got -2)
```



## System information

**Please complete the following information:**
- GPyTorch Version (1.1.1)
- PyTorch Version 1.5.0)
- Windows bash on windows 10

## Additional context
Let me know if you need more info.



Discussion:
To solve this issue, you should add `train_x = train_x.unsqueeze(-1)`. This will make `train_x` be 99 x 1.

We should update `initialize_from_data_empspect` to handle this though.
Wonderful. Thanks for the help. I can confirm it works. I will leave the issue open. Feel free to close it whenever you want.

Resolving patch:
diff --git a/gpytorch/kernels/spectral_mixture_kernel.py b/gpytorch/kernels/spectral_mixture_kernel.py
--- a/gpytorch/kernels/spectral_mixture_kernel.py
+++ b/gpytorch/kernels/spectral_mixture_kernel.py
@@ -158,6 +158,11 @@ def initialize_from_data_empspect(self, train_x, train_y):
         from scipy.fftpack import fft
         from scipy.integrate import cumtrapz
 
+        if not torch.is_tensor(train_x) or not torch.is_tensor(train_y):
+            raise RuntimeError("train_x and train_y should be tensors")
+        if train_x.ndimension() == 1:
+            train_x = train_x.unsqueeze(-1)
+
         N = train_x.size(-2)
         emp_spect = np.abs(fft(train_y.cpu().detach().numpy())) ** 2 / N
         M = math.floor(N / 2)
diff --git a/setup.py b/setup.py
--- a/setup.py
+++ b/setup.py
@@ -26,7 +26,7 @@ def find_version(*file_paths):
 
 
 torch_min = "1.5"
-install_requires = [">=".join(["torch", torch_min])]
+install_requires = [">=".join(["torch", torch_min]), "scikit-learn", "scipy"]
 # if recent dev version of PyTorch is installed, no need to install stable
 try:
     import torch


Test patch:
diff --git a/test/examples/test_spectral_mixture_gp_regression.py b/test/examples/test_spectral_mixture_gp_regression.py
--- a/test/examples/test_spectral_mixture_gp_regression.py
+++ b/test/examples/test_spectral_mixture_gp_regression.py
@@ -44,11 +44,14 @@
 
 
 class SpectralMixtureGPModel(gpytorch.models.ExactGP):
-    def __init__(self, train_x, train_y, likelihood):
+    def __init__(self, train_x, train_y, likelihood, empspect=False):
         super(SpectralMixtureGPModel, self).__init__(train_x, train_y, likelihood)
         self.mean_module = ConstantMean(prior=SmoothedBoxPrior(-1, 1))
         self.covar_module = SpectralMixtureKernel(num_mixtures=4, ard_num_dims=1)
-        self.covar_module.initialize_from_data(train_x, train_y)
+        if empspect:
+            self.covar_module.initialize_from_data(train_x, train_y)
+        else:
+            self.covar_module.initialize_from_data_empspect(train_x, train_y)
 
     def forward(self, x):
         mean_x = self.mean_module(x)
@@ -70,9 +73,12 @@ def tearDown(self):
         if hasattr(self, "rng_state"):
             torch.set_rng_state(self.rng_state)
 
-    def test_spectral_mixture_gp_mean_abs_error(self):
+    def test_spectral_mixture_gp_mean_abs_error_empspect_init(self):
+        return self.test_spectral_mixture_gp_mean_abs_error(empspect=True)
+
+    def test_spectral_mixture_gp_mean_abs_error(self, empspect=False):
         likelihood = GaussianLikelihood(noise_prior=SmoothedBoxPrior(exp(-5), exp(3), sigma=0.1))
-        gp_model = SpectralMixtureGPModel(train_x, train_y, likelihood)
+        gp_model = SpectralMixtureGPModel(train_x, train_y, likelihood, empspect=empspect)
         mll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, gp_model)
 
         # Optimize the model
@@ -81,27 +87,26 @@ def test_spectral_mixture_gp_mean_abs_error(self):
         optimizer = optim.SGD(list(gp_model.parameters()), lr=0.1)
         optimizer.n_iter = 0
 
-        with gpytorch.settings.num_trace_samples(100):
-            for _ in range(150):
-                optimizer.zero_grad()
-                output = gp_model(train_x)
-                loss = -mll(output, train_y)
-                loss.backward()
-                optimizer.n_iter += 1
-                optimizer.step()
-
-            for param in gp_model.parameters():
-                self.assertTrue(param.grad is not None)
-                self.assertGreater(param.grad.norm().item(), 0)
-            for param in likelihood.parameters():
-                self.assertTrue(param.grad is not None)
-                self.assertGreater(param.grad.norm().item(), 0)
+        for _ in range(300):
+            optimizer.zero_grad()
+            output = gp_model(train_x)
+            loss = -mll(output, train_y)
+            loss.backward()
+            optimizer.n_iter += 1
             optimizer.step()
 
-            gp_model.load_state_dict(good_state_dict, strict=False)
+        for param in gp_model.parameters():
+            self.assertTrue(param.grad is not None)
+            self.assertGreater(param.grad.norm().item(), 0)
+        for param in likelihood.parameters():
+            self.assertTrue(param.grad is not None)
+            self.assertGreater(param.grad.norm().item(), 0)
+        optimizer.step()
+
+        gp_model.load_state_dict(good_state_dict, strict=False)
 
-            # Test the model
-        with torch.no_grad(), gpytorch.settings.max_cg_iterations(100):
+        # Test the model
+        with torch.no_grad():
             gp_model.eval()
             likelihood.eval()
             test_preds = likelihood(gp_model(test_x)).mean