Text Generation
PEFT
Safetensors
PyTorch
English
causal-lm
lora
qwen
sft
dpo
seal
self-adaptation
hitl
Instructions to use aaronr43210/MiniSEAL with libraries, inference providers, notebooks, and local apps. Follow these links to get started.
- Libraries
- PEFT
How to use aaronr43210/MiniSEAL with PEFT:
Task type is invalid.
- Notebooks
- Google Colab
- Kaggle
Download src/alignment/losses.py from aaronr43210/MiniSEAL: direct link, hf CLI and curl.
- Browser
- Download file 3.16 kB
-
https://huggingface.co/aaronr43210/MiniSEAL/resolve/main/src/alignment/losses.py
- Command line
-
hf download hf://aaronr43210/MiniSEAL/src/alignment/losses.py
-
curl -L -o losses.py https://huggingface.co/aaronr43210/MiniSEAL/resolve/main/src/alignment/losses.py
3.16 kB
| """ | |
| Loss functions for SFT and DPO. | |
| SFT: | |
| Standard causal LM loss on response tokens. | |
| DPO: | |
| Direct Preference Optimization: | |
| -log sigmoid(beta * [(log pi chosen - log ref chosen) | |
| - (log pi rejected - log ref rejected)]) | |
| """ | |
| import torch | |
| import torch.nn.functional as F | |
| def causal_lm_loss(logits: torch.Tensor, labels: torch.Tensor) -> torch.Tensor: | |
| """ | |
| Calculates causal LM loss. | |
| Input: | |
| logits: [batch, seq, vocab] | |
| labels: [batch, seq] | |
| Labels use -100 for ignored positions. | |
| Output: | |
| scalar loss. | |
| Important: | |
| logits[:, t] predicts labels[:, t+1] | |
| """ | |
| shift_logits = logits[:, :-1, :].contiguous() | |
| shift_labels = labels[:, 1:].contiguous() | |
| loss = F.cross_entropy( | |
| shift_logits.view(-1, shift_logits.size(-1)), | |
| shift_labels.view(-1), | |
| ignore_index=-100, | |
| ) | |
| return loss | |
| def sequence_logprobs( | |
| model, | |
| input_ids: torch.Tensor, | |
| labels: torch.Tensor, | |
| ) -> torch.Tensor: | |
| """ | |
| Computes sequence log probability of only supervised answer tokens. | |
| Input: | |
| model: policy or reference model. | |
| input_ids: [batch, seq] | |
| labels: [batch, seq], -100 on ignored tokens. | |
| Output: | |
| log probability per sequence: [batch] | |
| """ | |
| logits, _ = model(input_ids, targets=None) | |
| shift_logits = logits[:, :-1, :].contiguous() | |
| shift_labels = labels[:, 1:].contiguous() | |
| log_probs = F.log_softmax(shift_logits, dim=-1) | |
| mask = shift_labels != -100 | |
| safe_labels = shift_labels.masked_fill(~mask, 0) | |
| token_log_probs = torch.gather( | |
| log_probs, | |
| dim=-1, | |
| index=safe_labels.unsqueeze(-1), | |
| ).squeeze(-1) | |
| token_log_probs = token_log_probs * mask | |
| return token_log_probs.sum(dim=-1) | |
| def dpo_loss( | |
| policy_chosen_logps: torch.Tensor, | |
| policy_rejected_logps: torch.Tensor, | |
| ref_chosen_logps: torch.Tensor, | |
| ref_rejected_logps: torch.Tensor, | |
| beta: float, | |
| ) -> tuple[torch.Tensor, dict]: | |
| """ | |
| Direct Preference Optimization loss. | |
| Input: | |
| policy_chosen_logps: log pi_theta(chosen) | |
| policy_rejected_logps: log pi_theta(rejected) | |
| ref_chosen_logps: log pi_ref(chosen) | |
| ref_rejected_logps: log pi_ref(rejected) | |
| beta: KL trade-off parameter. | |
| Output: | |
| loss | |
| metrics dictionary | |
| """ | |
| policy_logratios = policy_chosen_logps - policy_rejected_logps | |
| ref_logratios = ref_chosen_logps - ref_rejected_logps | |
| logits = beta * (policy_logratios - ref_logratios) | |
| losses = -F.logsigmoid(logits) | |
| chosen_rewards = beta * (policy_chosen_logps - ref_chosen_logps) | |
| rejected_rewards = beta * (policy_rejected_logps - ref_rejected_logps) | |
| reward_accuracy = (chosen_rewards > rejected_rewards).float().mean() | |
| metrics = { | |
| "reward_accuracy": reward_accuracy.detach().item(), | |
| "chosen_reward": chosen_rewards.mean().detach().item(), | |
| "rejected_reward": rejected_rewards.mean().detach().item(), | |
| "margin": (chosen_rewards - rejected_rewards).mean().detach().item(), | |
| } | |
| return losses.mean(), metrics | |