-
Notifications
You must be signed in to change notification settings - Fork 446
Closed
Labels
Description
Hi,
Whenever I try to use qNEHVI with MultitaskGP it throws the following error:
NotImplementedError Traceback (most recent call last)
Cell In[35], line 24
22 # not specify output_tasks will give an output for each task
23 model = MultiTaskGP(train_X, train_Y, task_feature=1)
---> 24 qNEHVI = qNoisyExpectedHypervolumeImprovement(
25 model=model,
26 ref_point=torch.zeros(2),
27 X_baseline=train_X,
28 )
29 test_X = torch.rand(64,8,2) # batch_shape=64 x q=8 x d=4
30 posterior = model.posterior(full_train_x,output_indices=full_train_i.type_as(full_train_x))
File /scratch/user/ahnafalvi/envs/gptor2/lib/python3.12/site-packages/botorch/acquisition/multi_objective/monte_carlo.py:420, in qNoisyExpectedHypervolumeImprovement.__init__(self, model, ref_point, X_baseline, sampler, objective, constraints, X_pending, eta, fat, prune_baseline, alpha, cache_pending, max_iep, incremental_nehvi, cache_root, marginalize_dim)
411 MultiObjectiveMCAcquisitionFunction.__init__(
412 self,
413 model=model,
(...)
417 eta=eta,
418 )
419 SubsetIndexCachingMixin.__init__(self)
--> 420 NoisyExpectedHypervolumeMixin.__init__(
421 self,
422 model=model,
423 ref_point=ref_point,
424 X_baseline=X_baseline,
425 sampler=self.sampler,
426 objective=self.objective,
427 constraints=self.constraints,
428 X_pending=X_pending,
429 prune_baseline=prune_baseline,
430 alpha=alpha,
431 cache_pending=cache_pending,
432 max_iep=max_iep,
433 incremental_nehvi=incremental_nehvi,
434 cache_root=cache_root,
435 marginalize_dim=marginalize_dim,
436 )
437 self.fat = fat
File /scratch/user/ahnafalvi/envs/gptor2/lib/python3.12/site-packages/botorch/utils/multi_objective/hypervolume.py:644, in NoisyExpectedHypervolumeMixin.__init__(self, model, ref_point, X_baseline, sampler, objective, constraints, X_pending, prune_baseline, alpha, cache_pending, max_iep, incremental_nehvi, cache_root, marginalize_dim)
639 # In the case that X_pending is not None, but there are fewer than
640 # max_iep pending points, the box decompositions are not performed in
641 # set_X_pending. Therefore, we need to perform a box decomposition over
642 # f(X_baseline) here.
643 if X_pending is None or X_pending.shape[-2] <= self._max_iep:
--> 644 self._set_cell_bounds(num_new_points=X_baseline.shape[0])
646 # Set q_in=-1 to so that self.sampler is updated at the next forward call.
647 self.q_in = -1
File /scratch/user/ahnafalvi/envs/gptor2/lib/python3.12/site-packages/botorch/utils/multi_objective/hypervolume.py:768, in NoisyExpectedHypervolumeMixin._set_cell_bounds(self, num_new_points)
759 else:
760 # use batched partitioning
761 obj = _pad_batch_pareto_frontier(
762 Y=obj,
763 ref_point=self.ref_point.unsqueeze(0).expand(
(...)
766 feasibility_mask=feas,
767 )
--> 768 self.partitioning = self.p_class(
769 ref_point=self.ref_point, Y=obj, **self.p_kwargs
770 )
771 cell_bounds = self.partitioning.get_hypercell_bounds().to(self.ref_point)
772 cell_bounds = cell_bounds.view(
773 2, *self._batch_sample_shape, *cell_bounds.shape[-2:]
774 ) # 2 x batch_shape x sample_shape x num_cells x m
File /scratch/user/ahnafalvi/envs/gptor2/lib/python3.12/site-packages/botorch/utils/multi_objective/box_decompositions/non_dominated.py:384, in FastNondominatedPartitioning.__init__(self, ref_point, Y)
370 def __init__(
371 self,
372 ref_point: Tensor,
373 Y: Optional[Tensor] = None,
374 ) -> None:
375 """Initialize FastNondominatedPartitioning.
376
377 Args:
(...)
382 >>> bd = FastNondominatedPartitioning(ref_point, Y=Y1)
383 """
--> 384 super().__init__(ref_point=ref_point, Y=Y)
File /scratch/user/ahnafalvi/envs/gptor2/lib/python3.12/site-packages/botorch/utils/multi_objective/box_decompositions/box_decomposition.py:275, in FastPartitioning.__init__(self, ref_point, Y)
265 def __init__(
266 self,
267 ref_point: Tensor,
268 Y: Optional[Tensor] = None,
269 ) -> None:
270 """
271 Args:
272 ref_point: A `m`-dim tensor containing the reference point.
273 Y: A `(batch_shape) x n x m`-dim tensor
274 """
--> 275 super().__init__(ref_point=ref_point, Y=Y, sort=ref_point.shape[-1] == 2)
File /scratch/user/ahnafalvi/envs/gptor2/lib/python3.12/site-packages/botorch/utils/multi_objective/box_decompositions/box_decomposition.py:68, in BoxDecomposition.__init__(self, ref_point, sort, Y)
66 self._validate_inputs()
67 self._neg_pareto_Y = self._compute_pareto_Y()
---> 68 self.partition_space()
69 else:
70 self._neg_Y = None
File /scratch/user/ahnafalvi/envs/gptor2/lib/python3.12/site-packages/botorch/utils/multi_objective/box_decompositions/box_decomposition.py:326, in FastPartitioning.partition_space(self)
324 self._get_single_cell()
325 else:
--> 326 super().partition_space()
File /scratch/user/ahnafalvi/envs/gptor2/lib/python3.12/site-packages/botorch/utils/multi_objective/box_decompositions/box_decomposition.py:152, in BoxDecomposition.partition_space(self)
150 self._partition_space()
151 else:
--> 152 self._partition_space()
File /scratch/user/ahnafalvi/envs/gptor2/lib/python3.12/site-packages/botorch/utils/multi_objective/box_decompositions/box_decomposition.py:337, in FastPartitioning._partition_space(self)
329 r"""Partition the non-dominated space into disjoint hypercells.
330
331 This method supports an arbitrary number of outcomes, but is
332 less efficient than `partition_space_2d` for the 2-outcome case.
333 """
334 if len(self.batch_shape) > 0:
335 # this could be triggered when m=2 outcomes and
336 # BoxDecomposition._partition_space_2d is not overridden.
--> 337 raise NotImplementedError(
338 "_partition_space does not support batch dimensions."
339 )
340 # this assumes minimization
341 # initialize local upper bounds
342 self.register_buffer("_U", self._neg_ref_point.unsqueeze(-2).clone())
NotImplementedError: _partition_space does not support batch dimensions.
Code example
import torch
import math
from botorch.models.multitask import MultiTaskGP
from botorch.acquisition.multi_objective.monte_carlo import qNoisyExpectedHypervolumeImprovement
torch.set_default_dtype(torch.float64)
train_x = torch.linspace(0, 0.95, 10) + 0.05 * torch.rand(10)
train_y1 = torch.sin(train_x * (2 * math.pi)) + torch.randn_like(train_x) * 0.2
train_y2 = torch.cos(train_x * (2 * math.pi)) + torch.randn_like(train_x) * 0.2
train_i_task1 = torch.full_like(train_x, dtype=torch.long, fill_value=0)
train_i_task2 = torch.full_like(train_x, dtype=torch.long, fill_value=1)
full_train_x = torch.cat([train_x, train_x])
full_train_i = torch.cat([train_i_task1, train_i_task2])
full_train_y = torch.cat([train_y1, train_y2])
train_X = torch.stack([full_train_x, full_train_i.type_as(full_train_x)], dim=-1)
train_Y = full_train_y.unsqueeze(-1)
print(train_Y.shape)
# not specify output_tasks will give an output for each task
model = MultiTaskGP(train_X, train_Y, task_feature=1)
qNEHVI = qNoisyExpectedHypervolumeImprovement(
model=model,
ref_point=torch.zeros(2),
X_baseline=train_X,
)
test_X = torch.rand(8, 2) # batch_shape=64 x q=8 x d=4
posterior = model.posterior(test_X)
samples = qNEHVI.get_posterior_samples(posterior) # default sampler has sample_shape=128. Samples has shape sample_shape=128 x batch_shape=64 x q=8 x m=2
acq_vals = qNEHVI(test_X) # has shape batch_shape=64
qNEHVI.sampler.base_samples.shape
Now, if I am not wrong , is it happening because of the task indices, all the two objectives are being outputted in a one-dimensional array and the acquisition function is thinking of it as being single objective because it has only dimension? or is it something else? how to get around it to make multitaskgp work with qNEHVI or qEHVI?
esantorella