niqun123123 commited on
Commit
30fa7c0
·
verified ·
1 Parent(s): 329bafa

Upload option_loss.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. option_loss.py +45 -0
option_loss.py ADDED
@@ -0,0 +1,45 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Shared valid-option FP32 CE for trainer and standalone HF forward(labels=...)."""
2
+ import torch
3
+ import torch.nn.functional as F
4
+
5
+ MAX_OPTIONS = 255
6
+
7
+
8
+ def option_cross_entropy(logits, target, counts, reduction='mean'):
9
+ """FP32 masked CE. Same AutoJev objective; strict target validation added.
10
+
11
+ Normalize over valid options ONLY, then zero padded log-probabilities
12
+ before multiplying targets (avoids 0 * -inf). This is the AutoJev CE
13
+ objective without reliance on a finite mask dominating valid logits.
14
+ Padded logits have zero gradient. Each decision contributes one loss,
15
+ regardless of scale length; there is no per-option or per-type weighting.
16
+ """
17
+ if logits.ndim != 2 or not 1 <= logits.shape[1] <= MAX_OPTIONS or target.shape != logits.shape or not len(logits):
18
+ raise ValueError('Expected nonempty logits and targets of shape [B,N], 1 <= N <= 255')
19
+ width = logits.shape[1]
20
+ counts = torch.as_tensor(counts, device=logits.device)
21
+ if counts.shape != (len(logits),) or counts.dtype == torch.bool or counts.is_floating_point():
22
+ raise ValueError('One integer option count required per row')
23
+ if not bool(((counts >= 1) & (counts <= width)).all()):
24
+ raise ValueError(f'Option counts must be 1..{width}')
25
+ invalid = torch.arange(width, device=logits.device)[None] >= counts[:, None]
26
+ values = target.to(device=logits.device, dtype=torch.float32)
27
+ if not bool(torch.isfinite(values).all()) or bool((values < 0).any()) or bool((values > 1).any()):
28
+ raise ValueError('Nonfinite/negative/out-of-range target')
29
+ if not torch.allclose(values.sum(-1), torch.ones(len(values), device=values.device), atol=1e-6, rtol=0):
30
+ raise ValueError('Target mass must sum to one')
31
+ if bool((values.masked_select(invalid) != 0).any()):
32
+ raise ValueError('Target mass on padded options')
33
+ if not bool(torch.isfinite(logits.masked_select(~invalid)).all()):
34
+ raise ValueError('Nonfinite valid logits')
35
+ masked = logits.float().masked_fill(invalid, -torch.inf)
36
+ logp = F.log_softmax(masked, dim=-1).masked_fill(invalid, 0.0)
37
+ loss = -(values * logp).sum(-1)
38
+ if reduction == 'none':
39
+ return loss
40
+ if reduction == 'sum':
41
+ return loss.sum()
42
+ if reduction == 'mean':
43
+ return loss.mean()
44
+ raise ValueError(f'Unknown reduction: {reduction}')
45
+