#23660·keras

Torch backend: `binary_crossentropy` with an integer target stops the Python process on MPS

Author: JyotinderSinghCreated Sep 16, 2026Updated Sep 16, 2026
Labelstype:Bugbackend:torch

Description

On the Torch backend with the MPS device, keras.ops.binary_crossentropy stops the Python process when the target has an integer dtype and from_logits=False. The process stops with SIGABRT (exit code 134 in a shell). Keras does not raise a Python exception. A try block cannot catch this failure.

The example in the keras.ops.binary_crossentropy docstring (keras/src/ops/nn.py) uses an integer target. This example stops the process on MPS.

Procedure

Run this code on an Apple silicon Mac:

import os

os.environ["KERAS_BACKEND"] = "torch"

import keras

target = keras.ops.convert_to_tensor([0, 1, 1, 0])
output = keras.ops.convert_to_tensor([0.1, 0.9, 0.8, 0.2])
print(keras.ops.binary_crossentropy(target, output))

Actual result

The process stops. The last lines of the output are:

error: 'mps.subtract' op requires the same element type for all operands and results
failed assertion `original module failed verification'

Expected result

keras.ops.binary_crossentropy returns the loss or raises a Python exception. The process does not stop.

Results on other backends and devices

Backend Device Result
JAX CPU Returns [0.1054, 0.1054, 0.2231, 0.2231]
NumPy CPU Returns [0.1054, 0.1054, 0.2231, 0.2231]
TensorFlow CPU Raises InvalidArgumentError
Torch CPU Raises RuntimeError: Found dtype Int but expected Float
Torch MPS Stops the process

These related cases also occur on the Torch backend:

  • A bool target on MPS returns the loss. The same target on CPU raises RuntimeError: Found dtype Bool but expected Float.
  • With from_logits=True, an integer target on MPS raises a RuntimeError. The process does not stop.
  • keras.losses.binary_crossentropy casts y_true to the dtype of y_pred. This function does not have the problem.

Cause

binary_crossentropy in keras/src/backend/torch/nn.py does not cast target to the dtype of output. The function sends the integer tensor to torch.nn.functional.binary_cross_entropy. On MPS, this PyTorch kernel does not check the dtype of the target. MPSGraph then fails an internal assertion, and the process stops.

The same failure occurs without Keras:

import torch
import torch.nn.functional as F

output = torch.tensor([0.1, 0.9, 0.8, 0.2], device="mps")
target = torch.tensor([0, 1, 1, 0], device="mps")
F.binary_cross_entropy(output, target, reduction="none")  # The process stops.

PR #23633 changes this function. The failure also occurs with the change from that PR.

Possible fix

Cast target to output.dtype at the start of the Torch binary_crossentropy. The JAX and NumPy backends accept integer targets. With this cast, the Torch backend gives the same result.

Environment

  • Keras: master at 32530b6ed
  • PyTorch: 2.10.0
  • Python: 3.12.12
  • macOS 26.6.2 on an Apple M1 Pro