Skip to content

Fix CANINE fp16 dtype mismatch in attention mask causing ONNX export failure#47083

Merged
Rocketknight1 merged 1 commit into
huggingface:mainfrom
lcheng321:fix-canine-fp16-clean
Jul 6, 2026
Merged

Fix CANINE fp16 dtype mismatch in attention mask causing ONNX export failure#47083
Rocketknight1 merged 1 commit into
huggingface:mainfrom
lcheng321:fix-canine-fp16-clean

Conversation

@lcheng321

@lcheng321 lcheng321 commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

CI

Fixes #47050

Problem

_create_3d_attention_mask_from_input_mask() always builds the mask in float32 through hardcoded .float() and dtype=torch.float32, ignoring the model dtype. In CanineSelfAttention.forward() the ndim==3 branch adds this float32 mask to attention_scores. When the model runs in float16 the addition promotes attention_scores to float32. After softmax attention_probs stays float32 while value_layer is still float16, so the final matmul crashes. Only the shallow character encoders hit this. The deep encoder uses create_bidirectional_mask() which is already dtype aware.

Fix

One line in CanineSelfAttention.forward():

- attention_scores = attention_scores + attention_mask
+ attention_scores = attention_scores + attention_mask.to(attention_scores.dtype)

Reproduction

import torch
from transformers import CanineModel, CanineTokenizer

tok = CanineTokenizer.from_pretrained("google/canine-s")
inputs = tok("hello world", return_tensors="pt")

model = CanineModel.from_pretrained("google/canine-s").half().eval()

torch.onnx.export(
    model,
    (inputs["input_ids"], inputs["attention_mask"]),
    "/tmp/canine_fp16.onnx",
    input_names=["input_ids", "attention_mask"],
    output_names=["last_hidden_state"],
    opset_version=17,
)

Before

Runtime dtype trace at the crash point:

attention_scores before mask add : torch.float16
attention_mask (3D path)         : torch.float32
attention_scores after mask add  : torch.float32   <- promoted
attention_probs after softmax    : torch.float32
value_layer                      : torch.float16   <- mismatch

Result:

RuntimeError: expected scalar type Float but found Half
  File ".../models/canine/modeling_canine.py", line 353, in forward
    context_layer = torch.matmul(attention_probs, value_layer)

ONNX export never completes.

After

Same trace with the fix applied:

attention_scores before mask add : torch.float16
attention_mask after .to()       : torch.float16
attention_scores after mask add  : torch.float16
attention_probs after softmax    : torch.float16
value_layer                      : torch.float16   <- ok

Result:

ONNX export: succeeded

No crash. The dtype stays float16 through the whole attention path.

Numerical check

fp16 output compared against the fp32 baseline on cpu, same input:

max abs diff  : 0.007903
mean abs diff : 0.001273
any NaN       : False

Difference is within normal fp16 tolerance. The output is not corrupted.

Tests

Added test_model_fp16_with_attention_mask to CanineModelTest. It builds the model from config only, no pretrained weights, calls .half(), forces partial masking to hit the 3D mask path, and asserts the output dtype is float16 with no NaN.

Full file result:

66 passed, 137 skipped, 3 xfailed, 0 failed

Existing test_onnx_export_* and test_torch_export_* still pass, so the change introduces no regression in the export paths.

Out of scope

A second independent issue exists, a device mismatch in _repeat_molecules() that becomes visible only after this dtype fix. It is noted in #47050 and left for a follow up PR.

…rward

_create_3d_attention_mask_from_input_mask() always constructs the mask
in float32 via hardcoded .float() calls, regardless of model dtype.
When the model runs in float16, adding this float32 mask to float16
attention_scores promotes them to float32. After softmax, attention_probs
stays float32 while value_layer remains float16, causing:

  RuntimeError: expected scalar type Float but found Half

Fix: cast attention_mask to attention_scores.dtype before the addition.
Only affects the shallow character encoders (ndim==3 mask path).

Fixes huggingface#47050
@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

[For maintainers] Suggested jobs to run (before merge)

run-slow: canine

@github-actions

github-actions Bot commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

CI recap

Dashboard: View test results in Grafana
Latest run: 28732666907:2
Result: success | Jobs: 2 | Tests: 8 | Failures: 0 | Duration: 36s

@Rocketknight1 Rocketknight1 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

It's a code agent PR but I'll allow it because I think the bug is real here.

@Rocketknight1 Rocketknight1 enabled auto-merge July 6, 2026 13:30
@Rocketknight1 Rocketknight1 added this pull request to the merge queue Jul 6, 2026
@HuggingFaceDocBuilderDev

Copy link
Copy Markdown

The docs for this PR live here. All of your documentation changes will be reflected on that endpoint. The docs are available until 30 days after the last update.

Merged via the queue into huggingface:main with commit 1da9d1d Jul 6, 2026
37 checks passed
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.

CanineModel fp16 ONNX export fails with dtype mismatch in attention (expected scalar type Float but found Half)

3 participants