Encode continuous scalars as a distribution over two adjacent bins.
The generalisation of one_hot to values that fall between
classes: all entries are zero except at the two bins bracketing the
scalar, which carry linearly interpolated weight summing to one.
Parameters
Returns
Tensor(..., K), non-negative and summing to 1 along the last axis.
Notes
Why a regression head would want this: predicting a scalar with a squared error forces the network to commit to one number, and the mean of a bimodal target is a value the target never takes. A distribution over bins can represent "either 0 or 10", and the scalar is recovered afterwards as . Trained with a cross-entropy, the gradient no longer scales with the error either, which is what lets one set of hyperparameters cover reward scales that differ by orders of magnitude.
Exact on a bin: a value landing on bins[k] puts all its weight
there, so this reduces to one_hot on the grid.
Examples
>>> import lucid
>>> import lucid.nn.functional as F
>>> F.two_hot(lucid.tensor([1.5]), lucid.tensor([0.0, 1.0, 2.0]))
tensor([[0., 0.5, 0.5]])See Also
one_hot—The discrete case.- lucid.nn.functional.symlog—Usually applied before encoding, so that
the grid can be uniform while the bins are not.