Foundations
Masked Log Softmax
Free account with email, Google or GitHub. Your code runs in an isolated PyTorch sandbox.
Your task
Return the natural logarithm of each included score’s softmax probability along dim. Each valid entry is its score minus the log of the included exponential sum; excluded entries use the finite sentinel.
Function signature
masked_log_softmax(
logits: torch.Tensor,
mask: torch.Tensor,
dim: int = -1,
sentinel: float = 0.0,
) -> torch.TensorWorked example
Unequal included scores
Take logits=[0,1,100], mask=[True,True,False] and dim=0. Only exponential weights 1 and e participate; the masked score 100 is excluded even from the denominator. With sentinel=-9, the log probabilities are [-log(1+e), 1-log(1+e), -9] ≈ [-1.313262, -0.313262, -9]. Exponentiating just the two valid entries gives probabilities that add to one.
Parameters
| Parameter | Shape and meaning |
|---|---|
logitstorch.Tensor | [d_0,\ldots,d_{R-1}]Finite scores to normalize along dim. |
masktorch.Tensor | Any shape broadcastable to logits.shape.True includes an entry in both the probability mass and normalizer. |
dimintDefault -1 | One integer normalization axis; negative indices count from the end. The output retains this axis and has the same shape as logits. |
sentinelfloatDefault 0.0 | Finite reporting value for excluded log-probability entries, including every entry of an entirely masked slice along dim; it is not log(0). |
Return
torch.Tensor · Exactly logits.shape.
A tensor with exactly logits.shape. Each slice along dim contains log probabilities at included entries and sentinel at excluded entries; an entirely masked slice is filled with sentinel.
Required behavior
- logits has rank at least one; mask is Boolean and must broadcast to exactly logits.shape. True includes a score. dim is one integer axis (default -1); negative axes count from the end. A slice fixes every index except dim.
- For a nonempty included set V, let a be its largest score and Z = sum(exp(logits[i]-a) for i in V). Subtract this included maximum before exponentiating; masked scores contribute neither exponential weight nor normalizer.
- Return logits[i]-a-log(Z) at included entries. Fill excluded entries, including all-masked slices, with sentinel (default 0). A zero-length normalization axis returns an empty tensor with logits.shape. The sentinel is a reporting value, not log(0).
- Use no epsilon, probability clipping or probability floor. Empty-support outputs have zero gradients. Preserve the shared CPU float32/float64 dtype and device, accept noncontiguous inputs, and do not mutate inputs.
- Use raw tensor operations, not a ready-made implementation of the requested primitive. Supplied parameters and random variates must not be reinitialized.
Why this matters
Subtracting a valid maximum controls exponent size; an explicit empty-row branch prevents an all-masked input from becoming NaN or a uniform distribution.
Starter code
You write the body of this function in the BioTorch workspace. Your code runs in an isolated PyTorch sandbox; Run checks the public examples and Submit grades the full test suite, including gradients.
import torch
def masked_log_softmax(
logits: torch.Tensor, # (d_0,...,d_{R-1})
mask: torch.Tensor, # Any shape broadcastable to logits.shape.
dim: int = -1,
sentinel: float = 0.0,
) -> torch.Tensor:
"""Return a tensor with shape logits.shape."""
# Implement the operation. Inputs and test setup are supplied by BioTorch.
raise NotImplementedError("Implement masked_log_softmax")
Ready to implement it?
3 progressive hints, a solution walkthrough, and grading that checks values, shapes and gradients are waiting in the workspace.
Free account with email, Google or GitHub. Your code runs in an isolated PyTorch sandbox.
Related exercises
Sources and further reading
A primitive exercise, not an end-to-end reproduction of the named models. No affiliation or endorsement is implied.