Skip to content

Commit bf9a3cb

Browse files
committed
Convert cached float8 predictions before NumPy evaluation
1 parent 41f9d39 commit bf9a3cb

2 files changed

Lines changed: 47 additions & 4 deletions

File tree

‎src/transformers/trainer_pt_utils.py‎

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -162,10 +162,8 @@ def nested_numpify(tensors):
162162
return type(tensors)({k: nested_numpify(t) for k, t in tensors.items()})
163163

164164
t = tensors.cpu()
165-
if t.dtype == torch.bfloat16:
166-
# As of Numpy 1.21.4, NumPy does not support bfloat16 (see
167-
# https://github.com/numpy/numpy/blob/a47ecdea856986cd60eabbd53265c2ca5916ad5d/doc/source/user/basics.types.rst ).
168-
# Until Numpy adds bfloat16, we must convert float32.
165+
if t.dtype == torch.bfloat16 or (t.is_floating_point() and t.element_size() == 1):
166+
# NumPy does not support bfloat16 or float8 dtypes.
169167
t = t.to(torch.float32)
170168
return t.numpy()
171169

‎tests/trainer/test_trainer_evaluation.py‎

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,51 @@ def test_predict(self):
149149
self.assertTrue(np.array_equal(labels[0], trainer.eval_dataset.ys[0]))
150150
self.assertTrue(np.array_equal(labels[1], trainer.eval_dataset.ys[1]))
151151

152+
def test_predict_preprocessed_float8_logits(self):
153+
dtypes = (
154+
torch.float8_e4m3fn,
155+
torch.float8_e4m3fnuz,
156+
torch.float8_e5m2,
157+
torch.float8_e5m2fnuz,
158+
torch.bfloat16,
159+
torch.float32,
160+
torch.float64,
161+
)
162+
for dtype in dtypes:
163+
for accumulation_steps in (None, 1):
164+
with self.subTest(dtype=dtype, accumulation_steps=accumulation_steps):
165+
with tempfile.TemporaryDirectory() as tmp_dir:
166+
trainer = get_regression_trainer(
167+
a=1.5,
168+
b=2.5,
169+
double_output=True,
170+
eval_len=7,
171+
per_device_eval_batch_size=3,
172+
eval_accumulation_steps=accumulation_steps,
173+
preprocess_logits_for_metrics=lambda logits, labels: tuple(t.to(dtype) for t in logits),
174+
compute_metrics=lambda output: {"prediction_mean": output.predictions[0].mean().item()},
175+
output_dir=tmp_dir,
176+
report_to=[],
177+
)
178+
raw = torch.from_numpy(1.5 * trainer.eval_dataset.x + 2.5)
179+
expected = raw.to(dtype)
180+
if dtype != torch.float64:
181+
expected = expected.float()
182+
expected = expected.numpy()
183+
184+
output = trainer.predict(trainer.eval_dataset)
185+
self.assertIsInstance(output.predictions, tuple)
186+
self.assertEqual(len(output.predictions), 2)
187+
for predictions in output.predictions:
188+
self.assertEqual(predictions.dtype, expected.dtype)
189+
np.testing.assert_array_equal(predictions, expected)
190+
np.testing.assert_array_equal(output.label_ids, trainer.eval_dataset.ys[0])
191+
self.assertEqual(output.metrics["test_prediction_mean"], expected.mean().item())
192+
193+
metrics = trainer.evaluate()
194+
self.assertEqual(metrics["eval_prediction_mean"], expected.mean().item())
195+
self.assertAlmostEqual(metrics["eval_loss"], output.metrics["test_loss"], places=6)
196+
152197
def test_train_and_predict_loss_parity(self):
153198
"""
154199
Tests that the loss computed during a training_step is the same as the one computed during prediction_step.

0 commit comments

Comments
 (0)