TF keras.utils.Sequence first batch called twice

20 Views Asked by At

While working on a data loader for a Keras deep learning model, I added some print statements in the get_item method of the data loader. This method is in charge of returning the n-th batch to the model. On this simple example, I expected the first batch to be logged once, on call. BUT the first batch is logged twice, on model.fit/model.predict.

I added

  • a print, which triggers twice on the first batch
  • a callback "on_batch_end", which triggers only once as expected... Is the data loader called (before prediction) by the model to set things up ?
import numpy as np
from keras.callbacks import Callback
from tensorflow import keras


class MyBatchCallback(Callback):
    def on_batch_end(self, batch, logs=None):
        # Your code to be executed at the end of each batch
        print(f"At the end of batch {batch}")


# Create a custom data sequence class by inheriting from keras.utils.Sequence
class MyDataSequence(keras.utils.Sequence):
    def __init__(self, x_set, y_set, batch_size):
        self.x, self.y = x_set, y_set
        self.batch_size = batch_size

    def __len__(self):
        return int(np.ceil(len(self.x) / self.batch_size))

    def __getitem__(self, idx):
        print(f"------------ Batch {idx}")
        start_idx = idx * self.batch_size
        end_idx = (idx + 1) * self.batch_size
        batch_x = self.x[start_idx:end_idx]
        batch_y = self.y[start_idx:end_idx]
        return np.array(batch_x), np.array(batch_y)


# Example usage
# Generate some dummy data
x_train = np.random.random((100, 32))
y_train = keras.utils.to_categorical(
    np.random.randint(10, size=(100, 1)), num_classes=10
)

# Set batch size
batch_size = 32

# Create an instance of your custom data sequence
data_sequence = MyDataSequence(x_train, y_train, batch_size)

# Create a simple model for illustration purposes
model = keras.models.Sequential()
model.add(keras.layers.Dense(64, activation="relu", input_dim=32))
model.add(keras.layers.Dense(10, activation="softmax"))

# Compile the model
model.compile(optimizer="adam", loss="categorical_crossentropy", metrics=["accuracy"])

# Train the model using the data sequence
model.fit(data_sequence, verbose=0, shuffle=False, callbacks=[MyBatchCallback()])


Console

------------ Batch 0
2024-01-24 09:35:11.573324: W tensorflow/core/platform/profile_utils/cpu_utils.cc:128] Failed to get CPU frequency: 0 Hz
2024-01-24 09:35:11.706627: I tensorflow/core/grappler/optimizers/custom_graph_optimizer_registry.cc:113] Plugin optimizer for device_type GPU is enabled.
------------ Batch 0
------------ Batch 1
At the end of batch 0
------------ Batch 2
At the end of batch 1
------------ Batch 3
At the end of batch 2
At the end of batch 3

TF 2.15.0 (Colab) Re-running the fit/predict, w/o re-init the model doesn't change the behavior. It seems that the first call happens a bit earlier than the others, my intuition is that it is needed to build the NN, but I don't see any reference to this on the internet. Any clues why?

0

There are 0 best solutions below