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?