我正在尝试为两个相关任务创建一个多任务 GP 回归,其中每个任务都具有 y=ax+b 形式的线性平均值,并且模型通过分配正常先验来学习参数。
我使用 python 中的 gpytorch 库开发了以下代码:
import torch
import gpytorch
class LinearMean(gpytorch.means.Mean):
def __init__(self, num_tasks):
super().__init__()
self.register_parameter(name='a', parameter=torch.nn.Parameter(torch.randn(num_tasks, train_x.shape[0])))
self.register_parameter(name='b', parameter=torch.nn.Parameter(torch.randn(1, train_x.shape[0])))
def forward(self, x):
return self.a.unsqueeze(-1) * x + self.b.unsqueeze(-1)
class LinearMultitaskGP(gpytorch.models.ExactGP):
def __init__(self, train_x, train_y, likelihood):
super().__init__(train_x, train_y, likelihood)
self.mean_module = LinearMean(num_tasks=2)
self.covar_module = gpytorch.kernels.ScaleKernel(
gpytorch.kernels.RBFKernel(ard_num_dims=train_x.size(-1))
)
def forward(self, x):
mean_x = self.mean_module(x)
covar_x = self.covar_module(x)
return gpytorch.distributions.MultitaskMultivariateNormal(mean_x, covar_x)
# Define the training data
train_x = torch.randn(100, 1)
train_y = torch.stack([torch.randn(100) * 0.1 + 0.5,
torch.randn(100) * 0.1 + 1.0], dim=-1)
# Define the likelihood and model
likelihood = gpytorch.likelihoods.MultitaskGaussianLikelihood(num_tasks=2)
model = LinearMultitaskGP(train_x, train_y, likelihood)
# Set priors on the parameters
model.mean_module.a.prior = gpytorch.priors.NormalPrior(0, 1)
model.mean_module.b.prior = gpytorch.priors.NormalPrior(0, 1)
model.covar_module.base_kernel.lengthscale.prior = gpytorch.priors.NormalPrior(0, 1)
model.covar_module.outputscale.prior = gpytorch.priors.NormalPrior(0, 1)
# Use the standard PyTorch training loop to optimize the model
optimizer = torch.optim.Adam(model.parameters(), lr=0.1)
mll = gpytorch.mlls.ExactMarginalLogLikelihood(likelihood, model)
num_epochs = 100
for epoch in range(num_epochs):
optimizer.zero_grad()
output = model(train_x)
loss = -mll(output, train_y)
loss.backward()
optimizer.step()
但是,我收到以下错误:
RuntimeError Traceback (most recent call last)
Cell In[7], line 49
47 optimizer.zero_grad()
48 output = model(train_x)
---> 49 loss = -mll(output, train_y)
50 loss.backward()
51 optimizer.step()
File ~\anaconda3\envs\python3-env\lib\site-packages\gpytorch\module.py:30, in Module.__call__(self, *inputs, **kwargs)
29 def __call__(self, *inputs, **kwargs):
---> 30 outputs = self.forward(*inputs, **kwargs)
31 if isinstance(outputs, list):
32 return [_validate_module_outputs(output) for output in outputs]
File ~\anaconda3\envs\python3-env\lib\site-packages\gpytorch\mlls\exact_marginal_log_likelihood.py:63, in ExactMarginalLogLikelihood.forward(self, function_dist, target, *params)
60 raise RuntimeError("ExactMarginalLogLikelihood can only operate on Gaussian random variables")
62 # Get the log prob of the marginal distribution
---> 63 output = self.likelihood(function_dist, *params)
64 res = output.log_prob(target)
65 res = self._add_other_terms(res, params)
File ~\anaconda3\envs\python3-env\lib\site-packages\gpytorch\likelihoods\likelihood.py:298, in Likelihood.__call__(self, input, *args, **kwargs)
287 # Marginal
288 elif any(
289 [
290 isinstance(input, MultivariateNormal),
(...)
296 ]
297 ):
--> 298 return self.marginal(input, *args, **kwargs)
299 # Error
300 else:
301 raise RuntimeError(
302 "Likelihoods expects a MultivariateNormal or Normal input to make marginal predictions, or a "
303 "torch.Tensor for conditional predictions. Got a {}".format(input.__class__.__name__)
304 )
File ~\anaconda3\envs\python3-env\lib\site-packages\gpytorch\likelihoods\multitask_gaussian_likelihood.py:111, in _MultitaskGaussianLikelihoodBase.marginal(self, function_dist, *params, **kwargs)
106 covar_kron_lt = self._shaped_noise_covar(
107 mean.shape, add_noise=self.has_global_noise, interleaved=function_dist._interleaved
108 )
109 covar = covar + covar_kron_lt
--> 111 return function_dist.__class__(mean, covar, interleaved=function_dist._interleaved)
File ~\anaconda3\envs\python3-env\lib\site-packages\pyro\distributions\distribution.py:24, in DistributionMeta.__call__(cls, *args, **kwargs)
22 if result is not None:
23 return result
---> 24 return super().__call__(*args, **kwargs)
File ~\anaconda3\envs\python3-env\lib\site-packages\gpytorch\distributions\multitask_multivariate_normal.py:39, in MultitaskMultivariateNormal.__init__(self, mean, covariance_matrix, validate_args, interleaved)
35 raise RuntimeError("mean should be a matrix or a batch matrix (batch mode)")
37 # Ensure that shapes are broadcasted appropriately across the mean and covariance
38 # Means can have singleton dimensions for either the `n` or `t` dimensions
---> 39 batch_shape = torch.broadcast_shapes(mean.shape[:-2], covariance_matrix.shape[:-2])
40 if mean.shape[-2:].numel() != covariance_matrix.size(-1):
41 if covariance_matrix.size(-1) % mean.shape[-2:].numel():
File ~\anaconda3\envs\python3-env\lib\site-packages\linear_operator\operators\_linear_operator.py:2160, in LinearOperator.shape(self)
2158 @property
2159 def shape(self):
-> 2160 return self.size()
File ~\anaconda3\envs\python3-env\lib\site-packages\linear_operator\operators\_linear_operator.py:2153, in LinearOperator.size(self, dim)
2147 def size(self, dim: Optional[int] = None) -> Union[torch.Size, int]:
2148 """
2149 Returns he size of the LinearOperator (or the specified dimension).
2150
2151 :param dim: A specific dimension.
2152 """
-> 2153 size = self._size()
2154 if dim is not None:
2155 return size[dim]
File ~\anaconda3\envs\python3-env\lib\site-packages\linear_operator\operators\sum_linear_operator.py:54, in SumLinearOperator._size(self)
53 def _size(self):
---> 54 return torch.broadcast_shapes(*[lt.shape for lt in self.linear_ops])
File ~\anaconda3\envs\python3-env\lib\site-packages\torch\functional.py:126, in broadcast_shapes(*shapes)
124 continue
125 if result[i] != 1:
--> 126 raise RuntimeError("Shape mismatch: objects cannot be broadcast to a single shape")
127 result[i] = shape[i]
128 else:
RuntimeError: Shape mismatch: objects cannot be broadcast to a single shape
我不确定问题出在哪里,非常感谢任何建议。