Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

add confidence weighted CE (DFT) as fused loss function#903

Open
0xEljh wants to merge 6 commits into
unslothai:mainunslothai/unsloth-zoo:mainfrom
0xEljh:feat/fused-dft0xEljh/unsloth-zoo:feat/fused-dftCopy head branch name to clipboard
Open

add confidence weighted CE (DFT) as fused loss function#903
0xEljh wants to merge 6 commits into
unslothai:mainunslothai/unsloth-zoo:mainfrom
0xEljh:feat/fused-dft0xEljh/unsloth-zoo:feat/fused-dftCopy head branch name to clipboard

Conversation

@0xEljh

@0xEljh 0xEljh commented Jul 13, 2026

Copy link
Copy Markdown

Summary

Dynamic Fine-Tuning (DFT) has already been added to TRL and is accessible by setting loss_type="dft" in the SFTTrainer. But doing so would currently deviate from the unsloth memory optimized path.

This PR adds DFT fused loss support for using the existing chunked fused-loss infrastructure. It is the first in a planned series of PRs to add support for RL x SFT hybrid losses as initially attempted in this PR in the main unsloth repo.

DFT weights each token’s negative log-likelihood by its detached predicted probability:
$$\text{sg}(\exp(-NLL_t)) * NLL_t$$

This reduces the contribution of low-confidence (high surprise) tokens while preserving the intended detached-weight gradient behavior.

Notably, this isn't just a matter of passing a scaling to fused CE, as access to the per-token $$NLL$$ is required.

Creating this PR in unsloth-zoo first before patching unsloth.

Changes

  • Add compute_fused_dft_loss for direct DFT loss computation.
  • Add unsloth_fused_dft_loss using the existing UnslothFusedLoss autograd and chunking path.
  • Mimic as much of the base fused_ce_loss behavior as possible:
    • automatic and explicit chunk sizing
    • shifted and pre-shifted labels
    • masking and custom ignore_index
    • mixed-precision loss scaling
    • logit scaling and soft-capping
    • eager and torch.compile execution
    • optional LM-head bias
  • Export unsloth_fused_dft_loss through loss_utils.
  • Prevent CE compile success from treating DFT’s first compiled execution as already proven. Compile failures remain process-wide and disable subsequent fused-loss compilation.
  • Reject non-zero label smoothing, which is not currently supported for DFT.
  • Add the DFT test suite as a CI hard gate.

For the purpose of this PR, we intentionally avoid doing anything to compute_fused_ce_loss and instead duplicate most of its behavior into compute_fused_dft_loss.

Testing

Correctness

Correctness tests are in tests/test_fused_dft_loss.py.

Most notable are

  • tests/test_fused_dft_loss.py::test_compute_dft_minus_p_log_p_shape
  • tests/test_fused_dft_loss.py::test_compute_dft_single_token_closed_form_loss_and_gradient
  • tests/test_fused_dft_loss.py::test_unsloth_fused_dft_compiled_parity_and_probe_success
  • Other tests cover chunking, label shifts/masking, ignored rows

Compilation

DFT compiled successfully on:

PyTorch 2.12.1+cu130
Triton 3.7.1
unique_graphs=1
graph_break_count=0
recompilation_count_from_guard_failures=0
Full compilation test
print(
    "COMPILE_OPTIONS_JSON="
    + json.dumps(cross_entropy_loss.torch_compile_options, sort_keys=True)
)

torch._dynamo.reset()
torch._dynamo.utils.counters.clear()
torch._dynamo.utils.guard_failures.clear()
cross_entropy_loss._FUSED_CE_COMPILE_SUPPORTED = None
cross_entropy_loss._FUSED_CE_COMPILE_FASTPATH_PROVEN.clear()

# Two equal chunks exercise one compiled accumulate_chunk region twice. Each
# chunk has one valid and one ignored row. All inputs are finite, but the
# ignored rows overflow in linear(), which makes the sanitizer observable.
hidden_states = torch.tensor(
    [[[2.0e-20, -1.0e-20], [1.0e20, -1.0e20],
      [1.5e-20, -0.5e-20], [1.0e20, -1.0e20]]],
    dtype=torch.float32,
    device="cuda",
    requires_grad=True,
)
lm_head_weight = torch.tensor(
    [[1.0e20, 0.0], [0.0, 1.0e20], [-1.0e20, 1.0e20]],
    dtype=torch.float32,
    device="cuda",
    requires_grad=True,
)
lm_head_bias = torch.tensor(
    [0.1, -0.2, 0.3],
    dtype=torch.float32,
    device="cuda",
    requires_grad=True,
)
labels = torch.tensor([[1, -100, 1, -100]], device="cuda")

with torch.no_grad():
    raw_logits = torch.nn.functional.linear(
        hidden_states,
        lm_head_weight,
        lm_head_bias,
    )
print("RAW_LOGITS=" + repr(raw_logits.detach().cpu().tolist()))

loss = cross_entropy_loss.unsloth_fused_dft_loss(
    trainer=None,
    hidden_states=hidden_states,
    lm_head_weight=lm_head_weight,
    lm_head_bias=lm_head_bias,
    labels=labels,
    shift_labels=False,
    torch_compile=True,
    n_chunks=2,
)
torch.cuda.synchronize()
loss.backward()
torch.cuda.synchronize()

guard_failures = {
    str(code): [str(failure) for failure in failures]
    for code, failures in torch._dynamo.utils.guard_failures.items()
    if failures
}
counters = json_counters()
graph_break_count = sum(counters.get("graph_break", {}).values())
recompilation_count = sum(len(failures) for failures in guard_failures.values())

result = {
    "loss": float(loss.detach().cpu()),
    "compile_supported": cross_entropy_loss._FUSED_CE_COMPILE_SUPPORTED,
    "fastpath_proven": (
        cross_entropy_loss.compute_fused_dft_loss
        in cross_entropy_loss._FUSED_CE_COMPILE_FASTPATH_PROVEN
    ),
    "hidden_grad_finite": bool(torch.isfinite(hidden_states.grad).all()),
    "weight_grad_finite": bool(torch.isfinite(lm_head_weight.grad).all()),
    "bias_grad_finite": bool(torch.isfinite(lm_head_bias.grad).all()),
    "ignored_hidden_grad_zero": bool(
        torch.count_nonzero(hidden_states.grad[0, [1, 3]]) == 0
    ),
    "graph_break_count": graph_break_count,
    "recompilation_count_from_guard_failures": recompilation_count,
    "guard_failures": guard_failures,
    "counters": counters,
}
print("RESULT_JSON=" + json.dumps(result, sort_keys=True))
COMPILE_OPTIONS_JSON={"benchmark_combo_kernel": true, "combo_kernel_foreach_dynamic_shapes": true, "combo_kernels": false, "compile_threads": 16, "coordinate_descent_tuning": false, "cuda.compile_opt_level": "-O2", "cuda.enable_cuda_lto": true, "dce": true, "debug": true, "disable_progress": true, "epilogue_fusion": true, "group_fusion": true, "max_autotune": false, "memory_planning": false, "shape_padding": true, "trace.enabled": true, "trace.graph_diagram": true, "triton.autotune_at_compile_time": false, "triton.cooperative_reductions": false, "triton.cudagraphs": false, "triton.enable_persistent_tma_matmul": true, "triton.multi_kernel": 0, "triton.use_block_ptr": false, "verbose_progress": false}
RAW_LOGITS=[[[2.0999999046325684, -1.2000000476837158, -2.700000047683716], [inf, -inf, -inf], [1.600000023841858, -0.699999988079071, -1.7000000476837158], [inf, -inf, -inf]]]
RESULT_JSON={"bias_grad_finite": true, "compile_supported": true, "counters": {"aot_autograd": {"autograd_cache_miss": 1, "autograd_cache_saved": 1, "ok": 1, "total": 1}, "aten_mm_info": {"aten.mm_s19_s19_s55": 1, "aten.mm_s19_s55_s19": 1, "aten.mm_s55_s19_s19": 1}, "inductor": {"async_compile_cache_hit": 6, "async_compile_cache_miss": 12, "benchmarking.InductorBenchmarker.benchmark": 5, "benchmarking.InductorBenchmarker.benchmark_gpu": 5, "extern_calls": 3, "fxgraph_cache_miss": 1, "pattern_matcher_count": 7, "pattern_matcher_nodes": 12, "triton_bundler_save_kernel": 72, "triton_bundler_save_static_autotuner": 1}, "stats": {"calls_captured": 59, "unique_graphs": 1}}, "fastpath_proven": true, "graph_break_count": 0, "guard_failures": {}, "hidden_grad_finite": true, "ignored_hidden_grad_zero": true, "loss": 0.1660669595003128, "recompilation_count_from_guard_failures": 0, "weight_grad_finite": true}

Future Work

  • Compose DFT around CCE
  • Update unsloth so loss_type=dft on SFTTrainer routes through this change.
  • Add loss_type=asft

@0xEljh
0xEljh requested a review from danielhanchen as a code owner July 13, 2026 08:55

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a new fused DFT loss function (unsloth_fused_dft_loss and compute_fused_dft_loss) to the Unsloth Zoo, along with comprehensive unit tests to verify its correctness, gradient behavior, and compilation compatibility. The feedback suggests optimizing the DFT loss implementation by removing redundant .contiguous() calls, using reshape for safer layout handling, and replacing a 0-D tensor allocation in torch.where with a scalar 0.0 to reduce GPU overhead.

Important

The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.

Comment thread unsloth_zoo/fused_losses/cross_entropy_loss.py Outdated

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: ff710d2463

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread unsloth_zoo/fused_losses/cross_entropy_loss.py
Comment thread unsloth_zoo/fused_losses/cross_entropy_loss.py Outdated
Comment thread unsloth_zoo/fused_losses/cross_entropy_loss.py
Comment thread unsloth_zoo/fused_losses/cross_entropy_loss.py
@Etherll

Etherll commented Jul 15, 2026

Copy link
Copy Markdown
Contributor

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. 🎉

Reviewed commit: 0f8b5f1a34

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@0xEljh

0xEljh commented Jul 15, 2026

Copy link
Copy Markdown
Author

@codex review

@chatgpt-codex-connector

Copy link
Copy Markdown

Codex Review: Didn't find any major issues. Bravo.

Reviewed commit: 23b75c558a

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

@0xEljh 0xEljh changed the title add dft as fused loss function add confidence weighted CE (DFT) as fused loss function Jul 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

Morty Proxy This is a proxified and sanitized view of the page, visit original site.