Feature Extraction
Transformers
Safetensors
lemondecider_decision
decision-engine
typed-decision
choice
classification
Merge
qwen3.5
custom_code
Instructions to use inclusionAI/LemonDecider with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- Transformers
How to use inclusionAI/LemonDecider with Transformers:
# Use a pipeline as a high-level helper from transformers import pipeline pipe = pipeline("feature-extraction", model="inclusionAI/LemonDecider", trust_remote_code=True)# pip install -U transformers accelerate # Load model directly from transformers import AutoModel model = AutoModel.from_pretrained("inclusionAI/LemonDecider", trust_remote_code=True, device_map="auto") - Notebooks
- Google Colab
- Kaggle
Upload option_loss.py with huggingface_hub
Browse files- 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 |
+
|