Skip to content

Commit d17443a

Browse files
committed
minor fixes
1 parent cbbc3e8 commit d17443a

1 file changed

Lines changed: 10 additions & 6 deletions

File tree

src/torchjd/scalarization/_pbi.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ class PBI(Scalarizer):
3535
direction. The paper uses ``5`` in its experiments; there is no single best value, and the
3636
paper notes that a too large or too small value worsens the result.
3737
:param weights: The preference vector :math:`r`, giving the direction along which the values are
38-
decomposed. It must have the same shape as the values passed at call time. To approximate the
39-
whole Pareto front rather than a single trade-off, it should be re-sampled from a Dirichlet
40-
distribution and reassigned before every call, e.g. for ``m`` objectives
41-
``pbi.weights = torch.distributions.Dirichlet(torch.ones(m)).sample()``.
38+
decomposed. Its values should be non-negative. It must have the same shape as the values
39+
passed at call time. To approximate the whole Pareto front rather than a single trade-off, it
40+
should be re-sampled from a Dirichlet distribution and reassigned before every call, e.g. for
41+
``m`` objectives ``pbi.weights = torch.distributions.Dirichlet(torch.ones(m)).sample()``.
4242
:param reference: The reference (ideal) point :math:`z^*` subtracted from the values. It should
4343
be a lower bound on the values. If ``None``, the origin is used, which assumes non-negative
4444
values. If provided, it must have the same shape as the values passed at call time.
@@ -78,9 +78,13 @@ def forward(self, values: Tensor, /) -> Tensor:
7878
direction = self.weights.flatten()
7979
direction = direction / direction.norm()
8080

81-
d1 = (f * direction).sum()
81+
d1 = f @ direction
8282
perpendicular = f - d1 * direction
83-
d2 = torch.sqrt((perpendicular * perpendicular).sum() + _EPSILON)
83+
# `perpendicular` has a zero norm when the values lie exactly on the preference direction
84+
# (always the case for a single-objective input, which has no perpendicular component). The
85+
# norm's gradient is then undefined, so we add a small constant under the square root to keep
86+
# it finite; this shifts the result by at most around 1e-6 there and is negligible elsewhere.
87+
d2 = torch.sqrt(perpendicular @ perpendicular + _EPSILON)
8488
return d1 + self.theta * d2
8589

8690
def __repr__(self) -> str:

0 commit comments

Comments
 (0)