While trying to author a subclass of PyDataset, I found that __getitem__()
must return a dictionary with named values, otherwise an unrelated error is given. In hind sight, this is obvious, but the error message led to hours of wasted debugging in the wrong places.
Attached is a small patch that demonstrates the problem on latest master: demonstrate-named-inputs-without-warning.patch.txt
The error looks like this:
Traceback (most recent call last):
File "<path>/keras/integration_tests/./tf_distribute_training_test.py", line 90, in <module>
test_model_fit()
File "<path>/keras/integration_tests/./tf_distribute_training_test.py", line 74, in test_model_fit
history = model.fit(dataset, epochs=epochs, callbacks=callbacks)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "<path>/keras/env/lib/python3.11/site-packages/keras/src/utils/traceback_utils.py", line 123, in error_handler
raise e.with_traceback(filtered_tb) from None
File "/tmp/__autograph_generated_fileczxvauzh.py", line 14, in tf__wrapped_fn
retval_ = ag__.converted_call(ag__.ld(call_for_each_replica), (ag__.ld(strategy), ag__.ld(fn).python_function, ag__.ld(args), ag__.ld(kwargs)), None, fscope)
^^^^^
ValueError: in user code:
File "<path>/keras/env/lib/python3.11/site-packages/keras/src/backend/tensorflow/trainer.py", line 105, in one_step_on_data **
return self.train_step(data)
File "<path>/keras/env/lib/python3.11/site-packages/keras/src/backend/tensorflow/trainer.py", line 59, in train_step
loss = self.compute_loss(
File "<path>/keras/env/lib/python3.11/site-packages/keras/src/trainers/trainer.py", line 327, in compute_loss
raise ValueError(
ValueError: No loss to compute. Provide a `loss` argument in `compile()`.
loss
is clearly provided in compile()
which leads to a wild goose chase.
If you remove name="inputs"
such as what you see in the commented out line, you get a related warning that is similar to what you would expect for this case:
<path>/keras/env/lib/python3.11/site-packages/keras/src/models/functional.py:104: UserWarning: When providing `inputs` as a dict, all keys in the dict must match the names of the corresponding tensors. Received key 'inputs' mapping to value <KerasTensor shape=(32, 100
), dtype=float32, sparse=None, name=keras_tensor> which has name 'keras_tensor'. Change the tensor name to 'inputs' (via `Input(..., name='inputs')`)
A warning like that could be given when the dataset provided to fit() contains unnamed inputs/outputs.
Comment From: jasonbcox
Relatedly, it's not clear what that named dataset should look like. Attempts at reimplementing __getitem__()
give off various related errors:
def __getitem__(self, index):
return {"inputs": self.x[index * self.batch_size:(index+1) * self.batch_size], "outputs": self.y[index * self.batch_size:(index+1) * self.batch_size]}
def __getitem__(self, index):
return map(lambda x, y: {"inputs": x, "outputs": y}, zip(self.x[index * self.batch_size:(index+1) * self.batch_size], self.y[index * self.batch_size:(index+1) * self.batch_size]))
I would expect at least one of these to work, modeling it off of the documentation here: https://keras.io/examples/keras_recipes/packaging_keras_models_for_wide_distribution/#model-with-dictionary-inputs
Comment From: dhantule
Hi @jasonbcox, thanks for reporting this.
Can you provide a colab with the reproducible code ?