We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Bug] PeriodicKernel returns error with BernoulliLikelihood 
# 🐛 Bug

When running the simple GPClassificationModel example (as in https://gpytorch.readthedocs.io/en/latest/examples/02_Simple_GP_Classification/Simple_GP_Classification.html), and changing the RBFKernel to a PeriodicKernel, the `likelihood(model(test_x))` line returns a RuntimeError:

`RuntimeError: The kernel LazyEvaluatedKernelTensor is not equipped to handle and diag. Expected size torch.Size([101]). Got size torch.Size([1, 101])`

This error does not occur when changing the RBFKernel to a LinearKernel, or when changing the BernoulliLikelihood to GaussianLikelihood.

## To reproduce

```
import math
import torch
import gpytorch
from matplotlib import pyplot as plt

train_x = torch.linspace(0, 1, 10)
train_y = torch.sign(torch.cos(train_x * (4 * math.pi))).add(1).div(2)

from gpytorch.models import AbstractVariationalGP
from gpytorch.variational import CholeskyVariationalDistribution
from gpytorch.variational import VariationalStrategy

class GPClassificationModel(AbstractVariationalGP):
    def __init__(self, train_x):
        variational_distribution = CholeskyVariationalDistribution(train_x.size(0))
        variational_strategy = VariationalStrategy(self, train_x, variational_distribution)
        super(GPClassificationModel, self).__init__(variational_strategy)
        self.mean_module = gpytorch.means.ConstantMean()
        self.covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel())

    def forward(self, x):
        mean_x = self.mean_module(x)
        covar_x = self.covar_module(x)
        latent_pred = gpytorch.distributions.MultivariateNormal(mean_x, covar_x)
        return latent_pred


model = GPClassificationModel(train_x)
likelihood = gpytorch.likelihoods.BernoulliLikelihood()

from gpytorch.mlls.variational_elbo import VariationalELBO

model.train()
likelihood.train()

optimizer = torch.optim.Adam(model.parameters(), lr=0.1)

mll = VariationalELBO(likelihood, model, train_y.numel())

training_iter = 50
for i in range(training_iter):
    optimizer.zero_grad()
    output = model(train_x)
    loss = -mll(output, train_y)
    loss.backward()
    optimizer.step()

model.eval()
likelihood.eval()

with torch.no_grad():
    test_x = torch.linspace(0, 1, 101)
    observed_pred = likelihood(model(test_x))

print('Reached the end of the script, successfully calculated likelihood')
```

** Stack trace/error message **
```
RuntimeError: The kernel LazyEvaluatedKernelTensor is not equipped to handle and diag. Expected size torch.Size([101]). Got size torch.Size([1, 101])
```

## Expected Behavior

The expected behavior is that the model will run with PeriodicKernel, and not only RBFKernel or LinearKernel.

## System information

**Please complete the following information:**
- <!-- GPyTorch Version (run `print(gpytorch.__version__)` -->0.3.2
- <!-- PyTorch Version (run `print(torch.__version__)` -->1.1.0
- <!-- Computer OS -->macOS


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `gpytorch/kernels/periodic_kernel.py`
Content:
```
1 #!/usr/bin/env python3
2 
3 import math
4 import torch
5 from .kernel import Kernel
6 from ..constraints import Positive
7 
8 
9 class PeriodicKernel(Kernel):
10     r""" Computes a covariance matrix based on the periodic kernel
11     between inputs :math:`\mathbf{x_1}` and :math:`\mathbf{x_2}`:
12 
13     .. math::
14 
15        \begin{equation*}
16           k_{\text{Periodic}}(\mathbf{x_1}, \mathbf{x_2}) = \exp \left(
17             \frac{2 \sin^2 \left( \pi \Vert \mathbf{x_1} - \mathbf{x_2} \Vert_1 / p \right) }
18             { \ell^2 } \right)
19        \end{equation*}
20 
21     where
22 
23     * :math:`p` is the periord length parameter.
24     * :math:`\ell` is a lengthscale parameter.
25 
26     .. note::
27 
28         This kernel does not have an `outputscale` parameter. To add a scaling parameter,
29         decorate this kernel with a :class:`gpytorch.kernels.ScaleKernel`.
30 
31     .. note::
32 
33         This kernel does not have an ARD lengthscale option.
34 
35     Args:
36         :attr:`batch_shape` (torch.Size, optional):
37             Set this if you want a separate lengthscale for each
38              batch of input data. It should be `b` if :attr:`x1` is a `b x n x d` tensor. Default: `torch.Size([])`.
39         :attr:`active_dims` (tuple of ints, optional):
40             Set this if you want to compute the covariance of only a few input dimensions. The ints
41             corresponds to the indices of the dimensions. Default: `None`.
42         :attr:`period_length_prior` (Prior, optional):
43             Set this if you want to apply a prior to the period length parameter.  Default: `None`.
44         :attr:`lengthscale_prior` (Prior, optional):
45             Set this if you want to apply a prior to the lengthscale parameter.  Default: `None`.
46         :attr:`lengthscale_constraint` (Constraint, optional):
47             Set this if you want to apply a constraint to the value of the lengthscale. Default: `Positive`.
48         :attr:`period_length_constraint` (Constraint, optional):
49             Set this if you want to apply a constraint to the value of the period length. Default: `Positive`.
50         :attr:`eps` (float):
51             The minimum value that the lengthscale/period length can take
52             (prevents divide by zero errors). Default: `1e-6`.
53 
54     Attributes:
55         :attr:`lengthscale` (Tensor):
56             The lengthscale parameter. Size = `*batch_shape x 1 x 1`.
57         :attr:`period_length` (Tensor):
58             The period length parameter. Size = `*batch_shape x 1 x 1`.
59 
60     Example:
61         >>> x = torch.randn(10, 5)
62         >>> # Non-batch: Simple option
63         >>> covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel())
64         >>>
65         >>> batch_x = torch.randn(2, 10, 5)
66         >>> # Batch: Simple option
67         >>> covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel())
68         >>> # Batch: different lengthscale for each batch
69         >>> covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel(batch_size=2))
70         >>> covar = covar_module(x)  # Output: LazyVariable of size (2 x 10 x 10)
71     """
72 
73     def __init__(self, period_length_prior=None, period_length_constraint=None, **kwargs):
74         super(PeriodicKernel, self).__init__(has_lengthscale=True, **kwargs)
75         if period_length_constraint is None:
76             period_length_constraint = Positive()
77 
78         self.register_parameter(
79             name="raw_period_length",
80             parameter=torch.nn.Parameter(torch.zeros(*self.batch_shape, 1, 1)))
81 
82         if period_length_prior is not None:
83             self.register_prior(
84                 "period_length_prior",
85                 period_length_prior,
86                 lambda: self.period_length,
87                 lambda v: self._set_period_length(v),
88             )
89 
90         self.register_constraint("raw_period_length", period_length_constraint)
91 
92     @property
93     def period_length(self):
94         return self.raw_period_length_constraint.transform(self.raw_period_length)
95 
96     @period_length.setter
97     def period_length(self, value):
98         self._set_period_length(value)
99 
100     def _set_period_length(self, value):
101         if not torch.is_tensor(value):
102             value = torch.as_tensor(value).to(self.raw_period_length)
103         self.initialize(raw_period_length=self.raw_period_length_constraint.inverse_transform(value))
104 
105     def forward(self, x1, x2, **params):
106         x1_ = x1.div(self.period_length)
107         x2_ = x2.div(self.period_length)
108         diff = self.covar_dist(x1_, x2_, **params)
109         res = torch.sin(diff.mul(math.pi)).pow(2).mul(-2 / self.lengthscale).exp_()
110         if diff.ndimension() == 2:
111             res = res.squeeze(0)
112         return res
113
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/gpytorch/kernels/periodic_kernel.py b/gpytorch/kernels/periodic_kernel.py
--- a/gpytorch/kernels/periodic_kernel.py
+++ b/gpytorch/kernels/periodic_kernel.py
@@ -102,11 +102,11 @@
             value = torch.as_tensor(value).to(self.raw_period_length)
         self.initialize(raw_period_length=self.raw_period_length_constraint.inverse_transform(value))
 
-    def forward(self, x1, x2, **params):
+    def forward(self, x1, x2, diag=False, **params):
         x1_ = x1.div(self.period_length)
         x2_ = x2.div(self.period_length)
-        diff = self.covar_dist(x1_, x2_, **params)
+        diff = self.covar_dist(x1_, x2_, diag=diag, **params)
         res = torch.sin(diff.mul(math.pi)).pow(2).mul(-2 / self.lengthscale).exp_()
-        if diff.ndimension() == 2:
+        if diff.ndimension() == 2 or diag:
             res = res.squeeze(0)
         return res

{"golden_diff": "diff --git a/gpytorch/kernels/periodic_kernel.py b/gpytorch/kernels/periodic_kernel.py\n--- a/gpytorch/kernels/periodic_kernel.py\n+++ b/gpytorch/kernels/periodic_kernel.py\n@@ -102,11 +102,11 @@\n             value = torch.as_tensor(value).to(self.raw_period_length)\n         self.initialize(raw_period_length=self.raw_period_length_constraint.inverse_transform(value))\n \n-    def forward(self, x1, x2, **params):\n+    def forward(self, x1, x2, diag=False, **params):\n         x1_ = x1.div(self.period_length)\n         x2_ = x2.div(self.period_length)\n-        diff = self.covar_dist(x1_, x2_, **params)\n+        diff = self.covar_dist(x1_, x2_, diag=diag, **params)\n         res = torch.sin(diff.mul(math.pi)).pow(2).mul(-2 / self.lengthscale).exp_()\n-        if diff.ndimension() == 2:\n+        if diff.ndimension() == 2 or diag:\n             res = res.squeeze(0)\n         return res\n", "issue": "[Bug] PeriodicKernel returns error with BernoulliLikelihood \n# \ud83d\udc1b Bug\r\n\r\nWhen running the simple GPClassificationModel example (as in https://gpytorch.readthedocs.io/en/latest/examples/02_Simple_GP_Classification/Simple_GP_Classification.html), and changing the RBFKernel to a PeriodicKernel, the `likelihood(model(test_x))` line returns a RuntimeError:\r\n\r\n`RuntimeError: The kernel LazyEvaluatedKernelTensor is not equipped to handle and diag. Expected size torch.Size([101]). Got size torch.Size([1, 101])`\r\n\r\nThis error does not occur when changing the RBFKernel to a LinearKernel, or when changing the BernoulliLikelihood to GaussianLikelihood.\r\n\r\n## To reproduce\r\n\r\n```\r\nimport math\r\nimport torch\r\nimport gpytorch\r\nfrom matplotlib import pyplot as plt\r\n\r\ntrain_x = torch.linspace(0, 1, 10)\r\ntrain_y = torch.sign(torch.cos(train_x * (4 * math.pi))).add(1).div(2)\r\n\r\nfrom gpytorch.models import AbstractVariationalGP\r\nfrom gpytorch.variational import CholeskyVariationalDistribution\r\nfrom gpytorch.variational import VariationalStrategy\r\n\r\nclass GPClassificationModel(AbstractVariationalGP):\r\n    def __init__(self, train_x):\r\n        variational_distribution = CholeskyVariationalDistribution(train_x.size(0))\r\n        variational_strategy = VariationalStrategy(self, train_x, variational_distribution)\r\n        super(GPClassificationModel, self).__init__(variational_strategy)\r\n        self.mean_module = gpytorch.means.ConstantMean()\r\n        self.covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel())\r\n\r\n    def forward(self, x):\r\n        mean_x = self.mean_module(x)\r\n        covar_x = self.covar_module(x)\r\n        latent_pred = gpytorch.distributions.MultivariateNormal(mean_x, covar_x)\r\n        return latent_pred\r\n\r\n\r\nmodel = GPClassificationModel(train_x)\r\nlikelihood = gpytorch.likelihoods.BernoulliLikelihood()\r\n\r\nfrom gpytorch.mlls.variational_elbo import VariationalELBO\r\n\r\nmodel.train()\r\nlikelihood.train()\r\n\r\noptimizer = torch.optim.Adam(model.parameters(), lr=0.1)\r\n\r\nmll = VariationalELBO(likelihood, model, train_y.numel())\r\n\r\ntraining_iter = 50\r\nfor i in range(training_iter):\r\n    optimizer.zero_grad()\r\n    output = model(train_x)\r\n    loss = -mll(output, train_y)\r\n    loss.backward()\r\n    optimizer.step()\r\n\r\nmodel.eval()\r\nlikelihood.eval()\r\n\r\nwith torch.no_grad():\r\n    test_x = torch.linspace(0, 1, 101)\r\n    observed_pred = likelihood(model(test_x))\r\n\r\nprint('Reached the end of the script, successfully calculated likelihood')\r\n```\r\n\r\n** Stack trace/error message **\r\n```\r\nRuntimeError: The kernel LazyEvaluatedKernelTensor is not equipped to handle and diag. Expected size torch.Size([101]). Got size torch.Size([1, 101])\r\n```\r\n\r\n## Expected Behavior\r\n\r\nThe expected behavior is that the model will run with PeriodicKernel, and not only RBFKernel or LinearKernel.\r\n\r\n## System information\r\n\r\n**Please complete the following information:**\r\n- <!-- GPyTorch Version (run `print(gpytorch.__version__)` -->0.3.2\r\n- <!-- PyTorch Version (run `print(torch.__version__)` -->1.1.0\r\n- <!-- Computer OS -->macOS\r\n\n", "before_files": [{"content": "#!/usr/bin/env python3\n\nimport math\nimport torch\nfrom .kernel import Kernel\nfrom ..constraints import Positive\n\n\nclass PeriodicKernel(Kernel):\n    r\"\"\" Computes a covariance matrix based on the periodic kernel\n    between inputs :math:`\\mathbf{x_1}` and :math:`\\mathbf{x_2}`:\n\n    .. math::\n\n       \\begin{equation*}\n          k_{\\text{Periodic}}(\\mathbf{x_1}, \\mathbf{x_2}) = \\exp \\left(\n            \\frac{2 \\sin^2 \\left( \\pi \\Vert \\mathbf{x_1} - \\mathbf{x_2} \\Vert_1 / p \\right) }\n            { \\ell^2 } \\right)\n       \\end{equation*}\n\n    where\n\n    * :math:`p` is the periord length parameter.\n    * :math:`\\ell` is a lengthscale parameter.\n\n    .. note::\n\n        This kernel does not have an `outputscale` parameter. To add a scaling parameter,\n        decorate this kernel with a :class:`gpytorch.kernels.ScaleKernel`.\n\n    .. note::\n\n        This kernel does not have an ARD lengthscale option.\n\n    Args:\n        :attr:`batch_shape` (torch.Size, optional):\n            Set this if you want a separate lengthscale for each\n             batch of input data. It should be `b` if :attr:`x1` is a `b x n x d` tensor. Default: `torch.Size([])`.\n        :attr:`active_dims` (tuple of ints, optional):\n            Set this if you want to compute the covariance of only a few input dimensions. The ints\n            corresponds to the indices of the dimensions. Default: `None`.\n        :attr:`period_length_prior` (Prior, optional):\n            Set this if you want to apply a prior to the period length parameter.  Default: `None`.\n        :attr:`lengthscale_prior` (Prior, optional):\n            Set this if you want to apply a prior to the lengthscale parameter.  Default: `None`.\n        :attr:`lengthscale_constraint` (Constraint, optional):\n            Set this if you want to apply a constraint to the value of the lengthscale. Default: `Positive`.\n        :attr:`period_length_constraint` (Constraint, optional):\n            Set this if you want to apply a constraint to the value of the period length. Default: `Positive`.\n        :attr:`eps` (float):\n            The minimum value that the lengthscale/period length can take\n            (prevents divide by zero errors). Default: `1e-6`.\n\n    Attributes:\n        :attr:`lengthscale` (Tensor):\n            The lengthscale parameter. Size = `*batch_shape x 1 x 1`.\n        :attr:`period_length` (Tensor):\n            The period length parameter. Size = `*batch_shape x 1 x 1`.\n\n    Example:\n        >>> x = torch.randn(10, 5)\n        >>> # Non-batch: Simple option\n        >>> covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel())\n        >>>\n        >>> batch_x = torch.randn(2, 10, 5)\n        >>> # Batch: Simple option\n        >>> covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel())\n        >>> # Batch: different lengthscale for each batch\n        >>> covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel(batch_size=2))\n        >>> covar = covar_module(x)  # Output: LazyVariable of size (2 x 10 x 10)\n    \"\"\"\n\n    def __init__(self, period_length_prior=None, period_length_constraint=None, **kwargs):\n        super(PeriodicKernel, self).__init__(has_lengthscale=True, **kwargs)\n        if period_length_constraint is None:\n            period_length_constraint = Positive()\n\n        self.register_parameter(\n            name=\"raw_period_length\",\n            parameter=torch.nn.Parameter(torch.zeros(*self.batch_shape, 1, 1)))\n\n        if period_length_prior is not None:\n            self.register_prior(\n                \"period_length_prior\",\n                period_length_prior,\n                lambda: self.period_length,\n                lambda v: self._set_period_length(v),\n            )\n\n        self.register_constraint(\"raw_period_length\", period_length_constraint)\n\n    @property\n    def period_length(self):\n        return self.raw_period_length_constraint.transform(self.raw_period_length)\n\n    @period_length.setter\n    def period_length(self, value):\n        self._set_period_length(value)\n\n    def _set_period_length(self, value):\n        if not torch.is_tensor(value):\n            value = torch.as_tensor(value).to(self.raw_period_length)\n        self.initialize(raw_period_length=self.raw_period_length_constraint.inverse_transform(value))\n\n    def forward(self, x1, x2, **params):\n        x1_ = x1.div(self.period_length)\n        x2_ = x2.div(self.period_length)\n        diff = self.covar_dist(x1_, x2_, **params)\n        res = torch.sin(diff.mul(math.pi)).pow(2).mul(-2 / self.lengthscale).exp_()\n        if diff.ndimension() == 2:\n            res = res.squeeze(0)\n        return res\n", "path": "gpytorch/kernels/periodic_kernel.py"}], "after_files": [{"content": "#!/usr/bin/env python3\n\nimport math\nimport torch\nfrom .kernel import Kernel\nfrom ..constraints import Positive\n\n\nclass PeriodicKernel(Kernel):\n    r\"\"\" Computes a covariance matrix based on the periodic kernel\n    between inputs :math:`\\mathbf{x_1}` and :math:`\\mathbf{x_2}`:\n\n    .. math::\n\n       \\begin{equation*}\n          k_{\\text{Periodic}}(\\mathbf{x_1}, \\mathbf{x_2}) = \\exp \\left(\n            \\frac{2 \\sin^2 \\left( \\pi \\Vert \\mathbf{x_1} - \\mathbf{x_2} \\Vert_1 / p \\right) }\n            { \\ell^2 } \\right)\n       \\end{equation*}\n\n    where\n\n    * :math:`p` is the periord length parameter.\n    * :math:`\\ell` is a lengthscale parameter.\n\n    .. note::\n\n        This kernel does not have an `outputscale` parameter. To add a scaling parameter,\n        decorate this kernel with a :class:`gpytorch.kernels.ScaleKernel`.\n\n    .. note::\n\n        This kernel does not have an ARD lengthscale option.\n\n    Args:\n        :attr:`batch_shape` (torch.Size, optional):\n            Set this if you want a separate lengthscale for each\n             batch of input data. It should be `b` if :attr:`x1` is a `b x n x d` tensor. Default: `torch.Size([])`.\n        :attr:`active_dims` (tuple of ints, optional):\n            Set this if you want to compute the covariance of only a few input dimensions. The ints\n            corresponds to the indices of the dimensions. Default: `None`.\n        :attr:`period_length_prior` (Prior, optional):\n            Set this if you want to apply a prior to the period length parameter.  Default: `None`.\n        :attr:`lengthscale_prior` (Prior, optional):\n            Set this if you want to apply a prior to the lengthscale parameter.  Default: `None`.\n        :attr:`lengthscale_constraint` (Constraint, optional):\n            Set this if you want to apply a constraint to the value of the lengthscale. Default: `Positive`.\n        :attr:`period_length_constraint` (Constraint, optional):\n            Set this if you want to apply a constraint to the value of the period length. Default: `Positive`.\n        :attr:`eps` (float):\n            The minimum value that the lengthscale/period length can take\n            (prevents divide by zero errors). Default: `1e-6`.\n\n    Attributes:\n        :attr:`lengthscale` (Tensor):\n            The lengthscale parameter. Size = `*batch_shape x 1 x 1`.\n        :attr:`period_length` (Tensor):\n            The period length parameter. Size = `*batch_shape x 1 x 1`.\n\n    Example:\n        >>> x = torch.randn(10, 5)\n        >>> # Non-batch: Simple option\n        >>> covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel())\n        >>>\n        >>> batch_x = torch.randn(2, 10, 5)\n        >>> # Batch: Simple option\n        >>> covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel())\n        >>> # Batch: different lengthscale for each batch\n        >>> covar_module = gpytorch.kernels.ScaleKernel(gpytorch.kernels.PeriodicKernel(batch_size=2))\n        >>> covar = covar_module(x)  # Output: LazyVariable of size (2 x 10 x 10)\n    \"\"\"\n\n    def __init__(self, period_length_prior=None, period_length_constraint=None, **kwargs):\n        super(PeriodicKernel, self).__init__(has_lengthscale=True, **kwargs)\n        if period_length_constraint is None:\n            period_length_constraint = Positive()\n\n        self.register_parameter(\n            name=\"raw_period_length\",\n            parameter=torch.nn.Parameter(torch.zeros(*self.batch_shape, 1, 1)))\n\n        if period_length_prior is not None:\n            self.register_prior(\n                \"period_length_prior\",\n                period_length_prior,\n                lambda: self.period_length,\n                lambda v: self._set_period_length(v),\n            )\n\n        self.register_constraint(\"raw_period_length\", period_length_constraint)\n\n    @property\n    def period_length(self):\n        return self.raw_period_length_constraint.transform(self.raw_period_length)\n\n    @period_length.setter\n    def period_length(self, value):\n        self._set_period_length(value)\n\n    def _set_period_length(self, value):\n        if not torch.is_tensor(value):\n            value = torch.as_tensor(value).to(self.raw_period_length)\n        self.initialize(raw_period_length=self.raw_period_length_constraint.inverse_transform(value))\n\n    def forward(self, x1, x2, diag=False, **params):\n        x1_ = x1.div(self.period_length)\n        x2_ = x2.div(self.period_length)\n        diff = self.covar_dist(x1_, x2_, diag=diag, **params)\n        res = torch.sin(diff.mul(math.pi)).pow(2).mul(-2 / self.lengthscale).exp_()\n        if diff.ndimension() == 2 or diag:\n            res = res.squeeze(0)\n        return res\n", "path": "gpytorch/kernels/periodic_kernel.py"}]}