使用可学习参数开发多任务 GP 回归

问题描述 投票:0回答:0

我正在尝试为两个相关任务创建一个多任务 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

我不确定问题出在哪里,非常感谢任何建议。

python multitasking gpytorch
© www.soinside.com 2019 - 2024. All rights reserved.