Repository navigation
[Bug] Incorrect Parenthesis Location in Cross Term of AUCMLoss(version='v2') #74
Description
Environment: libauc 2.0.1, torch 2.2.2
Location: libauc/losses/auc.py AUCMLoss.forward branch for version == 'v2'
Issue:
The cross term is currently written as:
self.mean((y_pred*neg_mask) - self.mean(y_pred*pos_mask))The inner self.mean(y_pred*pos_mask) computes a scalar neg_mask—to become self.mean's count_nonzero includes these positions in its denominator, making the denominator
This means the negative class mean is unexpectedly scaled by
self.mean(y_pred*neg_mask) - self.mean(y_pred*pos_mask) # Fix parenthesis locationMinimal Reproducible Example:
import torch
from libauc.losses.auc import AUCMLoss
s = torch.tensor([0.1, 0.4, 0.35, 0.8]).view(-1, 1)
y = torch.tensor([0., 0., 1., 1.]).view(-1, 1)
f = AUCMLoss(margin=1.0, version='v2')
with torch.no_grad():
f.a.fill_(0.3); f.b.fill_(0.6); f.alpha.fill_(0.5)
out = f(s, y); out.backward()
print(float(out), float(f.alpha.grad)) # 0.57125002 0.10000002
# Manual calculation based on class-wise means:
mu_pos, mu_neg = (0.35+0.8)/2, (0.1+0.4)/2 # 0.575, 0.25
expect = ((0.35-0.3)**2 + (0.8-0.3)**2)/2 \
+ ((0.1-0.6)**2 + (0.4-0.6)**2)/2 \
+ 2*0.5*(1.0 + mu_neg - mu_pos) - 0.5**2
print(expect) # 0.69625000Cross-Validation (Key Evidence):
The version='v1' implementation in your library is correct. Since v1 and the class-wise mean formulation differ by a constant scaling factor
f1 = AUCMLoss(margin=1.0, version='v1')
with torch.no_grad():
f1.a.fill_(0.3); f1.b.fill_(0.6); f1.alpha.fill_(0.5)
print(float(f1(s, y)) / (0.5*0.5)) # 0.69625002 ← Matches manual calculation, contradicts v2This identity holds for the current v2 implementation when
Impact:
-
Loss value deviation: Closed-form deviation is
$-2 \cdot \alpha \cdot p \cdot \mu_-$ ; -
Underestimated dual variable pressure:
$\partial L / \partial \alpha$ is significantly smaller than expected (e.g.,$0.10$ vs. expected$0.35$ in the example above), underestimating the margin constraint penalty; -
Asymmetric gradients: The gradient on the network output for negative samples is scaled down by
$(1-p)$ , introducing asymmetry against positive samples. Under recommended training setups likeDualSampler(sampling_rate=0.5), negative sample gradients are reduced to only half of their intended magnitude.
Recommendation:
Fix the parenthesis placement. If backward compatibility is a concern, consider providing a feature toggle or documenting numerical changes in the release notes.
Activity