4

I'm trying to implement a Convolutional Neural Network using Keras and Tensorflow.

I have the following code:

from keras.models import Sequential
from keras.layers import Conv2D, MaxPooling2D
from keras.layers import Activation, Dropout, Flatten, Dense

model = Sequential()
model.add(Conv2D(32, (2, 2), input_shape=(3, 150, 150), padding='SAME'))
model.add(Activation('relu'))
# model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))

model.add(Conv2D(32, (2, 2), padding='SAME'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))

model.add(Conv2D(64, (2, 2), padding='SAME'))
model.add(Activation('relu'))
model.add(MaxPooling2D(pool_size=(2, 2), data_format="channels_first"))

print("after declaring models")

model.add(Flatten())  # this converts our 3D feature maps to 1D feature vectors
model.add(Dense(64))
model.add(Activation('relu'))
model.add(Dropout(0.5))
model.add(Dense(1))
model.add(Activation('sigmoid'))

model.compile(loss='binary_crossentropy',
              optimizer='rmsprop',
              metrics=['accuracy'])

print("After creating the model\n")


batch_size = 16

# this is the augmentation configuration we will use for training
train_datagen = ImageDataGenerator(
        rescale=1./255,
        shear_range=0.2,
        zoom_range=0.2,
        horizontal_flip=True)

# this is the augmentation configuration we will use for testing:
# only rescaling
test_datagen = ImageDataGenerator(rescale=1./255)

# this is a generator that will read pictures found in
# subfolers of 'data/train', and indefinitely generate
# batches of augmented image data
train_generator = train_datagen.flow_from_directory(
        '../input/train',  # this is the target directory
        target_size=(150, 150),  # all images will be resized to 150x150
        batch_size=batch_size,
        class_mode='binary')  # since we use binary_crossentropy loss, we need binary labels            

model.fit_generator(
        train_generator,
        steps_per_epoch=2000 // batch_size,
        epochs=50)

The problem is that on the last line I get:

Epoch 1/50
17.3s
6
Exception in thread Thread-20:
Traceback (most recent call last):
  File "/opt/conda/lib/python3.6/threading.py", line 916, in _bootstrap_inner
    self.run()
  File "/opt/conda/lib/python3.6/threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "/opt/conda/lib/python3.6/site-packages/Keras-2.0.5-py3.6.egg/keras/utils/data_utils.py", line 590, in data_generator_task
    generator_output = next(self._generator)
  File "/opt/conda/lib/python3.6/site-packages/Keras-2.0.5-py3.6.egg/keras/preprocessing/image.py", line 737, in __next__
    return self.next(*args, **kwargs)
  File "/opt/conda/lib/python3.6/site-packages/Keras-2.0.5-py3.6.egg/keras/preprocessing/image.py", line 1026, in next
    index_array, current_index, current_batch_size = next(self.index_generator)
  File "/opt/conda/lib/python3.6/site-packages/Keras-2.0.5-py3.6.egg/keras/preprocessing/image.py", line 720, in _flow_index
    current_index = (self.batch_index * batch_size) % n
ZeroDivisionError: integer division or modulo by zero

17.3s
7
Traceback (most recent call last):
  File "../src/script.py", line 115, in <module>
    epochs=50)
  File "/opt/conda/lib/python3.6/site-packages/Keras-2.0.5-py3.6.egg/keras/legacy/interfaces.py", line 87, in wrapper
  File "/opt/conda/lib/python3.6/site-packages/Keras-2.0.5-py3.6.egg/keras/models.py", line 1117, in fit_generator
  File "/opt/conda/lib/python3.6/site-packages/Keras-2.0.5-py3.6.egg/keras/legacy/interfaces.py", line 87, in wrapper
  File "/opt/conda/lib/python3.6/site-packages/Keras-2.0.5-py3.6.egg/keras/engine/training.py", line 1809, in fit_generator
StopIteration

How can there be a division by 0? I don't see how any of the variables can be 0.

bsky
  • 19,326
  • 49
  • 155
  • 270

2 Answers2

14

Division by zero comes from the fact that n is equal to zero. n is the total number of samples in the dataset to loop over, so it means that your image generator fails to provide any data. Most probably this is caused by the way how your training data is arranged. Keras expects images to be arranged in a directory containing one subdirectory per image class, like

input/
    train/
        class_0/
            class_0_0.jpg
            class_0_1.jpg
            ...
        class_1/
            class_1_0.jpg
            class_1_1.jpg
            ...
        ...

Note that this applies even for non-classification tasks. flow_from_directory would still expect a directory that contains a subdirectory with images when class_mode is None.

Sergii Gryshkevych
  • 4,029
  • 1
  • 25
  • 42
  • 1
    My folder structure doesn't have subfolders like these. All the images are in one folder. The labels corresponding to each image are written in a separate file. How can i adapt my file structure such that I can use it with Keras? – bsky Jul 10 '17 at 12:38
  • Well, current version of `ImageDataGenerator` won't work correctly with your set-up. You will have to either arrange your images in subdirectories, or write a custom generator. – Sergii Gryshkevych Jul 10 '17 at 12:44
  • Is there an alternative to `ImageDataGenerator`? – bsky Jul 10 '17 at 13:14
  • You can use `fit` instead of `fit_generator`. In that case input is provided as numpy arrays. This depends, of course, on the size of your training set. – Sergii Gryshkevych Jul 10 '17 at 13:18
  • I got a divide by zero error in keras classification problem with n_jobs=8 on GridSearchCV for wide hyperparameters range like epochs [100,200...1000], batch_size [100,200...1000] and full set of activation function, optimizers, etc...., my dataset is small, having 952 records which then split to 80:20, whether smaller data is a reason for that? – hanzgs Aug 26 '21 at 02:43
  • Same worked for n_jobs=1, whether smaller dataset is the issue – hanzgs Aug 26 '21 at 03:13
0

My case was slightly different, but as was the case with your error message, the answer was in the message. My problem was in the Tensorboard callback. I tried to disabled it with update_freq=0:

tf.keras.callbacks.TensorBoard(
        log_dir=logdir,
        update_freq=0)

which gave me the error message:

if self.update_freq != 'epoch' and batch % self.update_freq == 0:
ZeroDivisionError: integer division or modulo by zero

And the giveaway was in batch % self.update_freq == 0.

After reading the docs for Tensorboard callback I realized I was using an invalid value.

rodrigo-silveira
  • 12,607
  • 11
  • 69
  • 123