definition of an epoch in the fit method in keras I understand that one epoch is one pass through the training data. I'm training a CNN using the following lines of code
cnn = tf.keras.models.Sequential()
# ... code to define network layers ..
cnn.compile(optimizer = 'adam', loss = 'binary_crossentropy', metrics = ['accuracy'])
cnn.fit(x = training_set, validation_data = test_set, epochs = 2)

training_set was generated using
train_datagen = ImageDataGenerator(rescale = 1./255,
                                   shear_range = 0.2,
                                   zoom_range = 0.2,
                                   horizontal_flip = True)
training_set = train_datagen.flow_from_directory('dataset/training_set_cut',
                                                 target_size = (64, 64),
                                                 batch_size = 32,
                                                 class_mode = 'binary')

And test_set was generated using similar code. training_set and test_set seem to be generators which never stop yielding or raise StopIteration. If that is the case, then how does cnn.fit know that one epoch has been completed?
 A: In Keras, generators generate infinitely many elements. In order to define what an epoch is, you have to tell the generator when it should yield. This can be done with steps_per_epochand epochs in the model.fit call. From the Keras documentation, here is an example how you train a model with generators:
(x_train, y_train), (x_test, y_test) = cifar10.load_data()
y_train = utils.to_categorical(y_train, num_classes)
y_test = utils.to_categorical(y_test, num_classes)
datagen = ImageDataGenerator(
    featurewise_center=True,
    featurewise_std_normalization=True,
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True)
# compute quantities required for featurewise normalization
# (std, mean, and principal components if ZCA whitening is applied)
datagen.fit(x_train)
# fits the model on batches with real-time data augmentation:
model.fit(datagen.flow(x_train, y_train, batch_size=32),
          steps_per_epoch=len(x_train) / 32, epochs=epochs)

Manually, you only generate as many images as you want per generator (using e.g. zip if you have multiple generators) and from the same source we get:
for e in range(epochs):
    print('Epoch', e)
    batches = 0
    for x_batch, y_batch in datagen.flow(x_train, y_train, batch_size=32):
        model.fit(x_batch, y_batch)
        batches += 1
        if batches >= len(x_train) / 32:
            # we need to break the loop by hand because
            # the generator loops indefinitely
            break


Both examples are taken verbatim from here
