BCE-with-logits: the loss, and the cotangent the RSB renders emit #
SmoothedLossCot.lean is this file's twin for the label-smoothed softmax cross-entropy every
other net trains on. ResNet-50's RSB-A2/A3 recipes use binary cross-entropy with logits
instead, and ResNet50RenderB's bce := true path swaps the loss cotangent for a three-op chain:
%sm = sigmoidB(logits) %d0 = %sm − %onehot %dy = %d0 / (B·K)
so dy = (σ(z) − t)/(B·K), against softmax-CE's five ops and /B. This file proves that chain
is the gradient of a loss, which ResNet-50's BCE step tie needs.
What is proved #
softplus,softplus_hasDerivAt—log(1 + eᶻ)andd/dz softplus = σ(z). The renderer already computes the loss in this form (%lsp = %lmax + %llg, the stablemax(z,0) + log(1 + e^−|z|)), so the ℝ definition is the reference's own spelling.bceLogits_eq_logSigmoid— and it IS binary cross-entropy:softplus(z) − t·zequals−[t·log σ(z) + (1−t)·log(1 − σ(z))], class by class. Without this the gradient theorem would be circular — defining the loss as whatever has the wanted derivative and then proving it has it. The identity is what earns the name.bceLogits_grad—∂/∂z_j Σ_k (softplus(z_k) − t_k·z_k) = σ(z_j) − t_j, with NO hypothesis ontat all (it is per-class, so unlike softmax-CE nothing has to sum to 1 — which is the point of BCE under mixup, where the target is a sum of one-hots and can exceed 1 nowhere but need not be a distribution either).bceLossCotGraph/_den/_row— the emitted three-op chain, its denotation, and each row as that gradient at that example's logits, divided by the emitted constant.
What is NOT claimed #
Note: The divisor is B·K, not B, and the theorem carries it as a binder rather than asserting
it. bceLossCotGraph_row_committed pins it to N·K, which is what ResNet50RenderB bakes.
timm's BinaryCrossEntropy is reduction='mean' over B×C, not the mean of the per-example sum
over classes; at K = 1000 the two differ by 1000× on the effective step, and RSB-A2's lr 5e-3
is tuned to this form. bceLogits is the per-example SUM over classes, so the /K half of the
divisor is what turns it into the mean.
Note: No label smoothing on this path, and that is the recipe. timm's a3 arg string is ls0.0;
the soft targets reach %onehot from mixup/cutmix on the host, not from a smoothing constant.
So smoothTarget does not appear here and the render emits three ops where CE emits five.
Note: %loss itself is report-only. The renderer's reportBceLoss block is hand-written text, not
pretty of an AST node, and nothing here is about those lines. What is proved
is about the COTANGENT chain, which is on the gradient path and is pretty(provenGraph).
Note: One replica, as everywhere: under *dp* each gradient node feeds the
allReduceMeanF node (DataParallel.Node), which composes this with the replica mean.
Softplus, log(1 + eᶻ). The renderer computes it as max(z,0) + log(1 + e^−|z|), which
is this function written so that no positive number is ever exponentiated; that rearrangement
is a floating-point concern and not a different map.
Equations
- Proofs.softplus z = Real.log (1 + Real.exp z)
Instances For
d/dz softplus(z) = σ(z) — the one derivative BCE-with-logits needs, and the reason
the loss is written in this form at all.
log σ(z) = −softplus(−z).
1 − σ(z) = σ(−z), hence log(1 − σ(z)) = −softplus(z).
BCE-with-logits at one example, Σ_k (softplus(z_k) − t_k·z_k) — the SUM over the K
classes, in the stable form the renderer's own %loss block computes. The emitted cotangent
divides by B·K, so the /K half of that divisor is what makes the shipped objective the
MEAN over B×K rather than the mean of these sums (see the module header's note on the divisor).
Equations
- Proofs.bceLogits K t z = ∑ k : Fin K, (Proofs.softplus (z k) - t k * z k)
Instances For
It IS binary cross-entropy: class by class, softplus(z) − t·z is
−[t·log σ(z) + (1−t)·log(1 − σ(z))].
This is what earns bceLogits its name. Without it, bceLogits_grad would be circular —
a function defined to have the derivative the render emits, then proved to have it. The
proof is softplus_neg and the two log σ identities; nothing analytic.
The emitted cotangent's numerator is this loss's gradient:
∂/∂z_j Σ_k (softplus(z_k) − t_k·z_k) = σ(z_j) − t_j.
Note: NO hypothesis on t. Softmax-CE's gradient needed Σ_k t_k = 1 to collapse
(Σ t)·softmax − t; BCE is per-class and separable, so the mixup targets — which are convex
combinations of one-hots, and the a3 recipe's only source of soft labels — need no clause.
The two ops after the sigmoid: (sg − oh) / bk. bceLossCotGraph is this applied to its
sigmoid; it is computable, so the render prints its cotangent as pretty of this node over the
sigmoid's name (RenderKit.bceCotB).
Equations
- Proofs.bceCotTail bk bStr sg oh = Proofs.StableHLO.SHlo.divConstB bStr bk (sg.subB oh)
Instances For
The three-op BCE cotangent chain ResNet50RenderB emits under bce := true, at one row
per example (m = 1, n = K) and batch N. logits is the head's output, t the graph
input %onehot, and bk the baked divisor.
Note: The render emits the sigmoid at (N := B, n := K) and re-enters the subtraction through an
.operand at N*(1*K); the two indices are equal and NOT definitionally so at a variable
K, which the render's own comment records. Stated here at the one index throughout, which
is legitimate because sigmoid is elementwise and carries no row structure —
smoothedLossCotGraph nests through the same .operand seam for the same reason.
Equations
- Proofs.bceLossCotGraph N K bk bStr logN ohN logits t = Proofs.bceCotTail bk bStr (Proofs.StableHLO.SHlo.operand logN logits).sigmoidB (Proofs.StableHLO.SHlo.operand ohN t)
Instances For
What the chain denotes, coordinatewise: (σ(logits) − t) / bk.
Each row of the emitted cotangent is BCE-with-logits' gradient at that example's logits,
divided by the baked constant. SmoothedLossCot's smoothedLossCotGraph_row at this loss,
and with no hypothesis at all where that one needs the target's mass.
Note: The committed divisor is N·K, the mean over B×K. ResNet50RenderB bakes
{B * nClasses}.0; softmax-CE's peer bakes {B}.0. timm's BinaryCrossEntropy is
reduction='mean' over B×C, not the mean of the per-example sum over classes, and at
K = 1000 the two differ by 1000× on the effective step — RSB-A2's lr 5e-3 is tuned to
this form. Stated separately from bceLossCotGraph_row so that the divisor is a checked
fact about the artifact rather than a binder nobody instantiated.